[Spice-commits] 336 commits - .gitignore Makefile Makefile.hw Makefile.objs Makefile.target QMP/README QMP/qmp-spec.txt QMP/vm-info aio.c arch_init.c audio/audio_template.h block.c block.h block/blkdebug.c block/curl.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2.c block/qcow2.h block/raw-posix.c block/vvfat.c blockdev.c blockdev.h bsd-user/main.c bswap.h check-qdict.c check-qfloat.c check-qint.c check-qjson.c check-qlist.c check-qstring.c configure console.c console.h cpu-all.h cpu-exec.c cpus.c create_config cursor.c cursor_hidden.xpm cursor_left_ptr.xpm darwin-user/commpage.c darwin-user/syscall.c default-configs/i386-softmmu.mak default-configs/mips-softmmu.mak default-configs/mips64-softmmu.mak default-configs/mips64el-softmmu.mak default-configs/mipsel-softmmu.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/sparc64-softmmu.mak default-configs/x86_64-softmmu.mak dyngen-exec.h elf.h exec-all.h e xec.c hw/9p.h hw/acpi_piix4.c hw/apb_pci.c hw/apic.c hw/arm_boot.c hw/arm_timer.c hw/axis_dev88.c hw/cirrus_vga.c hw/cris-boot.c hw/cris-boot.h hw/device-hotplug.c hw/dma.c hw/e1000.c hw/eepro100.c hw/elf_ops.h hw/esp.c hw/etraxfs.c hw/etraxfs_ser.c hw/fdc.c hw/fdc.h hw/gt64xxx.c hw/gumstix.c hw/hpet.c hw/hpet_emul.h hw/hw.h hw/i8259.c hw/ide hw/ioapic.c hw/isa.h hw/lan9118.c hw/lsi53c895a.c hw/mainstone.c hw/mc146818rtc.c hw/mc146818rtc.h hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/msix.c hw/multiboot.c hw/musicpal.c hw/nand.c hw/nseries.c hw/omap2.c hw/omap_sx1.c hw/onenand.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/pckbd.c hw/pcmcia.h hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/piix_pci.c hw/pl181.c hw/ppc_prep.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/serial.c hw/sparc32_dma.c hw/spitz.c hw/ssi-sd.c hw/sun4m.c hw/sun4u.c hw/tosa.c hw/usb-hid.c hw/usb-msd.c hw/usb-ohci.c hw/vga-isa-mm.c hw/vga.c hw/vhost_net.c hw/virtio-blk.c hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/vmmouse.c hw/vmware_vga.c hw/xenfb.c hxtool ia64-dis.c input.c json-lexer.c json-parser.c json-streamer.c kvm.h linux-user/elfload.c linux-user/flatload.c linux-user/main.c linux-user/mmap.c linux-user/syscall.c linux-user/syscall_defs.h migration-exec.c migration-tcp.c migration.c migration.h monitor.c nbd.c nbd.h net.c net.h os-posix.c os-win32.c pc-bios/optionrom posix-aio-compat.c qbool.c qdict.c qdict.h qemu-char.c qemu-common.h qemu-config.c qemu-doc.texi qemu-img-cmds.hx qemu-img.c qemu-io.c qemu-malloc.c qemu-monitor.hx qemu-objects.h qemu-option.c qemu-option.h qemu-options.h qemu-options.hx qemu-os-posix.h qemu-os-win32.h qemu-thread.c qerror.c qerror.h qfloat.c qint.c qint.h qjson.c qlist.c qlist.h qobject.h qstring.c qstring.h rules.mak s390-dis.c savevm.c sdl.c softmmu_header.h sysemu.h t arget-arm/cpu.h target-arm/helper.c target-arm/translate.c target-cris/cpu.h target-cris/mmu.c target-cris/translate.c target-i386/cpuid.c target-i386/translate.c target-microblaze/cpu.h target-mips/cpu.h target-mips/helper.c target-mips/helper.h target-mips/mips-defs.h target-mips/op_helper.c target-mips/translate.c target-ppc/helper.c target-ppc/op_helper.c target-ppc/translate.c target-sparc/cpu.h target-sparc/helper.c target-sparc/op_helper.c target-sparc/translate.c tcg/arm tcg/hppa tcg/i386 tcg/ia64 tcg/mips tcg/ppc tcg/ppc64 tcg/s390 tcg/sparc tcg/tcg-op.h tcg/tcg-opc.h tcg/tcg.c tcg/tcg.h tcg/x86_64 translate-all.c vl.c vnc-encoding-hextile.c vnc-encoding-tight.c vnc-encoding-tight.h vnc-encoding-zlib.c vnc.c vnc.h vnchextile.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jun 15 05:04:40 PDT 2010


 .gitignore                           |    1 
 Makefile                             |   60 
 Makefile.hw                          |    2 
 Makefile.objs                        |   16 
 Makefile.target                      |   19 
 QMP/README                           |    5 
 QMP/qmp-spec.txt                     |   55 
 QMP/vm-info                          |    2 
 aio.c                                |    4 
 arch_init.c                          |   35 
 audio/audio_template.h               |    2 
 block.c                              |  219 +-
 block.h                              |    5 
 block/blkdebug.c                     |    2 
 block/curl.c                         |   14 
 block/qcow2-cluster.c                |   94 -
 block/qcow2-refcount.c               |   42 
 block/qcow2.c                        |   24 
 block/qcow2.h                        |    4 
 block/raw-posix.c                    |   20 
 block/vvfat.c                        |   10 
 blockdev.c                           |  600 ++++++
 blockdev.h                           |   71 
 bsd-user/main.c                      |   11 
 bswap.h                              |    2 
 check-qdict.c                        |    3 
 check-qfloat.c                       |    5 
 check-qint.c                         |    3 
 check-qjson.c                        |  113 +
 check-qlist.c                        |    4 
 check-qstring.c                      |    3 
 configure                            |  168 +
 console.c                            |   18 
 console.h                            |   27 
 cpu-all.h                            |   29 
 cpu-exec.c                           |   42 
 cpus.c                               |   38 
 create_config                        |   12 
 cursor.c                             |  210 ++
 cursor_hidden.xpm                    |   37 
 cursor_left_ptr.xpm                  |   39 
 darwin-user/commpage.c               |    2 
 darwin-user/syscall.c                |    2 
 default-configs/i386-softmmu.mak     |    2 
 default-configs/mips-softmmu.mak     |    2 
 default-configs/mips64-softmmu.mak   |    2 
 default-configs/mips64el-softmmu.mak |    2 
 default-configs/mipsel-softmmu.mak   |    2 
 default-configs/ppc-softmmu.mak      |    2 
 default-configs/ppc64-softmmu.mak    |    2 
 default-configs/ppcemb-softmmu.mak   |    2 
 default-configs/sparc64-softmmu.mak  |    1 
 default-configs/x86_64-softmmu.mak   |    2 
 dyngen-exec.h                        |    1 
 elf.h                                |    3 
 exec-all.h                           |    1 
 exec.c                               |   92 -
 hw/9p.h                              |    2 
 hw/acpi_piix4.c                      |   30 
 hw/apb_pci.c                         |   50 
 hw/apic.c                            |   43 
 hw/arm_boot.c                        |    1 
 hw/arm_timer.c                       |    4 
 hw/axis_dev88.c                      |   54 
 hw/cirrus_vga.c                      |    1 
 hw/cris-boot.c                       |   97 +
 hw/cris-boot.h                       |   11 
 hw/device-hotplug.c                  |    4 
 hw/dma.c                             |   17 
 hw/e1000.c                           |    4 
 hw/eepro100.c                        |    1 
 hw/elf_ops.h                         |    5 
 hw/esp.c                             |   19 
 hw/etraxfs.c                         |   55 
 hw/etraxfs_ser.c                     |   73 
 hw/fdc.c                             |    1 
 hw/fdc.h                             |    2 
 hw/gt64xxx.c                         |    2 
 hw/gumstix.c                         |    4 
 hw/hpet.c                            |  599 ++++--
 hw/hpet_emul.h                       |   57 
 hw/hw.h                              |   11 
 hw/i8259.c                           |   23 
 hw/ide/cmd646.c                      |    4 
 hw/ide/core.c                        |  108 -
 hw/ide/internal.h                    |   13 
 hw/ide/isa.c                         |    2 
 hw/ide/macio.c                       |    2 
 hw/ide/microdrive.c                  |    3 
 hw/ide/mmio.c                        |    2 
 hw/ide/piix.c                        |    4 
 hw/ide/qdev.c                        |   21 
 hw/ioapic.c                          |   16 
 hw/isa.h                             |    2 
 hw/lan9118.c                         |    1 
 hw/lsi53c895a.c                      |    4 
 hw/mainstone.c                       |    3 
 hw/mc146818rtc.c                     |   71 
 hw/mc146818rtc.h                     |    4 
 hw/mips_jazz.c                       |   15 
 hw/mips_malta.c                      |   15 
 hw/mips_mipssim.c                    |    5 
 hw/mips_r4k.c                        |    2 
 hw/msix.c                            |   17 
 hw/multiboot.c                       |    9 
 hw/musicpal.c                        |    2 
 hw/nand.c                            |    3 
 hw/nseries.c                         |    7 
 hw/omap2.c                           |    2 
 hw/omap_sx1.c                        |    5 
 hw/onenand.c                         |    3 
 hw/palm.c                            |    4 
 hw/parallel.c                        |    1 
 hw/pc.c                              |   81 
 hw/pc.h                              |    7 
 hw/pc_piix.c                         |    1 
 hw/pci-hotplug.c                     |   58 
 hw/pci.c                             |  103 -
 hw/pci.h                             |   16 
 hw/pckbd.c                           |  112 -
 hw/pcmcia.h                          |    2 
 hw/petalogix_s3adsp1800_mmu.c        |    4 
 hw/pflash_cfi01.c                    |   20 
 hw/piix_pci.c                        |    2 
 hw/pl181.c                           |    1 
 hw/ppc_prep.c                        |   17 
 hw/qdev-properties.c                 |   12 
 hw/qdev.c                            |   20 
 hw/qdev.h                            |    6 
 hw/scsi-bus.c                        |    1 
 hw/scsi-disk.c                       |   26 
 hw/scsi-generic.c                    |    1 
 hw/serial.c                          |    1 
 hw/sparc32_dma.c                     |   12 
 hw/spitz.c                           |    3 
 hw/ssi-sd.c                          |    1 
 hw/sun4m.c                           |   20 
 hw/sun4u.c                           |   12 
 hw/tosa.c                            |    3 
 hw/usb-hid.c                         |    9 
 hw/usb-msd.c                         |    4 
 hw/usb-ohci.c                        |    4 
 hw/vga-isa-mm.c                      |    6 
 hw/vga.c                             |    2 
 hw/vhost_net.c                       |    4 
 hw/virtio-blk.c                      |   89 
 hw/virtio-net.c                      |   26 
 hw/virtio-net.h                      |    4 
 hw/virtio-pci.c                      |    1 
 hw/virtio-serial-bus.c               |    3 
 hw/virtio-serial.h                   |    1 
 hw/vmmouse.c                         |    2 
 hw/vmware_vga.c                      |   40 
 hw/xenfb.c                           |    1 
 hxtool                               |   62 
 ia64-dis.c                           |    9 
 input.c                              |   24 
 json-lexer.c                         |  114 -
 json-parser.c                        |    5 
 json-streamer.c                      |    8 
 kvm.h                                |    1 
 linux-user/elfload.c                 |   24 
 linux-user/flatload.c                |    2 
 linux-user/main.c                    |   97 -
 linux-user/mmap.c                    |  172 +
 linux-user/syscall.c                 |  103 -
 linux-user/syscall_defs.h            |   10 
 migration-exec.c                     |   14 
 migration-tcp.c                      |    4 
 migration.c                          |   57 
 migration.h                          |    2 
 monitor.c                            |  230 --
 nbd.c                                |    3 
 nbd.h                                |    1 
 net.c                                |   33 
 net.h                                |    1 
 os-posix.c                           |  329 +++
 os-win32.c                           |  221 ++
 pc-bios/optionrom/linuxboot.S        |    8 
 pc-bios/optionrom/optionrom.h        |   32 
 posix-aio-compat.c                   |   58 
 qbool.c                              |    8 
 qdict.c                              |    6 
 qdict.h                              |   12 
 qemu-char.c                          |   17 
 qemu-common.h                        |    1 
 qemu-config.c                        |   14 
 qemu-doc.texi                        |    5 
 qemu-img-cmds.hx                     |    2 
 qemu-img.c                           |   59 
 qemu-io.c                            |  254 ++
 qemu-malloc.c                        |    8 
 qemu-monitor.hx                      | 1485 +++++++++++++++-
 qemu-objects.h                       |    5 
 qemu-option.c                        |   74 
 qemu-option.h                        |    2 
 qemu-options.h                       |   41 
 qemu-options.hx                      |   32 
 qemu-os-posix.h                      |   39 
 qemu-os-win32.h                      |   52 
 qemu-thread.c                        |    7 
 qerror.c                             |    2 
 qerror.h                             |    2 
 qfloat.c                             |    8 
 qint.c                               |    7 
 qint.h                               |   12 
 qjson.c                              |    3 
 qlist.c                              |    7 
 qlist.h                              |    7 
 qobject.h                            |    4 
 qstring.c                            |    7 
 qstring.h                            |   12 
 rules.mak                            |    2 
 s390-dis.c                           |  166 +
 savevm.c                             |    7 
 sdl.c                                |   56 
 softmmu_header.h                     |    2 
 sysemu.h                             |   92 -
 target-arm/cpu.h                     |   14 
 target-arm/helper.c                  |    1 
 target-arm/translate.c               |    6 
 target-cris/cpu.h                    |    2 
 target-cris/mmu.c                    |    2 
 target-cris/translate.c              |    4 
 target-i386/cpuid.c                  |   14 
 target-i386/translate.c              |    2 
 target-microblaze/cpu.h              |    9 
 target-mips/cpu.h                    |    1 
 target-mips/helper.c                 |   21 
 target-mips/helper.h                 |    9 
 target-mips/mips-defs.h              |    1 
 target-mips/op_helper.c              |  136 +
 target-mips/translate.c              | 3121 +++++++++++++++++++++++++++++++----
 target-ppc/helper.c                  |    2 
 target-ppc/op_helper.c               |    6 
 target-ppc/translate.c               |    7 
 target-sparc/cpu.h                   |   73 
 target-sparc/helper.c                |  135 +
 target-sparc/op_helper.c             |  373 ++--
 target-sparc/translate.c             |  351 ++-
 tcg/arm/tcg-target.c                 |    6 
 tcg/hppa/tcg-target.c                |   54 
 tcg/i386/tcg-target.c                | 1925 ++++++++++++++-------
 tcg/i386/tcg-target.h                |   61 
 tcg/ia64/tcg-target.c                |  206 +-
 tcg/mips/tcg-target.c                |   32 
 tcg/ppc/tcg-target.c                 |   52 
 tcg/ppc64/tcg-target.c               |   14 
 tcg/s390/tcg-target.c                |    6 
 tcg/s390/tcg-target.h                |    5 
 tcg/sparc/tcg-target.c               |   14 
 tcg/tcg-op.h                         |    8 
 tcg/tcg-opc.h                        |  293 +--
 tcg/tcg.c                            |   21 
 tcg/tcg.h                            |   18 
 tcg/x86_64/tcg-target.c              | 1454 ----------------
 tcg/x86_64/tcg-target.h              |  101 -
 translate-all.c                      |   16 
 vl.c                                 | 1031 -----------
 vnc-encoding-hextile.c               |    5 
 vnc-encoding-tight.c                 |  959 ++++++++++
 vnc-encoding-tight.h                 |  176 +
 vnc-encoding-zlib.c                  |   40 
 vnc.c                                |  220 +-
 vnc.h                                |   34 
 vnchextile.h                         |    7 
 266 files changed, 13096 insertions(+), 6543 deletions(-)

New commits:
commit fd42deeb4cb42f90084046e3ebdb4383953195e3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jun 4 14:08:07 2010 +0200

    Add exit notifiers.
    
    Hook up any cleanup work which needs to be done here.  Advantages over
    using atexit(3):
    
      (1) You get passed in a pointer to the notifier.  If you embed that
          into your state struct you can use container_of() to get get your
          state info.
      (2) You can unregister, say when un-plugging a device.
    
    [ v2: move code out of #ifndef _WIN32 ]
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/sysemu.h b/sysemu.h
index fbe103b..c758243 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -6,6 +6,7 @@
 #include "qemu-option.h"
 #include "qemu-queue.h"
 #include "qemu-timer.h"
+#include "notify.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -56,6 +57,9 @@ int qemu_powerdown_requested(void);
 extern qemu_irq qemu_system_powerdown;
 void qemu_system_reset(void);
 
+void qemu_add_exit_notifier(Notifier *notify);
+void qemu_remove_exit_notifier(Notifier *notify);
+
 void do_savevm(Monitor *mon, const QDict *qdict);
 int load_vmstate(const char *name);
 void do_delvm(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index df18198..e5e43b3 100644
--- a/vl.c
+++ b/vl.c
@@ -234,6 +234,9 @@ uint8_t qemu_uuid[16];
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
 
+static NotifierList exit_notifiers =
+    NOTIFIER_LIST_INITIALIZER(exit_notifiers);
+
 int kvm_allowed = 0;
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
@@ -1740,6 +1743,21 @@ static int debugcon_parse(const char *devname)
     return 0;
 }
 
+void qemu_add_exit_notifier(Notifier *notify)
+{
+    notifier_list_add(&exit_notifiers, notify);
+}
+
+void qemu_remove_exit_notifier(Notifier *notify)
+{
+    notifier_list_remove(&exit_notifiers, notify);
+}
+
+static void qemu_run_exit_notifiers(void)
+{
+    notifier_list_notify(&exit_notifiers);
+}
+
 static const QEMUOption *lookup_opt(int argc, char **argv,
                                     const char **poptarg, int *poptind)
 {
@@ -1804,6 +1822,7 @@ int main(int argc, char **argv, char **envp)
     int show_vnc_port = 0;
     int defconfig = 1;
 
+    atexit(qemu_run_exit_notifiers);
     error_set_progname(argv[0]);
 
     init_clocks();
commit 4cf3e6f3d85492f20a773dd6c9068ab89ba24a18
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Wed Jun 2 10:58:29 2010 -0600

    acpi_piix4: save gpe and pci hotplug slot status
    
    PCI hotplug currently doesn't work after a migration because
    we don't migrate the enable bits of the GPE state.  Pull hotplug
    structs into vmstate.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index a87286b..8d1a628 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -283,9 +283,33 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static const VMStateDescription vmstate_gpe = {
+    .name = "gpe",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT16(sts, struct gpe_regs),
+        VMSTATE_UINT16(en, struct gpe_regs),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_pci_status = {
+    .name = "pci_status",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32(up, struct pci_status),
+        VMSTATE_UINT32(down, struct pci_status),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_acpi = {
     .name = "piix4_pm",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .post_load = vmstate_acpi_post_load,
@@ -297,6 +321,9 @@ static const VMStateDescription vmstate_acpi = {
         VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
         VMSTATE_TIMER(tmr_timer, PIIX4PMState),
         VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
+        VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
+        VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
+                       struct pci_status),
         VMSTATE_END_OF_LIST()
     }
 };
commit b560a9ab9be06afcbb78b3791ab836dad208a239
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 8 13:54:26 2010 +0200

    qemu-option: Reject anti-social IDs
    
    Restrict IDs to letters, digits, '-', '.', '_', starting with a
    letter.
    
    This takes care of '/' in qdev IDs breaking qbus_find().
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-option.c b/qemu-option.c
index f884865..7f70d0f 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -673,11 +673,31 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
     return NULL;
 }
 
+static int id_wellformed(const char *id)
+{
+    int i;
+
+    if (!qemu_isalpha(id[0])) {
+        return 0;
+    }
+    for (i = 1; id[i]; i++) {
+        if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
 {
     QemuOpts *opts = NULL;
 
     if (id) {
+        if (!id_wellformed(id)) {
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+            error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
+            return NULL;
+        }
         opts = qemu_opts_find(list, id);
         if (opts != NULL) {
             if (fail_if_exists) {
commit 1bb650420021ced718d550559034a5147c053068
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 8 13:54:04 2010 +0200

    qdev: Revert the hack to let -net nic and pci_add set qdev ID
    
    Setting the ID in pci_nic_init() is a blatant violation of the
    DeviceState abstraction.  Which even carries a comment advising
    against this:
    
    /* This structure should not be accessed directly.  We declare it here
       so that it can be embedded in individual device state structures.  */
    
    What's worse, it bypasses the code ensuring unique qdev IDs: "-device
    virtio-net-pci,id=foo -net nic,id=foo -net nic,name=foo" happily
    creates three qdevs with ID "foo".  That's because qdev relies on
    qemu_opts_create() to ensure unique IDs, but -net nic uses a different
    QemuOptsList, which means id is in a different namespace.  And its
    name is not checked for uniqueness at all.
    
    -net nic and pci_add are legacy.  Use -device and device_add if you
    want a NIC with a qdev ID.
    
    This reverts what's still left of commit eb54b6dc "qdev: add id=
    support for pci nics."
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pci.c b/hw/pci.c
index cd7ce8d..7787005 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1446,8 +1446,6 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 
     pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
     dev = &pci_dev->qdev;
-    if (nd->name)
-        dev->id = qemu_strdup(nd->name);
     qdev_set_nic_properties(dev, nd);
     if (qdev_init(dev) < 0)
         return NULL;
commit 3709c1b7ccad238e129c219c0081f1d55330e900
Author: Daniel P. Berrange <berrange at redhat.com>
Date:   Tue Jun 8 15:24:25 2010 +0100

    Clarify error message when a PCI slot is already in use (v2)
    
    When mistakenly configuring two devices in the same PCI slot,
    QEMU gives a not entirely obvious message about a 'devfn' being
    in use:
    
    $ qemu -device rtl8139 -device virtio-balloon-pci,bus=pci.0,addr=0x3
    qemu-kvm: -device virtio-balloon-pci,bus=pci.0,addr=0x3: PCI: devfn 24 not available for virtio-balloon-pci, in use by rtl8139
    
    The user does not configure 'devfn' numbers, they use slot+function.
    Thus the error messages should be reported back to the user with that
    same terminology rather than the internal QEMU terminology. This
    patch makes it report:
    
    $ qemu -device rtl8139 -device virtio-balloon-pci,bus=pci.0,addr=0x3
    qemu: -device virtio-balloon-pci,bus=pci.0,addr=0x3.7: PCI: slot 3 function 0 not available for virtio-balloon-pci, in use by rtl8139
    
    Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/pci.c b/hw/pci.c
index cbbd1dd..cd7ce8d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -609,12 +609,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
             if (!bus->devices[devfn])
                 goto found;
         }
-        error_report("PCI: no devfn available for %s, all in use", name);
+        error_report("PCI: no slot/function available for %s, all in use", name);
         return NULL;
     found: ;
     } else if (bus->devices[devfn]) {
-        error_report("PCI: devfn %d not available for %s, in use by %s",
-                     devfn, name, bus->devices[devfn]->name);
+        error_report("PCI: slot %d function %d not available for %s, in use by %s",
+                     PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
         return NULL;
     }
     pci_dev->bus = bus;
commit c20fd872257fb9abd2ce99741937c0f65aa162b7
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue Jun 8 18:26:07 2010 +0200

    virtio-blk: simplify multiwrite calling conventions
    
    Pass the MultiReqBuffer structure down all the way to the I/O submission
    instead of takin it apart.  Also mark num_writes unsigned as it can't
    go negative, and take the check for any pending I/O requests into the
    submission function.  Last but not least rename do_multiwrite to
    virtio_submit_multiwrite to fit the general naming scheme and make clear
    what it does.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 4e67088..4cc94f6 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -223,33 +223,39 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
 }
 #endif /* __linux__ */
 
-static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
-    int num_writes)
+typedef struct MultiReqBuffer {
+    BlockRequest        blkreq[32];
+    unsigned int        num_writes;
+} MultiReqBuffer;
+
+static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
 {
     int i, ret;
-    ret = bdrv_aio_multiwrite(bs, blkreq, num_writes);
 
+    if (!mrb->num_writes) {
+        return;
+    }
+
+    ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes);
     if (ret != 0) {
-        for (i = 0; i < num_writes; i++) {
-            if (blkreq[i].error) {
-                virtio_blk_rw_complete(blkreq[i].opaque, -EIO);
+        for (i = 0; i < mrb->num_writes; i++) {
+            if (mrb->blkreq[i].error) {
+                virtio_blk_rw_complete(mrb->blkreq[i].opaque, -EIO);
             }
         }
     }
+
+    mrb->num_writes = 0;
 }
 
-static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
-    VirtIOBlockReq *req)
+static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 {
     BlockDriverAIOCB *acb;
 
     /*
      * Make sure all outstanding writes are posted to the backing device.
      */
-    if (*num_writes > 0) {
-        do_multiwrite(req->dev->bs, blkreq, *num_writes);
-    }
-    *num_writes = 0;
+    virtio_submit_multiwrite(req->dev->bs, mrb);
 
     acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
     if (!acb) {
@@ -257,27 +263,28 @@ static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
     }
 }
 
-static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
-    VirtIOBlockReq *req)
+static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 {
+    BlockRequest *blkreq;
+
     if (req->out->sector & req->dev->sector_mask) {
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
 
-    if (*num_writes == 32) {
-        do_multiwrite(req->dev->bs, blkreq, *num_writes);
-        *num_writes = 0;
+    if (mrb->num_writes == 32) {
+        virtio_submit_multiwrite(req->dev->bs, mrb);
     }
 
-    blkreq[*num_writes].sector = req->out->sector;
-    blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
-    blkreq[*num_writes].qiov = &req->qiov;
-    blkreq[*num_writes].cb = virtio_blk_rw_complete;
-    blkreq[*num_writes].opaque = req;
-    blkreq[*num_writes].error = 0;
+    blkreq = &mrb->blkreq[mrb->num_writes];
+    blkreq->sector = req->out->sector;
+    blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
+    blkreq->qiov = &req->qiov;
+    blkreq->cb = virtio_blk_rw_complete;
+    blkreq->opaque = req;
+    blkreq->error = 0;
 
-    (*num_writes)++;
+    mrb->num_writes++;
 }
 
 static void virtio_blk_handle_read(VirtIOBlockReq *req)
@@ -297,11 +304,6 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
     }
 }
 
-typedef struct MultiReqBuffer {
-    BlockRequest        blkreq[32];
-    int                 num_writes;
-} MultiReqBuffer;
-
 static void virtio_blk_handle_request(VirtIOBlockReq *req,
     MultiReqBuffer *mrb)
 {
@@ -320,13 +322,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
     req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
 
     if (req->out->type & VIRTIO_BLK_T_FLUSH) {
-        virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes, req);
+        virtio_blk_handle_flush(req, mrb);
     } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
         virtio_blk_handle_scsi(req);
     } else if (req->out->type & VIRTIO_BLK_T_OUT) {
         qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
                                  req->elem.out_num - 1);
-        virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes, req);
+        virtio_blk_handle_write(req, mrb);
     } else {
         qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
                                  req->elem.in_num - 1);
@@ -346,9 +348,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
         virtio_blk_handle_request(req, &mrb);
     }
 
-    if (mrb.num_writes > 0) {
-        do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
-    }
+    virtio_submit_multiwrite(s->bs, &mrb);
 
     /*
      * FIXME: Want to check for completions before returning to guest mode,
@@ -375,9 +375,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
         req = req->next;
     }
 
-    if (mrb.num_writes > 0) {
-        do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
-    }
+    virtio_submit_multiwrite(s->bs, &mrb);
 }
 
 static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
commit 7e608e8903a39157c28ced12b2a061eafa43c905
Author: Christoph Hellwig <hch at lst.de>
Date:   Tue Jun 8 18:25:54 2010 +0200

    virtio-blk: stop tracking old_bs
    
    There is a 1:1 relation between VirtIOBlock and BlockDriverState instances,
    no need to track it because it won't change.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index cdcb492..4e67088 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -239,18 +239,17 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
 }
 
 static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
-    VirtIOBlockReq *req, BlockDriverState **old_bs)
+    VirtIOBlockReq *req)
 {
     BlockDriverAIOCB *acb;
 
     /*
      * Make sure all outstanding writes are posted to the backing device.
      */
-    if (*old_bs != NULL) {
-        do_multiwrite(*old_bs, blkreq, *num_writes);
+    if (*num_writes > 0) {
+        do_multiwrite(req->dev->bs, blkreq, *num_writes);
     }
     *num_writes = 0;
-    *old_bs = req->dev->bs;
 
     acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
     if (!acb) {
@@ -259,19 +258,16 @@ static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
 }
 
 static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
-    VirtIOBlockReq *req, BlockDriverState **old_bs)
+    VirtIOBlockReq *req)
 {
     if (req->out->sector & req->dev->sector_mask) {
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
 
-    if (req->dev->bs != *old_bs || *num_writes == 32) {
-        if (*old_bs != NULL) {
-            do_multiwrite(*old_bs, blkreq, *num_writes);
-        }
+    if (*num_writes == 32) {
+        do_multiwrite(req->dev->bs, blkreq, *num_writes);
         *num_writes = 0;
-        *old_bs = req->dev->bs;
     }
 
     blkreq[*num_writes].sector = req->out->sector;
@@ -304,7 +300,6 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
 typedef struct MultiReqBuffer {
     BlockRequest        blkreq[32];
     int                 num_writes;
-    BlockDriverState    *old_bs;
 } MultiReqBuffer;
 
 static void virtio_blk_handle_request(VirtIOBlockReq *req,
@@ -325,15 +320,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
     req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
 
     if (req->out->type & VIRTIO_BLK_T_FLUSH) {
-        virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes,
-            req, &mrb->old_bs);
+        virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes, req);
     } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
         virtio_blk_handle_scsi(req);
     } else if (req->out->type & VIRTIO_BLK_T_OUT) {
         qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
                                  req->elem.out_num - 1);
-        virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes,
-            req, &mrb->old_bs);
+        virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes, req);
     } else {
         qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
                                  req->elem.in_num - 1);
@@ -347,7 +340,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
     VirtIOBlockReq *req;
     MultiReqBuffer mrb = {
         .num_writes = 0,
-        .old_bs = NULL,
     };
 
     while ((req = virtio_blk_get_request(s))) {
@@ -355,7 +347,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
     }
 
     if (mrb.num_writes > 0) {
-        do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
+        do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
     }
 
     /*
@@ -371,7 +363,6 @@ static void virtio_blk_dma_restart_bh(void *opaque)
     VirtIOBlockReq *req = s->rq;
     MultiReqBuffer mrb = {
         .num_writes = 0,
-        .old_bs = NULL,
     };
 
     qemu_bh_delete(s->bh);
@@ -385,7 +376,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
     }
 
     if (mrb.num_writes > 0) {
-        do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
+        do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
     }
 }
 
commit 46aaebff40f942e7b17b426916a3dee9b8b6f274
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Tue Jun 8 15:12:18 2010 +0200

    un-register kbd driver in case of USB kbd unplug.
    
    If a USB keyboard is unplugged, the keyboard eventhandler is never
    removed, and events will continue to be passed through to the device,
    causing crashes or memory corruption.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.h b/console.h
index cac959f..aafb031 100644
--- a/console.h
+++ b/console.h
@@ -42,6 +42,7 @@ typedef struct QEMUPutLEDEntry {
 } QEMUPutLEDEntry;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+void qemu_remove_kbd_event_handler(void);
 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
                                                 void *opaque, int absolute,
                                                 const char *name);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 228d0a0..882d933 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -855,9 +855,13 @@ static void usb_hid_handle_destroy(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    if (s->kind != USB_KEYBOARD)
+    switch(s->kind) {
+    case USB_KEYBOARD:
+        qemu_remove_kbd_event_handler();
+        break;
+    default:
         qemu_remove_mouse_event_handler(s->ptr.eh_entry);
-    /* TODO: else */
+    }
 }
 
 static int usb_hid_initfn(USBDevice *dev, int kind)
diff --git a/input.c b/input.c
index 651442d..ec05548 100644
--- a/input.c
+++ b/input.c
@@ -42,6 +42,12 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
     qemu_put_kbd_event = func;
 }
 
+void qemu_remove_kbd_event_handler(void)
+{
+    qemu_put_kbd_event_opaque = NULL;
+    qemu_put_kbd_event = NULL;
+}
+
 static void check_mode_change(void)
 {
     static int current_is_absolute, current_has_absolute;
commit 55541c8afc1a2d75de890c6ee858769d7d605526
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 3 15:20:32 2010 +0200

    make qemu_thread_create block all signals
    
    All signals will thus be routed through the IO thread.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/cpus.c b/cpus.c
index 8341f6c..fcd0f09 100644
--- a/cpus.c
+++ b/cpus.c
@@ -318,8 +318,8 @@ static QemuCond qemu_system_cond;
 static QemuCond qemu_pause_cond;
 static QemuCond qemu_work_cond;
 
-static void tcg_block_io_signals(void);
-static void kvm_block_io_signals(CPUState *env);
+static void tcg_init_ipi(void);
+static void kvm_init_ipi(CPUState *env);
 static void unblock_io_signals(void);
 
 int qemu_init_main_loop(void)
@@ -464,7 +464,7 @@ static void *kvm_cpu_thread_fn(void *arg)
     if (kvm_enabled())
         kvm_init_vcpu(env);
 
-    kvm_block_io_signals(env);
+    kvm_init_ipi(env);
 
     /* signal CPU creation */
     env->created = 1;
@@ -487,7 +487,7 @@ static void *tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
 
-    tcg_block_io_signals();
+    tcg_init_ipi();
     qemu_thread_self(env->thread);
 
     /* signal CPU creation */
@@ -532,52 +532,36 @@ static void cpu_signal(int sig)
     exit_request = 1;
 }
 
-static void tcg_block_io_signals(void)
+static void tcg_init_ipi(void)
 {
     sigset_t set;
     struct sigaction sigact;
 
-    sigemptyset(&set);
-    sigaddset(&set, SIGUSR2);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIGCHLD);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = cpu_signal;
+    sigaction(SIG_IPI, &sigact, NULL);
 
     sigemptyset(&set);
     sigaddset(&set, SIG_IPI);
     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = cpu_signal;
-    sigaction(SIG_IPI, &sigact, NULL);
 }
 
 static void dummy_signal(int sig)
 {
 }
 
-static void kvm_block_io_signals(CPUState *env)
+static void kvm_init_ipi(CPUState *env)
 {
     int r;
     sigset_t set;
     struct sigaction sigact;
 
-    sigemptyset(&set);
-    sigaddset(&set, SIGUSR2);
-    sigaddset(&set, SIGIO);
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIGCHLD);
-    sigaddset(&set, SIG_IPI);
-    pthread_sigmask(SIG_BLOCK, &set, NULL);
-
-    pthread_sigmask(SIG_BLOCK, NULL, &set);
-    sigdelset(&set, SIG_IPI);
-
     memset(&sigact, 0, sizeof(sigact));
     sigact.sa_handler = dummy_signal;
     sigaction(SIG_IPI, &sigact, NULL);
 
+    pthread_sigmask(SIG_BLOCK, NULL, &set);
+    sigdelset(&set, SIG_IPI);
     r = kvm_set_signal_mask(env, &set);
     if (r) {
         fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r));
diff --git a/qemu-thread.c b/qemu-thread.c
index 3923db7..faf4061 100644
--- a/qemu-thread.c
+++ b/qemu-thread.c
@@ -137,9 +137,16 @@ void qemu_thread_create(QemuThread *thread,
 {
     int err;
 
+    /* Leave signal handling to the iothread.  */
+    sigset_t set, oldset;
+
+    sigfillset(&set);
+    pthread_sigmask(SIG_SETMASK, &set, &oldset);
     err = pthread_create(&thread->thread, NULL, start_routine, arg);
     if (err)
         error_exit(err, __func__);
+
+    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
 }
 
 void qemu_thread_signal(QemuThread *thread, int sig)
commit 304e3a7c802969811fe82b6247f63fcba063f52e
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date:   Thu Jun 10 06:50:10 2010 +0900

    migration-tcp: call migrate_fd_error() instead of close() and free().
    
    This patch fixes the following error report.  When changing
    migration-tcp.c to call migrate_fd_error() instead of close() and
    free() by itself, monitor is resumed, and returns allocated mig_state
    is set to current_migration in migration.c allows us to print "info
    migrate".
    
    Reported-by: Cole Robinson <crobinso at redhat.com>
    Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-tcp.c b/migration-tcp.c
index 95ce722..43af2e0 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -128,9 +128,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
 
     if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
         DPRINTF("connect failed\n");
-        close(s->fd);
-        qemu_free(s);
-        return NULL;
+        migrate_fd_error(s);
     } else if (ret >= 0)
         migrate_fd_connect(s);
 
commit faa1f8ddc18fe30257f2ed6c378fce848b159dab
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date:   Wed Jun 9 14:44:31 2010 +0900

    migration: use qemu_free() instead of free().
    
    Although there is no difference, other migration related code use
    qemu_free(), and it should be better to be consistent.
    
    Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index fbf2339..64ed36e 100644
--- a/migration.c
+++ b/migration.c
@@ -396,7 +396,7 @@ void migrate_fd_release(MigrationState *mig_state)
         s->state = MIG_STATE_CANCELLED;
         migrate_fd_cleanup(s);
     }
-    free(s);
+    qemu_free(s);
 }
 
 void migrate_fd_wait_for_unfreeze(void *opaque)
commit f2fcffbbe8d7d2720a5ce992dedbf328be25c03a
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Mon Jun 14 18:41:12 2010 +0200

    etrax-ser: Support the uart rx fifo.
    
    Add support for the rx fifo to speed up bulk transfers.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at axis.com>

diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index e1f9615..336cc54 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -49,20 +49,27 @@ struct etrax_serial
     CharDriverState *chr;
     qemu_irq irq;
 
-    /* This pending thing is a hack.  */
     int pending_tx;
 
+    uint8_t rx_fifo[16];
+    unsigned int rx_fifo_pos;
+    unsigned int rx_fifo_len;
+
     /* Control registers.  */
     uint32_t regs[R_MAX];
 };
 
 static void ser_update_irq(struct etrax_serial *s)
 {
-    s->regs[R_INTR] &= ~(s->regs[RW_ACK_INTR]);
-    s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
 
+    if (s->rx_fifo_len) {
+        s->regs[R_INTR] |= 8;
+    } else {
+        s->regs[R_INTR] &= ~8;
+    }
+
+    s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
     qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
-    s->regs[RW_ACK_INTR] = 0;
 }
 
 static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
@@ -75,16 +82,25 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
     switch (addr)
     {
         case R_STAT_DIN:
-            r = s->regs[RS_STAT_DIN];
+            r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
+            if (s->rx_fifo_len) {
+                r |= 1 << STAT_DAV;
+            }
+            r |= 1 << STAT_TR_RDY;
+            r |= 1 << STAT_TR_IDLE;
             break;
         case RS_STAT_DIN:
-            r = s->regs[addr];
-            /* Read side-effect: clear dav.  */
-            s->regs[addr] &= ~(1 << STAT_DAV);
+            r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
+            if (s->rx_fifo_len) {
+                r |= 1 << STAT_DAV;
+                s->rx_fifo_len--;
+            }
+            r |= 1 << STAT_TR_RDY;
+            r |= 1 << STAT_TR_IDLE;
             break;
         default:
             r = s->regs[addr];
-            D(printf ("%s %x=%x\n", __func__, addr, r));
+            D(printf ("%s " TARGET_FMT_plx "=%x\n", __func__, addr, r));
             break;
     }
     return r;
@@ -97,23 +113,25 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     unsigned char ch = value;
     D(CPUState *env = s->env);
 
-    D(printf ("%s %x %x\n",  __func__, addr, value));
+    D(printf ("%s " TARGET_FMT_plx "=%x\n",  __func__, addr, value));
     addr >>= 2;
     switch (addr)
     {
         case RW_DOUT:
             qemu_chr_write(s->chr, &ch, 1);
-            s->regs[R_INTR] |= 1;
+            s->regs[R_INTR] |= 3;
             s->pending_tx = 1;
             s->regs[addr] = value;
             break;
         case RW_ACK_INTR:
-            s->regs[addr] = value;
-            if (s->pending_tx && (s->regs[addr] & 1)) {
-                s->regs[R_INTR] |= 1;
+            if (s->pending_tx) {
+                value &= ~1;
                 s->pending_tx = 0;
-                s->regs[addr] &= ~1;
+                D(printf("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR]));
             }
+            s->regs[addr] = value;
+            s->regs[R_INTR] &= ~value;
+            D(printf("r_intr=%x\n", s->regs[R_INTR]));
             break;
         default:
             s->regs[addr] = value;
@@ -135,11 +153,21 @@ static CPUWriteMemoryFunc * const ser_write[] = {
 static void serial_receive(void *opaque, const uint8_t *buf, int size)
 {
     struct etrax_serial *s = opaque;
+    int i;
+
+    /* Got a byte.  */
+    if (s->rx_fifo_len >= 16) {
+        printf("WARNING: UART dropped char.\n");
+        return;
+    }
+
+    for (i = 0; i < size; i++) { 
+        s->rx_fifo[s->rx_fifo_pos] = buf[i];
+        s->rx_fifo_pos++;
+        s->rx_fifo_pos &= 15;
+        s->rx_fifo_len++;
+    }
 
-    s->regs[R_INTR] |= 8;
-    s->regs[RS_STAT_DIN] &= ~0xff;
-    s->regs[RS_STAT_DIN] |= (buf[0] & 0xff);
-    s->regs[RS_STAT_DIN] |= (1 << STAT_DAV); /* dav.  */
     ser_update_irq(s);
 }
 
@@ -149,10 +177,11 @@ static int serial_can_receive(void *opaque)
     int r;
 
     /* Is the receiver enabled?  */
-    r = s->regs[RW_REC_CTRL] & 1;
+    if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
+        return 0;
+    }
 
-    /* Pending rx data?  */
-    r |= !(s->regs[R_INTR] & 8);
+    r = sizeof(s->rx_fifo) - s->rx_fifo_len;
     return r;
 }
 
commit f471a17e9d869df3c6573f7ec02c4725676d6f3a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Fri Jun 11 11:11:42 2010 -0600

    ram_blocks: Convert to a QLIST
    
    This makes the RAM block list easier to manipulate.  Also incorporate
    relevant variables into the RAMList struct.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Acked-by: Chris Wright <chrisw at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 8e849a8..eb5b67c 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -110,7 +110,7 @@ static int ram_save_block(QEMUFile *f)
     ram_addr_t addr = 0;
     int bytes_sent = 0;
 
-    while (addr < last_ram_offset) {
+    while (addr < ram_list.last_offset) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
             uint8_t *p;
 
@@ -133,7 +133,7 @@ static int ram_save_block(QEMUFile *f)
             break;
         }
         addr += TARGET_PAGE_SIZE;
-        current_addr = (saved_addr + addr) % last_ram_offset;
+        current_addr = (saved_addr + addr) % ram_list.last_offset;
     }
 
     return bytes_sent;
@@ -146,7 +146,7 @@ static ram_addr_t ram_save_remaining(void)
     ram_addr_t addr;
     ram_addr_t count = 0;
 
-    for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
+    for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
         if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
             count++;
         }
@@ -167,7 +167,7 @@ uint64_t ram_bytes_transferred(void)
 
 uint64_t ram_bytes_total(void)
 {
-    return last_ram_offset;
+    return ram_list.last_offset;
 }
 
 int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
@@ -191,7 +191,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         bytes_transferred = 0;
 
         /* Make sure all dirty bits are set */
-        for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
+        for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
             if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
                 cpu_physical_memory_set_dirty(addr);
             }
@@ -200,7 +200,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
         /* Enable dirty memory tracking */
         cpu_physical_memory_set_dirty_tracking(1);
 
-        qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
+        qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
     }
 
     bytes_transferred_last = bytes_transferred;
@@ -259,7 +259,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
         addr &= TARGET_PAGE_MASK;
 
         if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
-            if (addr != last_ram_offset) {
+            if (addr != ram_list.last_offset) {
                 return -EINVAL;
             }
         }
diff --git a/cpu-all.h b/cpu-all.h
index 77eaf85..e31c2de 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -859,9 +859,21 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
 /* memory API */
 
 extern int phys_ram_fd;
-extern uint8_t *phys_ram_dirty;
 extern ram_addr_t ram_size;
-extern ram_addr_t last_ram_offset;
+
+typedef struct RAMBlock {
+    uint8_t *host;
+    ram_addr_t offset;
+    ram_addr_t length;
+    QLIST_ENTRY(RAMBlock) next;
+} RAMBlock;
+
+typedef struct RAMList {
+    uint8_t *phys_dirty;
+    ram_addr_t last_offset;
+    QLIST_HEAD(ram, RAMBlock) blocks;
+} RAMList;
+extern RAMList ram_list;
 
 extern const char *mem_path;
 extern int mem_prealloc;
@@ -891,29 +903,29 @@ extern int mem_prealloc;
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
-    return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
 }
 
 static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
 {
-    return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
 }
 
 static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
                                                 int dirty_flags)
 {
-    return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
-    phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
 }
 
 static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
                                                       int dirty_flags)
 {
-    return phys_ram_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
 }
 
 static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
@@ -925,7 +937,7 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
 
     len = length >> TARGET_PAGE_BITS;
     mask = ~dirty_flags;
-    p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+    p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
     for (i = 0; i < len; i++) {
         p[i] &= mask;
     }
diff --git a/exec.c b/exec.c
index 4273797..7f64384 100644
--- a/exec.c
+++ b/exec.c
@@ -110,21 +110,9 @@ uint8_t *code_gen_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
 int phys_ram_fd;
-uint8_t *phys_ram_dirty;
 static int in_migration;
 
-typedef struct RAMBlock {
-    uint8_t *host;
-    ram_addr_t offset;
-    ram_addr_t length;
-    struct RAMBlock *next;
-} RAMBlock;
-
-static RAMBlock *ram_blocks;
-/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
-   then we can no longer assume contiguous ram offsets, and external uses
-   of this variable will break.  */
-ram_addr_t last_ram_offset;
+RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
 #endif
 
 CPUState *first_cpu;
@@ -2810,18 +2798,17 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
         madvise(new_block->host, size, MADV_MERGEABLE);
 #endif
     }
-    new_block->offset = last_ram_offset;
+    new_block->offset = ram_list.last_offset;
     new_block->length = size;
 
-    new_block->next = ram_blocks;
-    ram_blocks = new_block;
+    QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
 
-    phys_ram_dirty = qemu_realloc(phys_ram_dirty,
-        (last_ram_offset + size) >> TARGET_PAGE_BITS);
-    memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
+    ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
+        (ram_list.last_offset + size) >> TARGET_PAGE_BITS);
+    memset(ram_list.phys_dirty + (ram_list.last_offset >> TARGET_PAGE_BITS),
            0xff, size >> TARGET_PAGE_BITS);
 
-    last_ram_offset += size;
+    ram_list.last_offset += size;
 
     if (kvm_enabled())
         kvm_setup_guest_memory(new_block->host, size);
@@ -2844,31 +2831,20 @@ void qemu_ram_free(ram_addr_t addr)
  */
 void *qemu_get_ram_ptr(ram_addr_t addr)
 {
-    RAMBlock *prev;
-    RAMBlock **prevp;
     RAMBlock *block;
 
-    prev = NULL;
-    prevp = &ram_blocks;
-    block = ram_blocks;
-    while (block && (block->offset > addr
-                     || block->offset + block->length <= addr)) {
-        if (prev)
-          prevp = &prev->next;
-        prev = block;
-        block = block->next;
-    }
-    if (!block) {
-        fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
-        abort();
-    }
-    /* Move this entry to to start of the list.  */
-    if (prev) {
-        prev->next = block->next;
-        block->next = *prevp;
-        *prevp = block;
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (addr - block->offset < block->length) {
+            QLIST_REMOVE(block, next);
+            QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
+            return block->host + (addr - block->offset);
+        }
     }
-    return block->host + (addr - block->offset);
+
+    fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+    abort();
+
+    return NULL;
 }
 
 /* Some of the softmmu routines need to translate from a host pointer
@@ -2878,16 +2854,16 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
     RAMBlock *block;
     uint8_t *host = ptr;
 
-    block = ram_blocks;
-    while (block && (block->host > host
-                     || block->host + block->length <= host)) {
-        block = block->next;
-    }
-    if (!block) {
-        fprintf(stderr, "Bad ram pointer %p\n", ptr);
-        abort();
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (host - block->host < block->length) {
+            return block->offset + (host - block->host);
+        }
     }
-    return block->offset + (host - block->host);
+
+    fprintf(stderr, "Bad ram pointer %p\n", ptr);
+    abort();
+
+    return 0;
 }
 
 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
commit 2ffcb18de0bc02ad8a836ec955584c02b70e0e24
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jun 11 14:21:34 2010 +0200

    Make netdev_del delete the netdev even when it's in use
    
    To hot-unplug guest and host part of a network device, you do:
    
        device_del NIC-ID
        netdev_del NETDEV-ID
    
    For PCI devices, device_del merely tells ACPI to unplug the device.
    The device goes away for real only after the guest processed the ACPI
    unplug event.
    
    You have to wait until then (e.g. by polling info pci) before you can
    unplug the netdev.  Not good.
    
    Fix by removing the "in use" check from do_netdev_del().  Deleting a
    netdev while it's in use is safe; packets simply get routed to the bit
    bucket.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net.c b/net.c
index 4cb93ed..0703698 100644
--- a/net.c
+++ b/net.c
@@ -1221,10 +1221,6 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         qerror_report(QERR_DEVICE_NOT_FOUND, id);
         return -1;
     }
-    if (vc->peer) {
-        qerror_report(QERR_DEVICE_IN_USE, id);
-        return -1;
-    }
     qemu_del_vlan_client(vc);
     qemu_opts_del(qemu_opts_find(&qemu_netdev_opts, id));
     return 0;
commit 40ac17cd56eb5c5a89559ea0fa53f7eea80cbd07
Author: Gleb Natapov <gleb at redhat.com>
Date:   Mon Jun 14 11:29:28 2010 +0300

    pass info about hpets to seabios.]
    
    Currently HPET ACPI table is created regardless of whether qemu actually
    created hpet device. This may confuse some guests that don't check that
    hpet is functional before using it. Solve this by passing info about
    hpets in qemu to seabios via fw config interface. Additional benefit is
    that seabios no longer uses hard coded hpet configuration. Proposed
    interface supports up to 8 hpets. This is the number defined by hpet
    spec.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index e9b585c..0c80ee5 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -71,8 +71,11 @@ typedef struct HPETState {
     uint64_t config;            /* configuration */
     uint64_t isr;               /* interrupt status reg */
     uint64_t hpet_counter;      /* main counter */
+    uint8_t  hpet_id;           /* instance id */
 } HPETState;
 
+struct hpet_fw_config hpet_cfg = {.count = ~0};
+
 static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
     return s->config & HPET_CFG_LEGACY;
@@ -228,6 +231,7 @@ static int hpet_post_load(void *opaque, int version_id)
     /* Push number of timers into capability returned via HPET_ID */
     s->capability &= ~HPET_ID_NUM_TIM_MASK;
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+    hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
 
     /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
     s->flags &= ~(1 << HPET_MSI_SUPPORT);
@@ -657,6 +661,8 @@ static void hpet_reset(DeviceState *d)
          */
         hpet_pit_enable();
     }
+    hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
+    hpet_cfg.hpet[s->hpet_id].address = sysbus_from_qdev(d)->mmio[0].addr;
     count = 1;
 }
 
@@ -676,6 +682,16 @@ static int hpet_init(SysBusDevice *dev)
     int i, iomemtype;
     HPETTimer *timer;
 
+    if (hpet_cfg.count == ~0) /* first instance */
+        hpet_cfg.count = 0;
+
+    if (hpet_cfg.count == 8) {
+        fprintf(stderr, "Only 8 instances of HPET is allowed\n");
+        return -1;
+    }
+
+    s->hpet_id = hpet_cfg.count++;
+
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index d7bc102..8bf312a 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -53,4 +53,19 @@
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
 
+struct hpet_fw_entry
+{
+    uint32_t event_timer_block_id;
+    uint64_t address;
+    uint16_t min_tick;
+    uint8_t page_prot;
+} __attribute__ ((packed));
+
+struct hpet_fw_config
+{
+    uint8_t count;
+    struct hpet_fw_entry hpet[8];
+} __attribute__ ((packed));
+
+extern struct hpet_fw_config hpet_cfg;
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 0f7d330..0211fbf 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -62,6 +62,7 @@
 #define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
 #define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
 #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
+#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
 
 #define E820_NR_ENTRIES		16
 
@@ -485,6 +486,8 @@ static void *bochs_bios_init(void)
     fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, (uint8_t *)&e820_table,
                      sizeof(struct e820_table));
 
+    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, (uint8_t *)&hpet_cfg,
+                     sizeof(struct hpet_fw_config));
     /* allocate memory for the NUMA channel: one (64bit) word for the number
      * of nodes, one word for each VCPU->node and one word for each node to
      * hold the amount of memory.
commit 072c2c31c27204e8e1897c52e481d2ab0b4d075d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon Jun 14 08:40:29 2010 +0200

    hpet: Init capability register only once
    
    The capability register is read-only from guest POV, so we do not need
    to update it on reset.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 93fc399..e9b585c 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -648,10 +648,6 @@ static void hpet_reset(DeviceState *d)
 
     s->hpet_counter = 0ULL;
     s->hpet_offset = 0ULL;
-    /* 64-bit main counter; LegacyReplacementRoute. */
-    s->capability = 0x8086a001ULL;
-    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
-    s->capability |= ((HPET_CLK_PERIOD) << 32);
     s->config = 0ULL;
     if (count > 0) {
         /* we don't enable pit when hpet_reset is first called (by hpet_init)
@@ -696,6 +692,11 @@ static int hpet_init(SysBusDevice *dev)
         timer->state = s;
     }
 
+    /* 64-bit main counter; LegacyReplacementRoute. */
+    s->capability = 0x8086a001ULL;
+    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+    s->capability |= ((HPET_CLK_PERIOD) << 32);
+
     isa_reserve_irq(RTC_ISA_IRQ);
     qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
 
commit bd69fe8448024258d046e2a15d4cf5c498188144
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Jun 11 10:19:41 2010 +0200

    qemu-option: Fix uninitialized value in append_option_parameter
    
    When dest is NULL, i.e. a new copy of the list is created, we don't get a
    properly terminated list after the realloc. Initialize it as an empty list.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-option.c b/qemu-option.c
index acd74f9..f884865 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -378,6 +378,7 @@ QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
     num_options += count_option_parameters(list);
 
     dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
+    dest[num_dest_options].name = NULL;
 
     while (list && list->name) {
         if (get_option_parameter(dest, list->name) == NULL) {
commit 271248886e6110b4af0545f6a2d3ef38217cd58f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jun 14 17:05:17 2010 +0200

    Change #define DEBUG to #define E1000_DEBUG in hw/e1000.c
    
    Change #define DEBUG to #define E1000_DEBUG in hw/e1000.c to make
    it possible to build QEMU with -DDEBUG
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/e1000.c b/hw/e1000.c
index 96d045d..0da65f9 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -33,9 +33,9 @@
 
 #include "e1000_hw.h"
 
-#define DEBUG
+#define E1000_DEBUG
 
-#ifdef DEBUG
+#ifdef E1000_DEBUG
 enum {
     DEBUG_GENERAL,	DEBUG_IO,	DEBUG_MMIO,	DEBUG_INTERRUPT,
     DEBUG_RX,		DEBUG_TX,	DEBUG_MDIC,	DEBUG_EEPROM,
commit ac7045cff7db837cfcc552bdc0f0baa15699f21a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jun 14 17:05:16 2010 +0200

    Remove unused DEBUG defines from hw/msix.c
    
    Remove unused DEBUG defines from hw/msix.c to avoid having anything
    define the word DEBUG without any additions such as MSIX_DEBUG.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/msix.c b/hw/msix.c
index 1613bb4..d99403a 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -42,15 +42,6 @@
 #define MSIX_MAX_ENTRIES 32
 
 
-#ifdef MSIX_DEBUG
-#define DEBUG(fmt, ...)                                       \
-    do {                                                      \
-      fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__);    \
-    } while (0)
-#else
-#define DEBUG(fmt, ...) do { } while(0)
-#endif
-
 /* Flag for interrupt controller to declare MSI-X support */
 int msix_supported;
 
commit a4673e276248ada38f40d39191a197e7e35d3f8b
Merge: a2da039... 653dbec...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 14 10:33:36 2010 -0500

    Merge remote branch 'kwolf/for-anthony' into staging
    
    Conflicts:
    	hw/pc.c

diff --cc hw/pc.c
index 1491129,6e7c468..0f7d330
--- a/hw/pc.c
+++ b/hw/pc.c
@@@ -35,7 -35,7 +35,8 @@@
  #include "elf.h"
  #include "multiboot.h"
  #include "mc146818rtc.h"
 +#include "sysbus.h"
+ #include "sysemu.h"
  
  /* output Bochs bios info messages */
  //#define DEBUG_BIOS
commit a2da0395c12bd2b26e2180d735c83988ff66a559
Merge: 0956457... 02e9591...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jun 14 09:39:01 2010 -0500

    Merge remote branch 'qmp/for-anthony' into staging

commit 09564574b868f591fb1a9cf426f0c1d64f280431
Author: Paul Brook <paul at codesourcery.com>
Date:   Sun Jun 13 23:37:31 2010 +0100

    OHCI address decoding fix
    
    Ignore high address bits when PCI memory window is not mapped on a page
    boundary.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 9f80e15..c60fd8d 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1415,6 +1415,8 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
     OHCIState *ohci = ptr;
     uint32_t retval;
 
+    addr &= 0xff;
+
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1538,6 +1540,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
 {
     OHCIState *ohci = ptr;
 
+    addr &= 0xff;
+
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
 #endif
commit 11165820d194478d493d667a11ea8480ce893c70
Author: Paul Brook <paul at codesourcery.com>
Date:   Sun Jun 13 19:00:50 2010 +0100

    Move stdbool.h
    
    Move inclusion of stdbool.h to common header files, instead of including
    in an ad-hoc manner.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 8325f75..98fed94 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -26,8 +26,6 @@
 #include "block_int.h"
 #include "module.h"
 
-#include <stdbool.h>
-
 typedef struct BlkdebugVars {
     int state;
 
diff --git a/check-qjson.c b/check-qjson.c
index 109e777..86e780c 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -9,7 +9,6 @@
  *
  */
 #include <check.h>
-#include <stdbool.h>
 
 #include "qstring.h"
 #include "qint.h"
diff --git a/dyngen-exec.h b/dyngen-exec.h
index 0700a2d..5bfef3f 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -31,6 +31,7 @@
    host headers do not allow that. */
 #include <stddef.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #ifdef __OpenBSD__
 #include <sys/types.h>
diff --git a/hw/9p.h b/hw/9p.h
index 5fdd770..d9951d6 100644
--- a/hw/9p.h
+++ b/hw/9p.h
@@ -14,8 +14,6 @@
 #ifndef QEMU_9P_H
 #define QEMU_9P_H
 
-#include <stdbool.h>
-
 typedef struct V9fsConf
 {
     /* tag name for the device */
diff --git a/hw/eepro100.c b/hw/eepro100.c
index a74d834..97afa2c 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -41,7 +41,6 @@
  *      * Wake-on-LAN is not implemented.
  */
 
-#include <stdbool.h>            /* bool */
 #include <stddef.h>             /* offsetof */
 #include "hw.h"
 #include "pci.h"
diff --git a/hw/hw.h b/hw/hw.h
index 36be0be..a49d866 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -8,7 +8,6 @@
 #include "cpu-common.h"
 #endif
 
-#include <stdbool.h>
 #include "ioport.h"
 #include "irq.h"
 
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index a93b545..ff08c40 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -15,7 +15,6 @@
 #ifndef _QEMU_VIRTIO_SERIAL_H
 #define _QEMU_VIRTIO_SERIAL_H
 
-#include <stdbool.h>
 #include "qdev.h"
 #include "virtio.h"
 
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 422cd53..da5297b 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -29,7 +29,6 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <stdbool.h>
 #include <sys/mman.h>
 #include <errno.h>
 #include <stdio.h>
diff --git a/json-parser.c b/json-parser.c
index b55d763..1c88ed8 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -11,7 +11,6 @@
  *
  */
 
-#include <stdbool.h>
 #include <stdarg.h>
 
 #include "qemu-common.h"
diff --git a/kvm.h b/kvm.h
index a28e7aa..a30529c 100644
--- a/kvm.h
+++ b/kvm.h
@@ -14,7 +14,6 @@
 #ifndef QEMU_KVM_H
 #define QEMU_KVM_H
 
-#include <stdbool.h>
 #include <errno.h>
 #include "config-host.h"
 #include "qemu-queue.h"
diff --git a/nbd.h b/nbd.h
index 5deac29..5a1fbdf 100644
--- a/nbd.h
+++ b/nbd.h
@@ -20,7 +20,6 @@
 #define NBD_H
 
 #include <sys/types.h>
-#include <stdbool.h>
 
 #include <qemu-common.h>
 #include "block_int.h"
diff --git a/net.h b/net.h
index b83f615..518cf9c 100644
--- a/net.h
+++ b/net.h
@@ -1,7 +1,6 @@
 #ifndef QEMU_NET_H
 #define QEMU_NET_H
 
-#include <stdbool.h>
 #include "qemu-queue.h"
 #include "qemu-common.h"
 #include "qdict.h"
diff --git a/qemu-common.h b/qemu-common.h
index a4888e5..d133f35 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -26,6 +26,7 @@ typedef struct QEMUBH QEMUBH;
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <string.h>
 #include <strings.h>
 #include <inttypes.h>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index e8604a8..faba483 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -26,8 +26,6 @@
  * THE SOFTWARE.
  */
 
-#include <stdbool.h>
-
 #include "qdict.h"
 #include "qint.h"
 #include "vnc.h"
commit ea4e78e590e5dbef9c41d987d2553d752ecb49b1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:46 2010 +0200

    monitor/QMP: Drop info hpet / query-hpet
    
    This command was of minimal use before, now it is useless as the hpet
    become a qdev device and is thus easily discoverable. We should
    definitely not set query-hpet in QMP's stone, and there is also no good
    reason to keep it for the interactive monitor.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/QMP/vm-info b/QMP/vm-info
index b150d82..8ebaeb3 100755
--- a/QMP/vm-info
+++ b/QMP/vm-info
@@ -25,7 +25,7 @@ def main():
     qemu = qmp.QEMUMonitorProtocol(argv[1])
     qemu.connect()
 
-    for cmd in [ 'version', 'hpet', 'kvm', 'status', 'uuid', 'balloon' ]:
+    for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]:
         print cmd + ': ' + str(qemu.send('query-' + cmd))
 
 if __name__ == '__main__':
diff --git a/monitor.c b/monitor.c
index 15b53b9..14f77bd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -740,20 +740,6 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
     *ret_data = QOBJECT(cmd_list);
 }
 
-#if defined(TARGET_I386)
-static void do_info_hpet_print(Monitor *mon, const QObject *data)
-{
-    monitor_printf(mon, "HPET is %s by QEMU\n",
-                   qdict_get_bool(qobject_to_qdict(data), "enabled") ?
-                   "enabled" : "disabled");
-}
-
-static void do_info_hpet(Monitor *mon, QObject **ret_data)
-{
-    *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
-}
-#endif
-
 static void do_info_uuid_print(Monitor *mon, const QObject *data)
 {
     monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
@@ -2509,14 +2495,6 @@ static const mon_cmd_t info_cmds[] = {
         .help       = "show the active virtual memory mappings",
         .mhandler.info = mem_info,
     },
-    {
-        .name       = "hpet",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show state of HPET",
-        .user_print = do_info_hpet_print,
-        .mhandler.info_new = do_info_hpet,
-    },
 #endif
     {
         .name       = "jit",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f6a94f2..9f62b94 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -2144,27 +2144,6 @@ show the active virtual memory mappings (i386 only)
 ETEXI
 
 STEXI
- at item info hpet
-show state of HPET (i386 only)
-ETEXI
-SQMP
-query-hpet
-----------
-
-Show HPET state.
-
-Return a json-object with the following information:
-
-- "enabled": true if hpet if enabled, false otherwise (json-bool)
-
-Example:
-
--> { "execute": "query-hpet" }
-<- { "return": { "enabled": true } }
-
-EQMP
-
-STEXI
 @item info jit
 show dynamic compiler info
 @item info kvm
commit 8caa0065b82c1a223aeaca62e7d572c89db2b6eb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:45 2010 +0200

    hpet: Add MSI support
    
    This implements the HPET capability of routing IRQs to the front-side
    bus, aka MSI support. This feature can be enabled via the qdev property
    "msi" and is off by default.
    
    Note that switching it on can cause guests (at least Linux) to use the
    HPET as timer instead of the LAPIC. KVM users should recall that only
    the latter is currently available as fast in-kernel model.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 6187e5e..93fc399 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -39,6 +39,8 @@
 #define DPRINTF(...)
 #endif
 
+#define HPET_MSI_SUPPORT        0
+
 struct HPETState;
 typedef struct HPETTimer {  /* timers */
     uint8_t tn;             /*timer number*/
@@ -47,7 +49,7 @@ typedef struct HPETTimer {  /* timers */
     /* Memory-mapped, software visible timer registers */
     uint64_t config;        /* configuration/cap */
     uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route, not supported now */
+    uint64_t fsb;           /* FSB route */
     /* Hidden register state */
     uint64_t period;        /* Last value written to comparator */
     uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
@@ -59,6 +61,7 @@ typedef struct HPETState {
     SysBusDevice busdev;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint32_t flags;
     uint8_t rtc_irq_level;
     uint8_t num_timers;
     HPETTimer timer[HPET_MAX_TIMERS];
@@ -80,6 +83,11 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
     return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
+static uint32_t timer_fsb_route(HPETTimer *t)
+{
+    return t->config & HPET_TN_FSB_ENABLE;
+}
+
 static uint32_t hpet_enabled(HPETState *s)
 {
     return s->config & HPET_CFG_ENABLE;
@@ -179,7 +187,11 @@ static void update_irq(struct HPETTimer *timer, int set)
     mask = 1 << timer->tn;
     if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
         s->isr &= ~mask;
-        qemu_irq_lower(s->irqs[route]);
+        if (!timer_fsb_route(timer)) {
+            qemu_irq_lower(s->irqs[route]);
+        }
+    } else if (timer_fsb_route(timer)) {
+        stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         qemu_irq_raise(s->irqs[route]);
@@ -216,6 +228,12 @@ static int hpet_post_load(void *opaque, int version_id)
     /* Push number of timers into capability returned via HPET_ID */
     s->capability &= ~HPET_ID_NUM_TIM_MASK;
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+
+    /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
+    s->flags &= ~(1 << HPET_MSI_SUPPORT);
+    if (s->timer[0].config & HPET_TN_FSB_CAP) {
+        s->flags |= 1 << HPET_MSI_SUPPORT;
+    }
     return 0;
 }
 
@@ -361,6 +379,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
         case HPET_TN_CMP + 4:
             return timer->cmp >> 32;
         case HPET_TN_ROUTE:
+            return timer->fsb;
+        case HPET_TN_ROUTE + 4:
             return timer->fsb >> 32;
         default:
             DPRINTF("qemu: invalid hpet_ram_readl\n");
@@ -444,6 +464,9 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
         switch ((addr - 0x100) % 0x20) {
         case HPET_TN_CFG:
             DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
+            if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
+                update_irq(timer, 0);
+            }
             val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
             timer->config = (timer->config & 0xffffffff00000000ULL) | val;
             if (new_val & HPET_TN_32BIT) {
@@ -501,8 +524,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     hpet_set_timer(timer);
                 }
                 break;
+        case HPET_TN_ROUTE:
+            timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
+            break;
         case HPET_TN_ROUTE + 4:
-            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+            timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
             break;
         default:
             DPRINTF("qemu: invalid hpet_ram_writel\n");
@@ -610,7 +636,10 @@ static void hpet_reset(DeviceState *d)
 
         hpet_del_timer(timer);
         timer->cmp = ~0ULL;
-        timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        if (s->flags & (1 << HPET_MSI_SUPPORT)) {
+            timer->config |= HPET_TN_FSB_CAP;
+        }
         /* advertise availability of ioapic inti2 */
         timer->config |=  0x00000004ULL << 32;
         timer->period = 0ULL;
@@ -686,6 +715,7 @@ static SysBusDeviceInfo hpet_device_info = {
     .init         = hpet_init,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+        DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index e8b794c..d7bc102 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -46,7 +46,9 @@
 #define HPET_TN_SETVAL           0x040
 #define HPET_TN_32BIT            0x100
 #define HPET_TN_INT_ROUTE_MASK  0x3e00
-#define HPET_TN_CFG_WRITE_MASK  0x3f4e
+#define HPET_TN_FSB_ENABLE      0x4000
+#define HPET_TN_FSB_CAP         0x8000
+#define HPET_TN_CFG_WRITE_MASK  0x7f4e
 #define HPET_TN_INT_ROUTE_SHIFT      9
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
commit be4b44c59bcee4b3d63bfef137c0ac7d68ef514b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:44 2010 +0200

    hpet: Make number of timers configurable
    
    One HPET block supports up to 32 timers. Allow to instantiate more than
    the recommended and implemented minimum of 3. The number is configured
    via the qdev property "timers". It is also saved/restored so that it
    need not match between migration peers.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index f24b227..6187e5e 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -60,7 +60,8 @@ typedef struct HPETState {
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     uint8_t rtc_irq_level;
-    HPETTimer timer[HPET_NUM_TIMERS];
+    uint8_t num_timers;
+    HPETTimer timer[HPET_MAX_TIMERS];
 
     /* Memory-mapped, software visible registers */
     uint64_t capability;        /* capabilities */
@@ -196,12 +197,25 @@ static void hpet_pre_save(void *opaque)
     s->hpet_counter = hpet_get_ticks(s);
 }
 
+static int hpet_pre_load(void *opaque)
+{
+    HPETState *s = opaque;
+
+    /* version 1 only supports 3, later versions will load the actual value */
+    s->num_timers = HPET_MIN_TIMERS;
+    return 0;
+}
+
 static int hpet_post_load(void *opaque, int version_id)
 {
     HPETState *s = opaque;
 
     /* Recalculate the offset between the main counter and guest time */
     s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+
+    /* Push number of timers into capability returned via HPET_ID */
+    s->capability &= ~HPET_ID_NUM_TIM_MASK;
+    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     return 0;
 }
 
@@ -224,17 +238,19 @@ static const VMStateDescription vmstate_hpet_timer = {
 
 static const VMStateDescription vmstate_hpet = {
     .name = "hpet",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .pre_save = hpet_pre_save,
+    .pre_load = hpet_pre_load,
     .post_load = hpet_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_UINT64(config, HPETState),
         VMSTATE_UINT64(isr, HPETState),
         VMSTATE_UINT64(hpet_counter, HPETState),
-        VMSTATE_STRUCT_ARRAY(timer, HPETState, HPET_NUM_TIMERS, 0,
-                             vmstate_hpet_timer, HPETTimer),
+        VMSTATE_UINT8_V(num_timers, HPETState, 2),
+        VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
+                                    vmstate_hpet_timer, HPETTimer),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -330,7 +346,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
         uint8_t timer_id = (addr - 0x100) / 0x20;
         HPETTimer *timer = &s->timer[timer_id];
 
-        if (timer_id > HPET_NUM_TIMERS - 1) {
+        if (timer_id > s->num_timers) {
             DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
@@ -421,7 +437,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
         HPETTimer *timer = &s->timer[timer_id];
 
         DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
-        if (timer_id > HPET_NUM_TIMERS - 1) {
+        if (timer_id > s->num_timers) {
             DPRINTF("qemu: timer id out of range\n");
             return;
         }
@@ -504,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 /* Enable main counter and interrupt generation. */
                 s->hpet_offset =
                     ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
-                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                for (i = 0; i < s->num_timers; i++) {
                     if ((&s->timer[i])->cmp != ~0ULL) {
                         hpet_set_timer(&s->timer[i]);
                     }
@@ -512,7 +528,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Halt main counter and disable interrupt generation. */
                 s->hpet_counter = hpet_get_ticks(s);
-                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                for (i = 0; i < s->num_timers; i++) {
                     hpet_del_timer(&s->timer[i]);
                 }
             }
@@ -530,7 +546,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_STATUS:
             val = new_val & s->isr;
-            for (i = 0; i < HPET_NUM_TIMERS; i++) {
+            for (i = 0; i < s->num_timers; i++) {
                 if (val & (1 << i)) {
                     update_irq(&s->timer[i], 0);
                 }
@@ -589,7 +605,7 @@ static void hpet_reset(DeviceState *d)
     int i;
     static int count = 0;
 
-    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+    for (i = 0; i < s->num_timers; i++) {
         HPETTimer *timer = &s->timer[i];
 
         hpet_del_timer(timer);
@@ -603,8 +619,9 @@ static void hpet_reset(DeviceState *d)
 
     s->hpet_counter = 0ULL;
     s->hpet_offset = 0ULL;
-    /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
-    s->capability = 0x8086a201ULL;
+    /* 64-bit main counter; LegacyReplacementRoute. */
+    s->capability = 0x8086a001ULL;
+    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
     s->config = 0ULL;
     if (count > 0) {
@@ -637,7 +654,13 @@ static int hpet_init(SysBusDevice *dev)
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
-    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+
+    if (s->num_timers < HPET_MIN_TIMERS) {
+        s->num_timers = HPET_MIN_TIMERS;
+    } else if (s->num_timers > HPET_MAX_TIMERS) {
+        s->num_timers = HPET_MAX_TIMERS;
+    }
+    for (i = 0; i < HPET_MAX_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
         timer->tn = i;
@@ -661,6 +684,10 @@ static SysBusDeviceInfo hpet_device_info = {
     .qdev.vmsd    = &vmstate_hpet,
     .qdev.reset   = hpet_reset,
     .init         = hpet_init,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+        DEFINE_PROP_END_OF_LIST(),
+    },
 };
 
 static void hpet_register_device(void)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 9c268cc..e8b794c 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -17,7 +17,8 @@
 #define HPET_CLK_PERIOD         10000000ULL /* 10000000 femtoseconds == 10ns*/
 
 #define FS_PER_NS 1000000
-#define HPET_NUM_TIMERS 3
+#define HPET_MIN_TIMERS         3
+#define HPET_MAX_TIMERS         32
 
 #define HPET_NUM_IRQ_ROUTES     32
 
@@ -34,6 +35,9 @@
 #define HPET_TN_ROUTE   0x010
 #define HPET_CFG_WRITE_MASK  0x3
 
+#define HPET_ID_NUM_TIM_SHIFT   8
+#define HPET_ID_NUM_TIM_MASK    0x1f00
+
 #define HPET_TN_TYPE_LEVEL       0x002
 #define HPET_TN_ENABLE           0x004
 #define HPET_TN_PERIODIC         0x008
commit cea1adfda7cca55788fbe55107e5e7943d374065
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:43 2010 +0200

    vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8
    
    Required for hpet.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hw.h b/hw/hw.h
index fc2d184..36be0be 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -474,6 +474,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint8_t),  \
+    .version_id = (_version),                                        \
+    .vmsd       = &(_vmsd),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_STRUCT|VMS_VARRAY_INT32,                       \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
commit 22a9fe38a37efc2feb67fac533309ea219242cb5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:42 2010 +0200

    hpet: Add support for level-triggered interrupts
    
    By implementing this feature we can also remove a nasty way to kill qemu
    (by trying to enable level-triggered hpet interrupts).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 59a06f6..f24b227 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -159,8 +159,10 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
     }
 }
 
-static void update_irq(struct HPETTimer *timer)
+static void update_irq(struct HPETTimer *timer, int set)
 {
+    uint64_t mask;
+    HPETState *s;
     int route;
 
     if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
@@ -172,10 +174,18 @@ static void update_irq(struct HPETTimer *timer)
     } else {
         route = timer_int_route(timer);
     }
-    if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
-        return;
+    s = timer->state;
+    mask = 1 << timer->tn;
+    if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
+        s->isr &= ~mask;
+        qemu_irq_lower(s->irqs[route]);
+    } else if (timer->config & HPET_TN_TYPE_LEVEL) {
+        s->isr |= mask;
+        qemu_irq_raise(s->irqs[route]);
+    } else {
+        s->isr &= ~mask;
+        qemu_irq_pulse(s->irqs[route]);
     }
-    qemu_irq_pulse(timer->state->irqs[route]);
 }
 
 static void hpet_pre_save(void *opaque)
@@ -261,7 +271,7 @@ static void hpet_timer(void *opaque)
             t->wrap_flag = 0;
         }
     }
-    update_irq(t);
+    update_irq(t, 1);
 }
 
 static void hpet_set_timer(HPETTimer *t)
@@ -291,6 +301,7 @@ static void hpet_set_timer(HPETTimer *t)
 static void hpet_del_timer(HPETTimer *t)
 {
     qemu_del_timer(t->qemu_timer);
+    update_irq(t, 0);
 }
 
 #ifdef HPET_DEBUG
@@ -423,10 +434,6 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 timer->cmp = (uint32_t)timer->cmp;
                 timer->period = (uint32_t)timer->period;
             }
-            if (new_val & HPET_TN_TYPE_LEVEL) {
-                printf("qemu: level-triggered hpet not supported\n");
-                exit (-1);
-            }
             if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
                 hpet_set_timer(timer);
             } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
@@ -522,7 +529,12 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             DPRINTF("qemu: invalid HPET_CFG+4 write \n");
             break;
         case HPET_STATUS:
-            /* FIXME: need to handle level-triggered interrupts */
+            val = new_val & s->isr;
+            for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                if (val & (1 << i)) {
+                    update_irq(&s->timer[i], 0);
+                }
+            }
             break;
         case HPET_COUNTER:
             if (hpet_enabled(s)) {
commit b7eaa6c77c67c2f2e821a51c6b2758aa482b2d71
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:41 2010 +0200

    hpet: Drop static state
    
    Instead of keeping a static reference around, pass the state to
    hpet_enabled and hpet_get_ticks. All callers now have it at hand. Will
    once allow to instantiate the HPET more than a single time.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index edfe02e..59a06f6 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -69,8 +69,6 @@ typedef struct HPETState {
     uint64_t hpet_counter;      /* main counter */
 } HPETState;
 
-static HPETState *hpet_statep;
-
 static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
     return s->config & HPET_CFG_LEGACY;
@@ -81,9 +79,9 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
     return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
-static uint32_t hpet_enabled(void)
+static uint32_t hpet_enabled(HPETState *s)
 {
-    return hpet_statep->config & HPET_CFG_ENABLE;
+    return s->config & HPET_CFG_ENABLE;
 }
 
 static uint32_t timer_is_periodic(HPETTimer *t)
@@ -133,9 +131,9 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
     return ((old & mask) && !(new & mask));
 }
 
-static uint64_t hpet_get_ticks(void)
+static uint64_t hpet_get_ticks(HPETState *s)
 {
-    return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
+    return ns_to_ticks(qemu_get_clock(vm_clock) + s->hpet_offset);
 }
 
 /*
@@ -174,7 +172,7 @@ static void update_irq(struct HPETTimer *timer)
     } else {
         route = timer_int_route(timer);
     }
-    if (!timer_enabled(timer) || !hpet_enabled()) {
+    if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
         return;
     }
     qemu_irq_pulse(timer->state->irqs[route]);
@@ -185,7 +183,7 @@ static void hpet_pre_save(void *opaque)
     HPETState *s = opaque;
 
     /* save current counter value */
-    s->hpet_counter = hpet_get_ticks();
+    s->hpet_counter = hpet_get_ticks(s);
 }
 
 static int hpet_post_load(void *opaque, int version_id)
@@ -240,7 +238,7 @@ static void hpet_timer(void *opaque)
     uint64_t diff;
 
     uint64_t period = t->period;
-    uint64_t cur_tick = hpet_get_ticks();
+    uint64_t cur_tick = hpet_get_ticks(t->state);
 
     if (timer_is_periodic(t) && period != 0) {
         if (t->config & HPET_TN_32BIT) {
@@ -270,7 +268,7 @@ static void hpet_set_timer(HPETTimer *t)
 {
     uint64_t diff;
     uint32_t wrap_diff;  /* how many ticks until we wrap? */
-    uint64_t cur_tick = hpet_get_ticks();
+    uint64_t cur_tick = hpet_get_ticks(t->state);
 
     /* whenever new timer is being set up, make sure wrap_flag is 0 */
     t->wrap_flag = 0;
@@ -353,16 +351,16 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
             DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
             return 0;
         case HPET_COUNTER:
-            if (hpet_enabled()) {
-                cur_tick = hpet_get_ticks();
+            if (hpet_enabled(s)) {
+                cur_tick = hpet_get_ticks(s);
             } else {
                 cur_tick = s->hpet_counter;
             }
             DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
             return cur_tick;
         case HPET_COUNTER + 4:
-            if (hpet_enabled()) {
-                cur_tick = hpet_get_ticks();
+            if (hpet_enabled(s)) {
+                cur_tick = hpet_get_ticks(s);
             } else {
                 cur_tick = s->hpet_counter;
             }
@@ -457,7 +455,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     (timer->period & 0xffffffff00000000ULL) | new_val;
             }
             timer->config &= ~HPET_TN_SETVAL;
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 hpet_set_timer(timer);
             }
             break;
@@ -476,7 +474,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     (timer->period & 0xffffffffULL) | new_val << 32;
                 }
                 timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled()) {
+                if (hpet_enabled(s)) {
                     hpet_set_timer(timer);
                 }
                 break;
@@ -506,7 +504,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 }
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Halt main counter and disable interrupt generation. */
-                s->hpet_counter = hpet_get_ticks();
+                s->hpet_counter = hpet_get_ticks(s);
                 for (i = 0; i < HPET_NUM_TIMERS; i++) {
                     hpet_del_timer(&s->timer[i]);
                 }
@@ -527,7 +525,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             /* FIXME: need to handle level-triggered interrupts */
             break;
         case HPET_COUNTER:
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
@@ -536,7 +534,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     value, s->hpet_counter);
             break;
         case HPET_COUNTER + 4:
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
@@ -624,8 +622,6 @@ static int hpet_init(SysBusDevice *dev)
     int i, iomemtype;
     HPETTimer *timer;
 
-    assert(!hpet_statep);
-    hpet_statep = s;
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
commit 7d932dfdc5ebc07a7bfed9c01e587c9c7e9b6e26
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:40 2010 +0200

    hpet/rtc: Rework RTC IRQ replacement by HPET
    
    Allow the intercept the RTC IRQ for the HPET legacy mode. Then push
    routing to IRQ8 completely into the HPET. This allows to turn
    hpet_in_legacy_mode() into a private function. Furthermore, this stops
    the RTC from clearing IRQ8 even if the HPET is in control.
    
    This patch comes with a side effect: The RTC timers will no longer be
    stoppend when there is no IRQ consumer, possibly causing a minor
    performance degration. But as the guest may want to redirect the RTC to
    the SCI in that mode, it should normally disable unused IRQ source
    anyway.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 041dd84..edfe02e 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -30,6 +30,7 @@
 #include "qemu-timer.h"
 #include "hpet_emul.h"
 #include "sysbus.h"
+#include "mc146818rtc.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -58,6 +59,7 @@ typedef struct HPETState {
     SysBusDevice busdev;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint8_t rtc_irq_level;
     HPETTimer timer[HPET_NUM_TIMERS];
 
     /* Memory-mapped, software visible registers */
@@ -69,12 +71,9 @@ typedef struct HPETState {
 
 static HPETState *hpet_statep;
 
-uint32_t hpet_in_legacy_mode(void)
+static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
-    if (!hpet_statep) {
-        return 0;
-    }
-    return hpet_statep->config & HPET_CFG_LEGACY;
+    return s->config & HPET_CFG_LEGACY;
 }
 
 static uint32_t timer_int_route(struct HPETTimer *timer)
@@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
 {
     int route;
 
-    if (timer->tn <= 1 && hpet_in_legacy_mode()) {
+    if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
         /* if LegacyReplacementRoute bit is set, HPET specification requires
          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
          */
-        route = (timer->tn == 0) ? 0 : 8;
+        route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
     } else {
         route = timer_int_route(timer);
     }
@@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             /* i8254 and RTC are disabled when HPET is in legacy mode */
             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
                 hpet_pit_disable();
+                qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
                 hpet_pit_enable();
+                qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
             }
             break;
         case HPET_CFG + 4:
@@ -607,6 +608,16 @@ static void hpet_reset(DeviceState *d)
     count = 1;
 }
 
+static void hpet_handle_rtc_irq(void *opaque, int n, int level)
+{
+    HPETState *s = FROM_SYSBUS(HPETState, opaque);
+
+    s->rtc_irq_level = level;
+    if (!hpet_in_legacy_mode(s)) {
+        qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
+    }
+}
+
 static int hpet_init(SysBusDevice *dev)
 {
     HPETState *s = FROM_SYSBUS(HPETState, dev);
@@ -625,6 +636,9 @@ static int hpet_init(SysBusDevice *dev)
         timer->state = s;
     }
 
+    isa_reserve_irq(RTC_ISA_IRQ);
+    qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
+
     /* HPET Area */
     iomemtype = cpu_register_io_memory(hpet_ram_read,
                                        hpet_ram_write, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 785f850..9c268cc 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -47,8 +47,4 @@
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
 
-#if defined TARGET_I386
-extern uint32_t hpet_in_legacy_mode(void);
-#endif
-
 #endif
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index c3e6a70..c3459bf 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -27,7 +27,6 @@
 #include "pc.h"
 #include "apic.h"
 #include "isa.h"
-#include "hpet_emul.h"
 #include "mc146818rtc.h"
 
 //#define DEBUG_CMOS
@@ -101,19 +100,6 @@ typedef struct RTCState {
     QEMUTimer *second_timer2;
 } RTCState;
 
-static void rtc_irq_raise(qemu_irq irq)
-{
-    /* When HPET is operating in legacy mode, RTC interrupts are disabled
-     * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
-     * mode is established while interrupt is raised. We want it to
-     * be lowered in any case
-     */
-#if defined TARGET_I386
-    if (!hpet_in_legacy_mode())
-#endif
-        qemu_irq_raise(irq);
-}
-
 static void rtc_set_time(RTCState *s);
 static void rtc_copy_date(RTCState *s);
 
@@ -139,7 +125,7 @@ static void rtc_coalesced_timer(void *opaque)
         apic_reset_irq_delivered();
         s->cmos_data[RTC_REG_C] |= 0xc0;
         DPRINTF_C("cmos: injecting from timer\n");
-        rtc_irq_raise(s->irq);
+        qemu_irq_raise(s->irq);
         if (apic_get_irq_delivered()) {
             s->irq_coalesced--;
             DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
@@ -155,19 +141,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
     int64_t cur_clock, next_irq_clock;
-    int enable_pie;
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-#if defined TARGET_I386
-    /* disable periodic timer if hpet is in legacy mode, since interrupts are
-     * disabled anyway.
-     */
-    enable_pie = !hpet_in_legacy_mode();
-#else
-    enable_pie = 1;
-#endif
     if (period_code != 0
-        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
+        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
             || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
         if (period_code <= 2)
             period_code += 7;
@@ -206,7 +183,7 @@ static void rtc_periodic_timer(void *opaque)
             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
                 s->irq_reinject_on_ack_count = 0;		
             apic_reset_irq_delivered();
-            rtc_irq_raise(s->irq);
+            qemu_irq_raise(s->irq);
             if (!apic_get_irq_delivered()) {
                 s->irq_coalesced++;
                 rtc_coalesced_timer_update(s);
@@ -215,7 +192,7 @@ static void rtc_periodic_timer(void *opaque)
             }
         } else
 #endif
-        rtc_irq_raise(s->irq);
+        qemu_irq_raise(s->irq);
     }
     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
         /* Not square wave at all but we don't want 2048Hz interrupts!
@@ -444,15 +421,15 @@ static void rtc_update_second2(void *opaque)
              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0;
-            rtc_irq_raise(s->irq);
+            qemu_irq_raise(s->irq);
         }
     }
 
     /* update ended interrupt */
     s->cmos_data[RTC_REG_C] |= REG_C_UF;
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
-      s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-      rtc_irq_raise(s->irq);
+        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+        qemu_irq_raise(s->irq);
     }
 
     /* clear update in progress bit */
@@ -606,9 +583,6 @@ static int rtc_initfn(ISADevice *dev)
 {
     RTCState *s = DO_UPCAST(RTCState, dev, dev);
     int base = 0x70;
-    int isairq = 8;
-
-    isa_init_irq(dev, &s->irq, isairq);
 
     s->cmos_data[RTC_REG_A] = 0x26;
     s->cmos_data[RTC_REG_B] = 0x02;
@@ -638,13 +612,20 @@ static int rtc_initfn(ISADevice *dev)
     return 0;
 }
 
-ISADevice *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
 {
     ISADevice *dev;
+    RTCState *s;
 
     dev = isa_create("mc146818rtc");
+    s = DO_UPCAST(RTCState, dev, dev);
     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
     qdev_init_nofail(&dev->qdev);
+    if (intercept_irq) {
+        s->irq = intercept_irq;
+    } else {
+        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
+    }
     return dev;
 }
 
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 6f46a68..575968c 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -3,7 +3,9 @@
 
 #include "isa.h"
 
-ISADevice *rtc_init(int base_year);
+#define RTC_ISA_IRQ 8
+
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
 void rtc_set_date(ISADevice *dev, const struct tm *tm);
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index ead3a00..22db7a2 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -259,7 +259,7 @@ void mips_jazz_init (ram_addr_t ram_size,
     fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
 
     /* Real time clock */
-    rtc_init(1980);
+    rtc_init(1980, NULL);
     s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
     cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
 
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a8f9d15..23de7f0 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size,
     /* Super I/O */
     isa_dev = isa_create_simple("i8042");
  
-    rtc_state = rtc_init(2000);
+    rtc_state = rtc_init(2000, NULL);
     serial_isa_init(0, serial_hds[0]);
     serial_isa_init(1, serial_hds[1]);
     if (parallel_hds[0])
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index f1fcfcd..5a96dea 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -267,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
 
-    rtc_state = rtc_init(2000);
+    rtc_state = rtc_init(2000, NULL);
 
     /* Register 64 KB of ISA IO space at 0x14000000 */
 #ifdef TARGET_WORDS_BIGENDIAN
diff --git a/hw/pc.c b/hw/pc.c
index ae31e2e..1491129 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -943,6 +943,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     int i;
     DriveInfo *fd[MAX_FD];
     PITState *pit;
+    qemu_irq rtc_irq = NULL;
     qemu_irq *a20_line;
     ISADevice *i8042;
     qemu_irq *cpu_exit_irq;
@@ -951,19 +952,20 @@ void pc_basic_device_init(qemu_irq *isa_irq,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    *rtc_state = rtc_init(2000);
-
-    qemu_register_boot_set(pc_boot_set, *rtc_state);
-
-    pit = pit_init(0x40, isa_reserve_irq(0));
-    pcspk_init(pit);
     if (!no_hpet) {
         DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
 
         for (i = 0; i < 24; i++) {
             sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
         }
+        rtc_irq = qdev_get_gpio_in(hpet, 0);
     }
+    *rtc_state = rtc_init(2000, rtc_irq);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    pit = pit_init(0x40, isa_reserve_irq(0));
+    pcspk_init(pit);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 16c9950..bb9e15f 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -696,7 +696,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     pci_vga_init(pci_bus, 0, 0);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
     //    pit = pit_init(0x40, i8259[0]);
-    rtc_init(2000);
+    rtc_init(2000, NULL);
 
     if (serial_hds[0])
         serial_isa_init(0, serial_hds[0]);
commit 9cec89e8db494df43faf242a5a030bc6540c89dd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:39 2010 +0200

    hpet: Start/stop timer when HPET_TN_ENABLE is modified
    
    We have to update the qemu timer when the per-timer enable bit is
    toggled, just like for HPET_CFG_ENABLE changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 6974935..041dd84 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -430,6 +430,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 printf("qemu: level-triggered hpet not supported\n");
                 exit (-1);
             }
+            if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                hpet_set_timer(timer);
+            } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                hpet_del_timer(timer);
+            }
             break;
         case HPET_TN_CFG + 4: // Interrupt capabilities
             DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
commit 822557eb8ea4694d1a91b68cbf6152f5277f5599
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:38 2010 +0200

    hpet: Convert to qdev
    
    Register the HPET as a sysbus device and create it that way. As it can
    route its IRQs to any ISA IRQ, we need to connect it to all 24 of them.
    Once converted to qdev, we can move reset handler and vmstate
    registration into its hands as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index fd7a1fd..6974935 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -29,6 +29,7 @@
 #include "console.h"
 #include "qemu-timer.h"
 #include "hpet_emul.h"
+#include "sysbus.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -54,8 +55,9 @@ typedef struct HPETTimer {  /* timers */
 } HPETTimer;
 
 typedef struct HPETState {
+    SysBusDevice busdev;
     uint64_t hpet_offset;
-    qemu_irq *irqs;
+    qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     HPETTimer timer[HPET_NUM_TIMERS];
 
     /* Memory-mapped, software visible registers */
@@ -565,9 +567,9 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
     hpet_ram_writel,
 };
 
-static void hpet_reset(void *opaque)
+static void hpet_reset(DeviceState *d)
 {
-    HPETState *s = opaque;
+    HPETState *s = FROM_SYSBUS(HPETState, sysbus_from_qdev(d));
     int i;
     static int count = 0;
 
@@ -600,28 +602,43 @@ static void hpet_reset(void *opaque)
     count = 1;
 }
 
-
-void hpet_init(qemu_irq *irq)
+static int hpet_init(SysBusDevice *dev)
 {
+    HPETState *s = FROM_SYSBUS(HPETState, dev);
     int i, iomemtype;
     HPETTimer *timer;
-    HPETState *s;
-
-    DPRINTF ("hpet_init\n");
 
-    s = qemu_mallocz(sizeof(HPETState));
+    assert(!hpet_statep);
     hpet_statep = s;
-    s->irqs = irq;
+    for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
+        sysbus_init_irq(dev, &s->irqs[i]);
+    }
     for (i = 0; i < HPET_NUM_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
         timer->tn = i;
         timer->state = s;
     }
-    vmstate_register(-1, &vmstate_hpet, s);
-    qemu_register_reset(hpet_reset, s);
+
     /* HPET Area */
     iomemtype = cpu_register_io_memory(hpet_ram_read,
                                        hpet_ram_write, s);
-    cpu_register_physical_memory(HPET_BASE, 0x400, iomemtype);
+    sysbus_init_mmio(dev, 0x400, iomemtype);
+    return 0;
 }
+
+static SysBusDeviceInfo hpet_device_info = {
+    .qdev.name    = "hpet",
+    .qdev.size    = sizeof(HPETState),
+    .qdev.no_user = 1,
+    .qdev.vmsd    = &vmstate_hpet,
+    .qdev.reset   = hpet_reset,
+    .init         = hpet_init,
+};
+
+static void hpet_register_device(void)
+{
+    sysbus_register_withprop(&hpet_device_info);
+}
+
+device_init(hpet_register_device)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 2f5f8ba..785f850 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -19,6 +19,8 @@
 #define FS_PER_NS 1000000
 #define HPET_NUM_TIMERS 3
 
+#define HPET_NUM_IRQ_ROUTES     32
+
 #define HPET_CFG_ENABLE 0x001
 #define HPET_CFG_LEGACY 0x002
 
@@ -47,7 +49,6 @@
 
 #if defined TARGET_I386
 extern uint32_t hpet_in_legacy_mode(void);
-extern void hpet_init(qemu_irq *irq);
 #endif
 
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 9b85c42..ae31e2e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@
 #include "elf.h"
 #include "multiboot.h"
 #include "mc146818rtc.h"
+#include "sysbus.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -957,7 +958,11 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     pit = pit_init(0x40, isa_reserve_irq(0));
     pcspk_init(pit);
     if (!no_hpet) {
-        hpet_init(isa_irq);
+        DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
+
+        for (i = 0; i < 24; i++) {
+            sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+        }
     }
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
commit 7afbecc9efa64a88ab6194c2cf1d6feabd03d119
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:37 2010 +0200

    hpet: Move static timer field initialization
    
    Properly initialize HPETTimer::tn and HPETTimer::state once during
    hpet_init instead of (re-)writing them on every reset.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index bcb160b..fd7a1fd 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -575,12 +575,10 @@ static void hpet_reset(void *opaque)
         HPETTimer *timer = &s->timer[i];
 
         hpet_del_timer(timer);
-        timer->tn = i;
         timer->cmp = ~0ULL;
         timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
         /* advertise availability of ioapic inti2 */
         timer->config |=  0x00000004ULL << 32;
-        timer->state = s;
         timer->period = 0ULL;
         timer->wrap_flag = 0;
     }
@@ -617,6 +615,8 @@ void hpet_init(qemu_irq *irq)
     for (i = 0; i < HPET_NUM_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
+        timer->tn = i;
+        timer->state = s;
     }
     vmstate_register(-1, &vmstate_hpet, s);
     qemu_register_reset(hpet_reset, s);
commit ad0a655161a487007742b65d0b1b55aea8051cea
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:36 2010 +0200

    hpet: Silence warning on write to running main counter
    
    Setting the main counter while the HPET is enabled may not be a good
    idea of the guest, but it is supported and should, thus, not spam the
    host console with warnings.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 2836fb0..bcb160b 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -520,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_COUNTER:
             if (hpet_enabled()) {
-                printf("qemu: Writing counter while HPET enabled!\n");
+                DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
                 (s->hpet_counter & 0xffffffff00000000ULL) | value;
@@ -529,7 +529,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_COUNTER + 4:
             if (hpet_enabled()) {
-                printf("qemu: Writing counter while HPET enabled!\n");
+                DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
                 (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
commit 27bb0b2d6f80f058bdb6fcc8fcdfa69b0c8a6d71
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:35 2010 +0200

    hpet: Coding style cleanups and some refactorings
    
    This moves the private HPET structures into the C module, simplifies
    some helper functions and fixes most coding style issues (biggest chunk
    was improper switch-case indention). No functional changes.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 1980906..2836fb0 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -37,21 +37,47 @@
 #define DPRINTF(...)
 #endif
 
+struct HPETState;
+typedef struct HPETTimer {  /* timers */
+    uint8_t tn;             /*timer number*/
+    QEMUTimer *qemu_timer;
+    struct HPETState *state;
+    /* Memory-mapped, software visible timer registers */
+    uint64_t config;        /* configuration/cap */
+    uint64_t cmp;           /* comparator */
+    uint64_t fsb;           /* FSB route, not supported now */
+    /* Hidden register state */
+    uint64_t period;        /* Last value written to comparator */
+    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
+                             * mode. Next pop will be actual timer expiration.
+                             */
+} HPETTimer;
+
+typedef struct HPETState {
+    uint64_t hpet_offset;
+    qemu_irq *irqs;
+    HPETTimer timer[HPET_NUM_TIMERS];
+
+    /* Memory-mapped, software visible registers */
+    uint64_t capability;        /* capabilities */
+    uint64_t config;            /* configuration */
+    uint64_t isr;               /* interrupt status reg */
+    uint64_t hpet_counter;      /* main counter */
+} HPETState;
+
 static HPETState *hpet_statep;
 
 uint32_t hpet_in_legacy_mode(void)
 {
-    if (hpet_statep)
-        return hpet_statep->config & HPET_CFG_LEGACY;
-    else
+    if (!hpet_statep) {
         return 0;
+    }
+    return hpet_statep->config & HPET_CFG_LEGACY;
 }
 
 static uint32_t timer_int_route(struct HPETTimer *timer)
 {
-    uint32_t route;
-    route = (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
-    return route;
+    return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
 static uint32_t hpet_enabled(void)
@@ -108,9 +134,7 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
 
 static uint64_t hpet_get_ticks(void)
 {
-    uint64_t ticks;
-    ticks = ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
-    return ticks;
+    return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
 }
 
 /*
@@ -121,12 +145,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
     if (t->config & HPET_TN_32BIT) {
         uint32_t diff, cmp;
+
         cmp = (uint32_t)t->cmp;
         diff = cmp - (uint32_t)current;
         diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
         return (uint64_t)diff;
     } else {
         uint64_t diff, cmp;
+
         cmp = t->cmp;
         diff = cmp - current;
         diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
@@ -136,7 +162,6 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
 static void update_irq(struct HPETTimer *timer)
 {
-    qemu_irq irq;
     int route;
 
     if (timer->tn <= 1 && hpet_in_legacy_mode()) {
@@ -144,22 +169,20 @@ static void update_irq(struct HPETTimer *timer)
          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
          */
-        if (timer->tn == 0) {
-            irq=timer->state->irqs[0];
-        } else
-            irq=timer->state->irqs[8];
+        route = (timer->tn == 0) ? 0 : 8;
     } else {
-        route=timer_int_route(timer);
-        irq=timer->state->irqs[route];
+        route = timer_int_route(timer);
     }
-    if (timer_enabled(timer) && hpet_enabled()) {
-        qemu_irq_pulse(irq);
+    if (!timer_enabled(timer) || !hpet_enabled()) {
+        return;
     }
+    qemu_irq_pulse(timer->state->irqs[route]);
 }
 
 static void hpet_pre_save(void *opaque)
 {
     HPETState *s = opaque;
+
     /* save current counter value */
     s->hpet_counter = hpet_get_ticks();
 }
@@ -212,7 +235,7 @@ static const VMStateDescription vmstate_hpet = {
  */
 static void hpet_timer(void *opaque)
 {
-    HPETTimer *t = (HPETTimer*)opaque;
+    HPETTimer *t = opaque;
     uint64_t diff;
 
     uint64_t period = t->period;
@@ -220,20 +243,22 @@ static void hpet_timer(void *opaque)
 
     if (timer_is_periodic(t) && period != 0) {
         if (t->config & HPET_TN_32BIT) {
-            while (hpet_time_after(cur_tick, t->cmp))
+            while (hpet_time_after(cur_tick, t->cmp)) {
                 t->cmp = (uint32_t)(t->cmp + t->period);
-        } else
-            while (hpet_time_after64(cur_tick, t->cmp))
+            }
+        } else {
+            while (hpet_time_after64(cur_tick, t->cmp)) {
                 t->cmp += period;
-
+            }
+        }
         diff = hpet_calculate_diff(t, cur_tick);
-        qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                       + (int64_t)ticks_to_ns(diff));
+        qemu_mod_timer(t->qemu_timer,
+                       qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
     } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
         if (t->wrap_flag) {
             diff = hpet_calculate_diff(t, cur_tick);
-            qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                           + (int64_t)ticks_to_ns(diff));
+            qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock) +
+                           (int64_t)ticks_to_ns(diff));
             t->wrap_flag = 0;
         }
     }
@@ -260,8 +285,8 @@ static void hpet_set_timer(HPETTimer *t)
             t->wrap_flag = 1;
         }
     }
-    qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                   + (int64_t)ticks_to_ns(diff));
+    qemu_mod_timer(t->qemu_timer,
+                   qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
 }
 
 static void hpet_del_timer(HPETTimer *t)
@@ -285,7 +310,7 @@ static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
 
 static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
 {
-    HPETState *s = (HPETState *)opaque;
+    HPETState *s = opaque;
     uint64_t cur_tick, index;
 
     DPRINTF("qemu: Enter hpet_ram_readl at %" PRIx64 "\n", addr);
@@ -293,57 +318,60 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     /*address range of all TN regs*/
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
+        HPETTimer *timer = &s->timer[timer_id];
+
         if (timer_id > HPET_NUM_TIMERS - 1) {
             DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
-        HPETTimer *timer = &s->timer[timer_id];
 
         switch ((addr - 0x100) % 0x20) {
-            case HPET_TN_CFG:
-                return timer->config;
-            case HPET_TN_CFG + 4: // Interrupt capabilities
-                return timer->config >> 32;
-            case HPET_TN_CMP: // comparator register
-                return timer->cmp;
-            case HPET_TN_CMP + 4:
-                return timer->cmp >> 32;
-            case HPET_TN_ROUTE:
-                return timer->fsb >> 32;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_readl\n");
-                break;
+        case HPET_TN_CFG:
+            return timer->config;
+        case HPET_TN_CFG + 4: // Interrupt capabilities
+            return timer->config >> 32;
+        case HPET_TN_CMP: // comparator register
+            return timer->cmp;
+        case HPET_TN_CMP + 4:
+            return timer->cmp >> 32;
+        case HPET_TN_ROUTE:
+            return timer->fsb >> 32;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_readl\n");
+            break;
         }
     } else {
         switch (index) {
-            case HPET_ID:
-                return s->capability;
-            case HPET_PERIOD:
-                return s->capability >> 32;
-            case HPET_CFG:
-                return s->config;
-            case HPET_CFG + 4:
-                DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
-                return 0;
-            case HPET_COUNTER:
-                if (hpet_enabled())
-                    cur_tick = hpet_get_ticks();
-                else
-                    cur_tick = s->hpet_counter;
-                DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
-                return cur_tick;
-            case HPET_COUNTER + 4:
-                if (hpet_enabled())
-                    cur_tick = hpet_get_ticks();
-                else
-                    cur_tick = s->hpet_counter;
-                DPRINTF("qemu: reading counter + 4  = %" PRIx64 "\n", cur_tick);
-                return cur_tick >> 32;
-            case HPET_STATUS:
-                return s->isr;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_readl\n");
-                break;
+        case HPET_ID:
+            return s->capability;
+        case HPET_PERIOD:
+            return s->capability >> 32;
+        case HPET_CFG:
+            return s->config;
+        case HPET_CFG + 4:
+            DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
+            return 0;
+        case HPET_COUNTER:
+            if (hpet_enabled()) {
+                cur_tick = hpet_get_ticks();
+            } else {
+                cur_tick = s->hpet_counter;
+            }
+            DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
+            return cur_tick;
+        case HPET_COUNTER + 4:
+            if (hpet_enabled()) {
+                cur_tick = hpet_get_ticks();
+            } else {
+                cur_tick = s->hpet_counter;
+            }
+            DPRINTF("qemu: reading counter + 4  = %" PRIx64 "\n", cur_tick);
+            return cur_tick >> 32;
+        case HPET_STATUS:
+            return s->isr;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_readl\n");
+            break;
         }
     }
     return 0;
@@ -369,7 +397,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                             uint32_t value)
 {
     int i;
-    HPETState *s = (HPETState *)opaque;
+    HPETState *s = opaque;
     uint64_t old_val, new_val, val, index;
 
     DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
@@ -380,133 +408,137 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
     /*address range of all TN regs*/
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
-        DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         HPETTimer *timer = &s->timer[timer_id];
 
+        DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         if (timer_id > HPET_NUM_TIMERS - 1) {
             DPRINTF("qemu: timer id out of range\n");
             return;
         }
         switch ((addr - 0x100) % 0x20) {
-            case HPET_TN_CFG:
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
-                val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
-                timer->config = (timer->config & 0xffffffff00000000ULL) | val;
-                if (new_val & HPET_TN_32BIT) {
-                    timer->cmp = (uint32_t)timer->cmp;
-                    timer->period = (uint32_t)timer->period;
-                }
-                if (new_val & HPET_TIMER_TYPE_LEVEL) {
-                    printf("qemu: level-triggered hpet not supported\n");
-                    exit (-1);
-                }
-
-                break;
-            case HPET_TN_CFG + 4: // Interrupt capabilities
-                DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
-                break;
-            case HPET_TN_CMP: // comparator register
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
-                if (timer->config & HPET_TN_32BIT)
-                    new_val = (uint32_t)new_val;
-                if (!timer_is_periodic(timer) ||
-                           (timer->config & HPET_TN_SETVAL))
-                    timer->cmp = (timer->cmp & 0xffffffff00000000ULL)
-                                  | new_val;
-                if (timer_is_periodic(timer)) {
-                    /*
-                     * FIXME: Clamp period to reasonable min value?
-                     * Clamp period to reasonable max value
-                     */
-                    new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
-                    timer->period = (timer->period & 0xffffffff00000000ULL)
-                                     | new_val;
+        case HPET_TN_CFG:
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
+            val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
+            timer->config = (timer->config & 0xffffffff00000000ULL) | val;
+            if (new_val & HPET_TN_32BIT) {
+                timer->cmp = (uint32_t)timer->cmp;
+                timer->period = (uint32_t)timer->period;
+            }
+            if (new_val & HPET_TN_TYPE_LEVEL) {
+                printf("qemu: level-triggered hpet not supported\n");
+                exit (-1);
+            }
+            break;
+        case HPET_TN_CFG + 4: // Interrupt capabilities
+            DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
+            break;
+        case HPET_TN_CMP: // comparator register
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
+            if (timer->config & HPET_TN_32BIT) {
+                new_val = (uint32_t)new_val;
+            }
+            if (!timer_is_periodic(timer)
+                || (timer->config & HPET_TN_SETVAL)) {
+                timer->cmp = (timer->cmp & 0xffffffff00000000ULL) | new_val;
+            }
+            if (timer_is_periodic(timer)) {
+                /*
+                 * FIXME: Clamp period to reasonable min value?
+                 * Clamp period to reasonable max value
+                 */
+                new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+                timer->period =
+                    (timer->period & 0xffffffff00000000ULL) | new_val;
+            }
+            timer->config &= ~HPET_TN_SETVAL;
+            if (hpet_enabled()) {
+                hpet_set_timer(timer);
+            }
+            break;
+        case HPET_TN_CMP + 4: // comparator register high order
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
+            if (!timer_is_periodic(timer)
+                || (timer->config & HPET_TN_SETVAL)) {
+                timer->cmp = (timer->cmp & 0xffffffffULL) | new_val << 32;
+            } else {
+                /*
+                 * FIXME: Clamp period to reasonable min value?
+                 * Clamp period to reasonable max value
+                 */
+                new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+                timer->period =
+                    (timer->period & 0xffffffffULL) | new_val << 32;
                 }
                 timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled())
+                if (hpet_enabled()) {
                     hpet_set_timer(timer);
-                break;
-            case HPET_TN_CMP + 4: // comparator register high order
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
-                if (!timer_is_periodic(timer) ||
-                           (timer->config & HPET_TN_SETVAL))
-                    timer->cmp = (timer->cmp & 0xffffffffULL)
-                                  | new_val << 32;
-                else {
-                    /*
-                     * FIXME: Clamp period to reasonable min value?
-                     * Clamp period to reasonable max value
-                     */
-                    new_val &= (timer->config
-                                & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
-                    timer->period = (timer->period & 0xffffffffULL)
-                                     | new_val << 32;
                 }
-                timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled())
-                    hpet_set_timer(timer);
-                break;
-            case HPET_TN_ROUTE + 4:
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
-                break;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_writel\n");
                 break;
+        case HPET_TN_ROUTE + 4:
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+            break;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_writel\n");
+            break;
         }
         return;
     } else {
         switch (index) {
-            case HPET_ID:
-                return;
-            case HPET_CFG:
-                val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
-                s->config = (s->config & 0xffffffff00000000ULL) | val;
-                if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
-                    /* Enable main counter and interrupt generation. */
-                    s->hpet_offset = ticks_to_ns(s->hpet_counter)
-                                     - qemu_get_clock(vm_clock);
-                    for (i = 0; i < HPET_NUM_TIMERS; i++)
-                        if ((&s->timer[i])->cmp != ~0ULL)
-                            hpet_set_timer(&s->timer[i]);
-                }
-                else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
-                    /* Halt main counter and disable interrupt generation. */
-                    s->hpet_counter = hpet_get_ticks();
-                    for (i = 0; i < HPET_NUM_TIMERS; i++)
-                        hpet_del_timer(&s->timer[i]);
+        case HPET_ID:
+            return;
+        case HPET_CFG:
+            val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
+            s->config = (s->config & 0xffffffff00000000ULL) | val;
+            if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+                /* Enable main counter and interrupt generation. */
+                s->hpet_offset =
+                    ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                    if ((&s->timer[i])->cmp != ~0ULL) {
+                        hpet_set_timer(&s->timer[i]);
+                    }
                 }
-                /* i8254 and RTC are disabled when HPET is in legacy mode */
-                if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_disable();
-                } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_enable();
+            } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+                /* Halt main counter and disable interrupt generation. */
+                s->hpet_counter = hpet_get_ticks();
+                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                    hpet_del_timer(&s->timer[i]);
                 }
-                break;
-            case HPET_CFG + 4:
-                DPRINTF("qemu: invalid HPET_CFG+4 write \n");
-                break;
-            case HPET_STATUS:
-                /* FIXME: need to handle level-triggered interrupts */
-                break;
-            case HPET_COUNTER:
-               if (hpet_enabled())
-                   printf("qemu: Writing counter while HPET enabled!\n");
-               s->hpet_counter = (s->hpet_counter & 0xffffffff00000000ULL)
-                                  | value;
-               DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
-                        value, s->hpet_counter);
-               break;
-            case HPET_COUNTER + 4:
-               if (hpet_enabled())
-                   printf("qemu: Writing counter while HPET enabled!\n");
-               s->hpet_counter = (s->hpet_counter & 0xffffffffULL)
-                                  | (((uint64_t)value) << 32);
-               DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
-                        value, s->hpet_counter);
-               break;
-            default:
-               DPRINTF("qemu: invalid hpet_ram_writel\n");
-               break;
+            }
+            /* i8254 and RTC are disabled when HPET is in legacy mode */
+            if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                hpet_pit_disable();
+            } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                hpet_pit_enable();
+            }
+            break;
+        case HPET_CFG + 4:
+            DPRINTF("qemu: invalid HPET_CFG+4 write \n");
+            break;
+        case HPET_STATUS:
+            /* FIXME: need to handle level-triggered interrupts */
+            break;
+        case HPET_COUNTER:
+            if (hpet_enabled()) {
+                printf("qemu: Writing counter while HPET enabled!\n");
+            }
+            s->hpet_counter =
+                (s->hpet_counter & 0xffffffff00000000ULL) | value;
+            DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
+                    value, s->hpet_counter);
+            break;
+        case HPET_COUNTER + 4:
+            if (hpet_enabled()) {
+                printf("qemu: Writing counter while HPET enabled!\n");
+            }
+            s->hpet_counter =
+                (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
+            DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
+                    value, s->hpet_counter);
+            break;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_writel\n");
+            break;
         }
     }
 }
@@ -533,13 +565,15 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
     hpet_ram_writel,
 };
 
-static void hpet_reset(void *opaque) {
+static void hpet_reset(void *opaque)
+{
     HPETState *s = opaque;
     int i;
     static int count = 0;
 
-    for (i=0; i<HPET_NUM_TIMERS; i++) {
+    for (i = 0; i < HPET_NUM_TIMERS; i++) {
         HPETTimer *timer = &s->timer[i];
+
         hpet_del_timer(timer);
         timer->tn = i;
         timer->cmp = ~0ULL;
@@ -557,19 +591,22 @@ static void hpet_reset(void *opaque) {
     s->capability = 0x8086a201ULL;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
     s->config = 0ULL;
-    if (count > 0)
+    if (count > 0) {
         /* we don't enable pit when hpet_reset is first called (by hpet_init)
          * because hpet is taking over for pit here. On subsequent invocations,
          * hpet_reset is called due to system reset. At this point control must
          * be returned to pit until SW reenables hpet.
          */
         hpet_pit_enable();
+    }
     count = 1;
 }
 
 
-void hpet_init(qemu_irq *irq) {
+void hpet_init(qemu_irq *irq)
+{
     int i, iomemtype;
+    HPETTimer *timer;
     HPETState *s;
 
     DPRINTF ("hpet_init\n");
@@ -577,8 +614,8 @@ void hpet_init(qemu_irq *irq) {
     s = qemu_mallocz(sizeof(HPETState));
     hpet_statep = s;
     s->irqs = irq;
-    for (i=0; i<HPET_NUM_TIMERS; i++) {
-        HPETTimer *timer = &s->timer[i];
+    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+        timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
     }
     vmstate_register(-1, &vmstate_hpet, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index cfd95b4..2f5f8ba 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -18,7 +18,6 @@
 
 #define FS_PER_NS 1000000
 #define HPET_NUM_TIMERS 3
-#define HPET_TIMER_TYPE_LEVEL 0x002
 
 #define HPET_CFG_ENABLE 0x001
 #define HPET_CFG_LEGACY 0x002
@@ -33,7 +32,7 @@
 #define HPET_TN_ROUTE   0x010
 #define HPET_CFG_WRITE_MASK  0x3
 
-
+#define HPET_TN_TYPE_LEVEL       0x002
 #define HPET_TN_ENABLE           0x004
 #define HPET_TN_PERIODIC         0x008
 #define HPET_TN_PERIODIC_CAP     0x010
@@ -46,34 +45,6 @@
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
 
-struct HPETState;
-typedef struct HPETTimer {  /* timers */
-    uint8_t tn;             /*timer number*/
-    QEMUTimer *qemu_timer;
-    struct HPETState *state;
-    /* Memory-mapped, software visible timer registers */
-    uint64_t config;        /* configuration/cap */
-    uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route, not supported now */
-    /* Hidden register state */
-    uint64_t period;        /* Last value written to comparator */
-    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
-                             * mode. Next pop will be actual timer expiration.
-                             */
-} HPETTimer;
-
-typedef struct HPETState {
-    uint64_t hpet_offset;
-    qemu_irq *irqs;
-    HPETTimer timer[HPET_NUM_TIMERS];
-
-    /* Memory-mapped, software visible registers */
-    uint64_t capability;        /* capabilities */
-    uint64_t config;            /* configuration */
-    uint64_t isr;               /* interrupt status reg */
-    uint64_t hpet_counter;      /* main counter */
-} HPETState;
-
 #if defined TARGET_I386
 extern uint32_t hpet_in_legacy_mode(void);
 extern void hpet_init(qemu_irq *irq);
commit 6982d6647ea98544f76d5ef40ddc23115ff44a77
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Jun 13 14:15:34 2010 +0200

    hpet: Catch out-of-bounds timer access
    
    Also prevent out-of-bounds write access to the timers but don't spam the
    host console if it triggers.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/hpet.c b/hw/hpet.c
index 8729fb2..1980906 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -294,7 +294,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
         if (timer_id > HPET_NUM_TIMERS - 1) {
-            printf("qemu: timer id out of range\n");
+            DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
         HPETTimer *timer = &s->timer[timer_id];
@@ -383,6 +383,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
         DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         HPETTimer *timer = &s->timer[timer_id];
 
+        if (timer_id > HPET_NUM_TIMERS - 1) {
+            DPRINTF("qemu: timer id out of range\n");
+            return;
+        }
         switch ((addr - 0x100) % 0x20) {
             case HPET_TN_CFG:
                 DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
commit c3d96978d0faaa8e54003b45619ec0768147d168
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jun 11 22:58:29 2010 +0200

    configure: Fix evaluation of config-host.mak in create_config
    
    Only match on true dir variable assignments, avoid generating garbage
    due to the "# Configured with: ..." line which may contain "*dir=" as
    well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/create_config b/create_config
index 23c0cd5..0098e68 100755
--- a/create_config
+++ b/create_config
@@ -13,7 +13,7 @@ case $line in
     pkgversion=${line#*=}
     echo "#define QEMU_PKGVERSION \"$pkgversion\""
     ;;
- prefix=* | *dir=*) # directory configuration
+ prefix=* | [a-z]*dir=*) # directory configuration
     name=${line%=*}
     value=${line#*=}
     define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
commit d66ed0eae9c82b657bf7f3ea969490ad72155734
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Jun 13 12:28:21 2010 +0200

    tcg-s390: correctly detect s390 with a 64-bit kernel
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index ced4d2f..c0d8aa5 100755
--- a/configure
+++ b/configure
@@ -193,6 +193,12 @@ elif check_define __mips__ ; then
   cpu="mips"
 elif check_define __ia64__ ; then
   cpu="ia64"
+elif check_define __s390__ ; then
+  if check_define __s390x__ ; then
+    cpu="s390x"
+  else
+    cpu="s390"
+  fi
 else
   cpu=`uname -m`
 fi
commit b0cb640ac177c94af9e43a820cbb4085ac984ca1
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jun 12 05:49:30 2010 +0000

    Compile OS specific files only once for all targets
    
    OS specific files are not target dependent, so they can be compiled
    once for all targets.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 27595df..2dad0f9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -49,6 +49,8 @@ common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
 common-obj-y += readline.o console.o cursor.o async.o qemu-error.o
+common-obj-$(CONFIG_WIN32) += os-win32.o
+common-obj-$(CONFIG_POSIX) += os-posix.o
 
 common-obj-y += tcg-runtime.o host-utils.o
 common-obj-y += irq.o ioport.o input.o
@@ -144,8 +146,6 @@ hw-obj-$(CONFIG_ECC) += ecc.o
 hw-obj-$(CONFIG_NAND) += nand.o
 hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
 hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
-hw-obj-$(CONFIG_WIN32) += os-win32.o
-hw-obj-$(CONFIG_POSIX) += os-posix.o
 
 hw-obj-$(CONFIG_M48T59) += m48t59.o
 hw-obj-$(CONFIG_ESCC) += escc.o
commit ce798cf2a261eaf4186f416f150b7361d395c3a5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:31 2010 +0200

    Move set_proc_name() to OS specific files.
    
    Move handling to change process name to POSIX specific files
    plus add a better error message to cover the case where the
    feature isn't supported.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 9bae8fe..804e20c 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -37,6 +37,10 @@
 #include "net/slirp.h"
 #include "qemu-options.h"
 
+#ifdef CONFIG_LINUX
+#include <sys/prctl.h>
+#endif
+
 static struct passwd *user_pwd;
 static const char *chroot_dir;
 static int daemonize;
@@ -139,6 +143,26 @@ char *os_find_datadir(const char *argv0)
 #undef SHARE_SUFFIX
 #undef BUILD_SUFFIX
 
+void os_set_proc_name(const char *s)
+{
+#if defined(PR_SET_NAME)
+    char name[16];
+    if (!s)
+        return;
+    name[sizeof(name) - 1] = 0;
+    strncpy(name, s, sizeof(name));
+    /* Could rewrite argv[0] too, but that's a bit more complicated.
+       This simple way is enough for `top'. */
+    if (prctl(PR_SET_NAME, name)) {
+        perror("unable to change process name");
+        exit(1);
+    }
+#else
+    fprintf(stderr, "Change of process name not supported by your OS\n");
+    exit(1);
+#endif
+}
+
 /*
  * Parse OS specific command line options.
  * return 0 if option handled, -1 otherwise
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index cb210ba..ed5c058 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,6 +31,7 @@ static inline void os_host_main_loop_wait(int *timeout)
 }
 
 void os_set_line_buffering(void);
+void os_set_proc_name(const char *s);
 void os_setup_signal_handling(void);
 void os_daemonize(void);
 void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 5a97d8d..6323f7f 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -47,5 +47,6 @@ static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
 /* Win32 doesn't support line-buffering and requires size >= 2 */
 static inline void os_set_line_buffering(void) {}
+static inline void os_set_proc_name(const char *dummy) {}
 
 #endif
diff --git a/vl.c b/vl.c
index ba23e06..9cf5334 100644
--- a/vl.c
+++ b/vl.c
@@ -59,7 +59,6 @@
 #ifdef __linux__
 #include <pty.h>
 #include <malloc.h>
-#include <sys/prctl.h>
 
 #include <linux/ppdev.h>
 #include <linux/parport.h>
@@ -284,22 +283,6 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
 }
 
 /***********************************************************/
-
-static void set_proc_name(const char *s)
-{
-#if defined(__linux__) && defined(PR_SET_NAME)
-    char name[16];
-    if (!s)
-        return;
-    name[sizeof(name) - 1] = 0;
-    strncpy(name, s, sizeof(name));
-    /* Could rewrite argv[0] too, but that's a bit more complicated.
-       This simple way is enough for `top'. */
-    prctl(PR_SET_NAME, name);
-#endif    	
-}
- 
-/***********************************************************/
 /* real time host monotonic timer */
 
 /* compute with 96 bit intermediate result: (a*b)/c */
@@ -2988,7 +2971,7 @@ int main(int argc, char **argv, char **envp)
 			    exit(1);
 			}
 			p += 8;
-			set_proc_name(p);
+			os_set_proc_name(p);
 		     }	
 		 }	
                 break;
commit 9156d76331f2d51ce5b17cc945dd97788fc64c5a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:30 2010 +0200

    Move line-buffering setup to OS specific files.
    
    Move line-buffering setup to OS specific files.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 3a96c91..9bae8fe 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -298,3 +298,8 @@ void os_pidfile_error(void)
     } else
         fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
 }
+
+void os_set_line_buffering(void)
+{
+    setvbuf(stdout, NULL, _IOLBF, 0);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 8be583d..cb210ba 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,6 +30,7 @@ static inline void os_host_main_loop_wait(int *timeout)
 {
 }
 
+void os_set_line_buffering(void);
 void os_setup_signal_handling(void);
 void os_daemonize(void);
 void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 39df333..5a97d8d 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -45,5 +45,7 @@ void os_host_main_loop_wait(int *timeout);
 static inline void os_setup_signal_handling(void) {}
 static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
+/* Win32 doesn't support line-buffering and requires size >= 2 */
+static inline void os_set_line_buffering(void) {}
 
 #endif
diff --git a/vl.c b/vl.c
index cadd988..ba23e06 100644
--- a/vl.c
+++ b/vl.c
@@ -3215,10 +3215,7 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-#ifndef _WIN32
-    /* Win32 doesn't support line-buffering and requires size >= 2 */
-    setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
+    os_set_line_buffering();
 
     if (init_timer_alarm() < 0) {
         fprintf(stderr, "could not initialize alarm timer\n");
commit e06eb601b098d9bcb32eb1ce5e00920d638c6d51
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:29 2010 +0200

    Make os_change_process_uid and os_change_root os-posix.c local
    
    os_change_process_uid() and os_change_root() are now only called
    from os-posix.c, so no need to keep win32 stubs for them.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 1672e06..3a96c91 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -169,7 +169,7 @@ void os_parse_cmd_args(int index, const char *optarg)
     return;
 }
 
-void os_change_process_uid(void)
+static void change_process_uid(void)
 {
     if (user_pwd) {
         if (setgid(user_pwd->pw_gid) < 0) {
@@ -187,7 +187,7 @@ void os_change_process_uid(void)
     }
 }
 
-void os_change_root(void)
+static void change_root(void)
 {
     if (chroot_dir) {
         if (chroot(chroot_dir) < 0) {
@@ -276,8 +276,8 @@ void os_setup_post(void)
 	    exit(1);
     }
 
-    os_change_root();
-    os_change_process_uid();
+    change_root();
+    change_process_uid();
 
     if (daemonize) {
         dup2(fd, 0);
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 9b07660..8be583d 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,8 +31,6 @@ static inline void os_host_main_loop_wait(int *timeout)
 }
 
 void os_setup_signal_handling(void);
-void os_change_process_uid(void);
-void os_change_root(void);
 void os_daemonize(void);
 void os_setup_post(void);
 
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index c4aa84a..39df333 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -43,8 +43,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 void os_host_main_loop_wait(int *timeout);
 
 static inline void os_setup_signal_handling(void) {}
-static inline void os_change_process_uid(void) {}
-static inline void os_change_root(void) {}
 static inline void os_daemonize(void) {}
 static inline void os_setup_post(void) {}
 
commit eb505be11b18b09c621dfb19a4e3b5f703c69eeb
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:28 2010 +0200

    Move daemonize handling to OS specific files
    
    Move daemonize handling from vl.c to OS specific files. Provide dummy
    stubs for Win32.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 6417d16..1672e06 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -39,6 +39,8 @@
 
 static struct passwd *user_pwd;
 static const char *chroot_dir;
+static int daemonize;
+static int fds[2];
 
 void os_setup_early_signal_handling(void)
 {
@@ -160,6 +162,9 @@ void os_parse_cmd_args(int index, const char *optarg)
     case QEMU_OPTION_chroot:
         chroot_dir = optarg;
         break;
+    case QEMU_OPTION_daemonize:
+        daemonize = 1;
+        break;
     }
     return;
 }
@@ -196,3 +201,100 @@ void os_change_root(void)
     }
 
 }
+
+void os_daemonize(void)
+{
+    if (daemonize) {
+	pid_t pid;
+
+	if (pipe(fds) == -1)
+	    exit(1);
+
+	pid = fork();
+	if (pid > 0) {
+	    uint8_t status;
+	    ssize_t len;
+
+	    close(fds[1]);
+
+	again:
+            len = read(fds[0], &status, 1);
+            if (len == -1 && (errno == EINTR))
+                goto again;
+
+            if (len != 1)
+                exit(1);
+            else if (status == 1) {
+                fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
+                exit(1);
+            } else
+                exit(0);
+	} else if (pid < 0)
+            exit(1);
+
+	close(fds[0]);
+	qemu_set_cloexec(fds[1]);
+
+	setsid();
+
+	pid = fork();
+	if (pid > 0)
+	    exit(0);
+	else if (pid < 0)
+	    exit(1);
+
+	umask(027);
+
+        signal(SIGTSTP, SIG_IGN);
+        signal(SIGTTOU, SIG_IGN);
+        signal(SIGTTIN, SIG_IGN);
+    }
+}
+
+void os_setup_post(void)
+{
+    int fd = 0;
+
+    if (daemonize) {
+	uint8_t status = 0;
+	ssize_t len;
+
+    again1:
+	len = write(fds[1], &status, 1);
+	if (len == -1 && (errno == EINTR))
+	    goto again1;
+
+	if (len != 1)
+	    exit(1);
+
+        if (chdir("/")) {
+            perror("not able to chdir to /");
+            exit(1);
+        }
+	TFR(fd = qemu_open("/dev/null", O_RDWR));
+	if (fd == -1)
+	    exit(1);
+    }
+
+    os_change_root();
+    os_change_process_uid();
+
+    if (daemonize) {
+        dup2(fd, 0);
+        dup2(fd, 1);
+        dup2(fd, 2);
+
+        close(fd);
+    }
+}
+
+void os_pidfile_error(void)
+{
+    if (daemonize) {
+        uint8_t status = 1;
+        if (write(fds[1], &status, 1) != 1) {
+            perror("daemonize. Writing to pipe\n");
+        }
+    } else
+        fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+}
diff --git a/os-win32.c b/os-win32.c
index aefc535..d98fd77 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -214,3 +214,8 @@ void os_parse_cmd_args(int index, const char *optarg)
 {
     return;
 }
+
+void os_pidfile_error(void)
+{
+    fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 91c7b68..9b07660 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -33,5 +33,7 @@ static inline void os_host_main_loop_wait(int *timeout)
 void os_setup_signal_handling(void);
 void os_change_process_uid(void);
 void os_change_root(void);
+void os_daemonize(void);
+void os_setup_post(void);
 
 #endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index e2a97d2..c4aa84a 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -45,5 +45,7 @@ void os_host_main_loop_wait(int *timeout);
 static inline void os_setup_signal_handling(void) {}
 static inline void os_change_process_uid(void) {}
 static inline void os_change_root(void) {}
+static inline void os_daemonize(void) {}
+static inline void os_setup_post(void) {}
 
 #endif
diff --git a/sysemu.h b/sysemu.h
index 2162b1d..346cccd 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -83,6 +83,7 @@ void do_info_slirp(Monitor *mon);
 void os_setup_early_signal_handling(void);
 char *os_find_datadir(const char *argv0);
 void os_parse_cmd_args(int index, const char *optarg);
+void os_pidfile_error(void);
 
 typedef enum DisplayType
 {
diff --git a/vl.c b/vl.c
index a536784..cadd988 100644
--- a/vl.c
+++ b/vl.c
@@ -216,9 +216,6 @@ int no_shutdown = 0;
 int cursor_hide = 1;
 int graphic_rotate = 0;
 uint8_t irq0override = 1;
-#ifndef _WIN32
-int daemonize = 0;
-#endif
 const char *watchdog;
 const char *option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
@@ -2301,15 +2298,9 @@ int main(int argc, char **argv, char **envp)
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-#ifndef _WIN32
-    int fds[2];
-#endif
     int tb_size;
     const char *pid_file = NULL;
     const char *incoming = NULL;
-#ifndef _WIN32
-    int fd = 0;
-#endif
     int show_vnc_port = 0;
     int defconfig = 1;
 
@@ -2975,11 +2966,6 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
-#ifndef _WIN32
-	    case QEMU_OPTION_daemonize:
-		daemonize = 1;
-		break;
-#endif
 	    case QEMU_OPTION_option_rom:
 		if (nb_option_roms >= MAX_OPTION_ROMS) {
 		    fprintf(stderr, "Too many option ROMs\n");
@@ -3194,64 +3180,10 @@ int main(int argc, char **argv, char **envp)
     }
 #endif
 
-#ifndef _WIN32
-    if (daemonize) {
-	pid_t pid;
-
-	if (pipe(fds) == -1)
-	    exit(1);
-
-	pid = fork();
-	if (pid > 0) {
-	    uint8_t status;
-	    ssize_t len;
-
-	    close(fds[1]);
-
-	again:
-            len = read(fds[0], &status, 1);
-            if (len == -1 && (errno == EINTR))
-                goto again;
-
-            if (len != 1)
-                exit(1);
-            else if (status == 1) {
-                fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
-                exit(1);
-            } else
-                exit(0);
-	} else if (pid < 0)
-            exit(1);
-
-	close(fds[0]);
-	qemu_set_cloexec(fds[1]);
-
-	setsid();
-
-	pid = fork();
-	if (pid > 0)
-	    exit(0);
-	else if (pid < 0)
-	    exit(1);
-
-	umask(027);
-
-        signal(SIGTSTP, SIG_IGN);
-        signal(SIGTTOU, SIG_IGN);
-        signal(SIGTTIN, SIG_IGN);
-    }
-#endif
+    os_daemonize();
 
     if (pid_file && qemu_create_pidfile(pid_file) != 0) {
-#ifndef _WIN32
-        if (daemonize) {
-            uint8_t status = 1;
-            if (write(fds[1], &status, 1) != 1) {
-                perror("daemonize. Writing to pipe\n");
-            }
-        } else
-#endif
-            fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+        os_pidfile_error();
         exit(1);
     }
 
@@ -3520,39 +3452,7 @@ int main(int argc, char **argv, char **envp)
         vm_start();
     }
 
-#ifndef _WIN32
-    if (daemonize) {
-	uint8_t status = 0;
-	ssize_t len;
-
-    again1:
-	len = write(fds[1], &status, 1);
-	if (len == -1 && (errno == EINTR))
-	    goto again1;
-
-	if (len != 1)
-	    exit(1);
-
-        if (chdir("/")) {
-            perror("not able to chdir to /");
-            exit(1);
-        }
-	TFR(fd = qemu_open("/dev/null", O_RDWR));
-	if (fd == -1)
-	    exit(1);
-    }
-
-    os_change_root();
-    os_change_process_uid();
-
-    if (daemonize) {
-        dup2(fd, 0);
-        dup2(fd, 1);
-        dup2(fd, 2);
-
-        close(fd);
-    }
-#endif
+    os_setup_post();
 
     main_loop();
     quit_timers();
commit 0766379d4c58c5c1edc6adc414bfb25fc979b083
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:27 2010 +0200

    Move chroot handling to OS specific files.
    
    Move chroot handling to OS specific files.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 8b686a4..6417d16 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -38,6 +38,7 @@
 #include "qemu-options.h"
 
 static struct passwd *user_pwd;
+static const char *chroot_dir;
 
 void os_setup_early_signal_handling(void)
 {
@@ -156,6 +157,9 @@ void os_parse_cmd_args(int index, const char *optarg)
             exit(1);
         }
         break;
+    case QEMU_OPTION_chroot:
+        chroot_dir = optarg;
+        break;
     }
     return;
 }
@@ -177,3 +181,18 @@ void os_change_process_uid(void)
         }
     }
 }
+
+void os_change_root(void)
+{
+    if (chroot_dir) {
+        if (chroot(chroot_dir) < 0) {
+            fprintf(stderr, "chroot failed\n");
+            exit(1);
+        }
+        if (chdir("/")) {
+            perror("not able to chdir to /");
+            exit(1);
+        }
+    }
+
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 6d8cf79..91c7b68 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -32,5 +32,6 @@ static inline void os_host_main_loop_wait(int *timeout)
 
 void os_setup_signal_handling(void);
 void os_change_process_uid(void);
+void os_change_root(void);
 
 #endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 70fdca5..e2a97d2 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -44,5 +44,6 @@ void os_host_main_loop_wait(int *timeout);
 
 static inline void os_setup_signal_handling(void) {}
 static inline void os_change_process_uid(void) {}
+static inline void os_change_root(void) {}
 
 #endif
diff --git a/vl.c b/vl.c
index 723154b..a536784 100644
--- a/vl.c
+++ b/vl.c
@@ -2309,7 +2309,6 @@ int main(int argc, char **argv, char **envp)
     const char *incoming = NULL;
 #ifndef _WIN32
     int fd = 0;
-    const char *chroot_dir = NULL;
 #endif
     int show_vnc_port = 0;
     int defconfig = 1;
@@ -3053,11 +3052,6 @@ int main(int argc, char **argv, char **envp)
                 default_cdrom = 0;
                 default_sdcard = 0;
                 break;
-#ifndef _WIN32
-            case QEMU_OPTION_chroot:
-                chroot_dir = optarg;
-                break;
-#endif
             case QEMU_OPTION_xen_domid:
                 if (!(xen_available())) {
                     printf("Option %s not supported for this target\n", popt->name);
@@ -3548,17 +3542,7 @@ int main(int argc, char **argv, char **envp)
 	    exit(1);
     }
 
-    if (chroot_dir) {
-        if (chroot(chroot_dir) < 0) {
-            fprintf(stderr, "chroot failed\n");
-            exit(1);
-        }
-        if (chdir("/")) {
-            perror("not able to chdir to /");
-            exit(1);
-        }
-    }
-
+    os_change_root();
     os_change_process_uid();
 
     if (daemonize) {
commit 8847cfe8aa9d8f6b8648aafd5d929a57d836cc61
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:26 2010 +0200

    Move runas handling from vl.c to OS specific files.
    
    Move code to handle runas, ie. change of user id of QEMU process
    to OS specific files and provide dummy stub for Win32.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 0deddf3..8b686a4 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -28,6 +28,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <pwd.h>
 #include <libgen.h>
 
 /* Needed early for CONFIG_BSD etc. */
@@ -36,6 +37,8 @@
 #include "net/slirp.h"
 #include "qemu-options.h"
 
+static struct passwd *user_pwd;
+
 void os_setup_early_signal_handling(void)
 {
     struct sigaction act;
@@ -146,6 +149,31 @@ void os_parse_cmd_args(int index, const char *optarg)
             exit(1);
         break;
 #endif
+    case QEMU_OPTION_runas:
+        user_pwd = getpwnam(optarg);
+        if (!user_pwd) {
+            fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
+            exit(1);
+        }
+        break;
     }
     return;
 }
+
+void os_change_process_uid(void)
+{
+    if (user_pwd) {
+        if (setgid(user_pwd->pw_gid) < 0) {
+            fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
+            exit(1);
+        }
+        if (setuid(user_pwd->pw_uid) < 0) {
+            fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
+            exit(1);
+        }
+        if (setuid(0) != -1) {
+            fprintf(stderr, "Dropping privileges failed\n");
+            exit(1);
+        }
+    }
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index ff5adb1..6d8cf79 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,5 +31,6 @@ static inline void os_host_main_loop_wait(int *timeout)
 }
 
 void os_setup_signal_handling(void);
+void os_change_process_uid(void);
 
 #endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index e7e2ee3..70fdca5 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -43,5 +43,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 void os_host_main_loop_wait(int *timeout);
 
 static inline void os_setup_signal_handling(void) {}
+static inline void os_change_process_uid(void) {}
 
 #endif
diff --git a/vl.c b/vl.c
index b08b5ad..723154b 100644
--- a/vl.c
+++ b/vl.c
@@ -34,7 +34,6 @@
 
 #ifndef _WIN32
 #include <libgen.h>
-#include <pwd.h>
 #include <sys/times.h>
 #include <sys/wait.h>
 #include <termios.h>
@@ -2310,9 +2309,7 @@ int main(int argc, char **argv, char **envp)
     const char *incoming = NULL;
 #ifndef _WIN32
     int fd = 0;
-    struct passwd *pwd = NULL;
     const char *chroot_dir = NULL;
-    const char *run_as = NULL;
 #endif
     int show_vnc_port = 0;
     int defconfig = 1;
@@ -3060,9 +3057,6 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_chroot:
                 chroot_dir = optarg;
                 break;
-            case QEMU_OPTION_runas:
-                run_as = optarg;
-                break;
 #endif
             case QEMU_OPTION_xen_domid:
                 if (!(xen_available())) {
@@ -3554,14 +3548,6 @@ int main(int argc, char **argv, char **envp)
 	    exit(1);
     }
 
-    if (run_as) {
-        pwd = getpwnam(run_as);
-        if (!pwd) {
-            fprintf(stderr, "User \"%s\" doesn't exist\n", run_as);
-            exit(1);
-        }
-    }
-
     if (chroot_dir) {
         if (chroot(chroot_dir) < 0) {
             fprintf(stderr, "chroot failed\n");
@@ -3573,20 +3559,7 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
-    if (run_as) {
-        if (setgid(pwd->pw_gid) < 0) {
-            fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
-            exit(1);
-        }
-        if (setuid(pwd->pw_uid) < 0) {
-            fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
-            exit(1);
-        }
-        if (setuid(0) != -1) {
-            fprintf(stderr, "Dropping privileges failed\n");
-            exit(1);
-        }
-    }
+    os_change_process_uid();
 
     if (daemonize) {
         dup2(fd, 0);
commit 59a5264b994343f01d19faf95c0e5df70346ded8
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:25 2010 +0200

    Introduce OS specific cmdline argument handling and move SMB arg to os-posix.c
    
    Introduce OS specific cmdline argument handling by calling
    os_parse_cmd_args() at the end of switch() statement. Move option
    enum to qemu-options.h and have it included from os-posix.c and
    os-win32.c in addition to vl.c.
    
    In addition move SMB argument to os-posix.c
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 124afe7..27595df 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -259,6 +259,8 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 
 vl.o: qemu-options.def
+os-posix.o: qemu-options.def
+os-win32.o: qemu-options.def
 
 qemu-options.def: $(SRC_PATH)/qemu-options.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
diff --git a/os-posix.c b/os-posix.c
index 621ad06..0deddf3 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -33,6 +33,8 @@
 /* Needed early for CONFIG_BSD etc. */
 #include "config-host.h"
 #include "sysemu.h"
+#include "net/slirp.h"
+#include "qemu-options.h"
 
 void os_setup_early_signal_handling(void)
 {
@@ -130,3 +132,20 @@ char *os_find_datadir(const char *argv0)
 }
 #undef SHARE_SUFFIX
 #undef BUILD_SUFFIX
+
+/*
+ * Parse OS specific command line options.
+ * return 0 if option handled, -1 otherwise
+ */
+void os_parse_cmd_args(int index, const char *optarg)
+{
+    switch (index) {
+#ifdef CONFIG_SLIRP
+    case QEMU_OPTION_smb:
+        if (net_slirp_smb(optarg) < 0)
+            exit(1);
+        break;
+#endif
+    }
+    return;
+}
diff --git a/os-win32.c b/os-win32.c
index 1758538..aefc535 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -31,6 +31,7 @@
 #include <sys/time.h>
 #include "config-host.h"
 #include "sysemu.h"
+#include "qemu-options.h"
 
 /***********************************************************/
 /* Polling handling */
@@ -204,3 +205,12 @@ char *os_find_datadir(const char *argv0)
     }
     return NULL;
 }
+
+/*
+ * Parse OS specific command line options.
+ * return 0 if option handled, -1 otherwise
+ */
+void os_parse_cmd_args(int index, const char *optarg)
+{
+    return;
+}
diff --git a/qemu-options.h b/qemu-options.h
new file mode 100644
index 0000000..c96f994
--- /dev/null
+++ b/qemu-options.h
@@ -0,0 +1,41 @@
+/*
+ * qemu-options.h
+ *
+ * Defines needed for command line argument processing.
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * 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 _QEMU_OPTIONS_H_
+#define _QEMU_OPTIONS_H_
+
+enum {
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
+    opt_enum,
+#define DEFHEADING(text)
+#include "qemu-options.def"
+#undef DEF
+#undef DEFHEADING
+#undef GEN_DOCS
+};
+
+#endif
diff --git a/sysemu.h b/sysemu.h
index 72f3734..2162b1d 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -82,6 +82,7 @@ void do_info_slirp(Monitor *mon);
 /* OS specific functions */
 void os_setup_early_signal_handling(void);
 char *os_find_datadir(const char *argv0);
+void os_parse_cmd_args(int index, const char *optarg);
 
 typedef enum DisplayType
 {
diff --git a/vl.c b/vl.c
index 4998e87..b08b5ad 100644
--- a/vl.c
+++ b/vl.c
@@ -148,6 +148,7 @@ int main(int argc, char **argv)
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qemu-objects.h"
+#include "qemu-options.h"
 #ifdef CONFIG_LINUX
 #include "fsdev/qemu-fsdev.h"
 #endif
@@ -1899,16 +1900,6 @@ static void help(int exitcode)
 
 #define HAS_ARG 0x0001
 
-enum {
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
-    opt_enum,
-#define DEFHEADING(text)
-#include "qemu-options.def"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
-};
-
 typedef struct QEMUOption {
     const char *name;
     int flags;
@@ -2624,12 +2615,6 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_bootp:
                 legacy_bootp_filename = optarg;
                 break;
-#ifndef _WIN32
-            case QEMU_OPTION_smb:
-                if (net_slirp_smb(optarg) < 0)
-                    exit(1);
-                break;
-#endif
             case QEMU_OPTION_redir:
                 if (net_slirp_redir(optarg) < 0)
                     exit(1);
@@ -3126,6 +3111,8 @@ int main(int argc, char **argv, char **envp)
                     fclose(fp);
                     break;
                 }
+            default:
+                os_parse_cmd_args(popt->index, optarg);
             }
         }
     }
commit 9f16732a062fc7a3ffc5909dc681f05455cfdabc
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:24 2010 +0200

    Rename qemu-options.h to qemu-options.def
    
    Rename qemu-options.h to qemu-options.def as it is not a header file
    for general use and this leaves space for a proper qemu-options.h
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 2d94677..124afe7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -258,8 +258,8 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 
 vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
 
-vl.o: qemu-options.h
+vl.o: qemu-options.def
 
-qemu-options.h: $(SRC_PATH)/qemu-options.hx
+qemu-options.def: $(SRC_PATH)/qemu-options.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
diff --git a/vl.c b/vl.c
index 484cc44..4998e87 100644
--- a/vl.c
+++ b/vl.c
@@ -1875,7 +1875,7 @@ static void help(int exitcode)
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
         opt_help
 #define DEFHEADING(text) stringify(text) "\n"
-#include "qemu-options.h"
+#include "qemu-options.def"
 #undef DEF
 #undef DEFHEADING
 #undef GEN_DOCS
@@ -1903,7 +1903,7 @@ enum {
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
     opt_enum,
 #define DEFHEADING(text)
-#include "qemu-options.h"
+#include "qemu-options.def"
 #undef DEF
 #undef DEFHEADING
 #undef GEN_DOCS
@@ -1921,7 +1921,7 @@ static const QEMUOption qemu_options[] = {
 #define DEF(option, opt_arg, opt_enum, opt_help, arch_mask)     \
     { option, opt_arg, opt_enum, arch_mask },
 #define DEFHEADING(text)
-#include "qemu-options.h"
+#include "qemu-options.def"
 #undef DEF
 #undef DEFHEADING
 #undef GEN_DOCS
commit 6170540b824635a29eb7a0360affac9394c84c52
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:23 2010 +0200

    Move find_datadir to OS specific files.
    
    This moves the win32 and POSIX versions of find_datadir() to OS
    specific files, and removes some #ifdef clutter from vl.c
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 01dbec2..621ad06 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -28,6 +28,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <libgen.h>
 
 /* Needed early for CONFIG_BSD etc. */
 #include "config-host.h"
@@ -66,3 +67,66 @@ void os_setup_signal_handling(void)
     act.sa_flags = SA_NOCLDSTOP;
     sigaction(SIGCHLD, &act, NULL);
 }
+
+/* Find a likely location for support files using the location of the binary.
+   For installed binaries this will be "$bindir/../share/qemu".  When
+   running from the build tree this will be "$bindir/../pc-bios".  */
+#define SHARE_SUFFIX "/share/qemu"
+#define BUILD_SUFFIX "/pc-bios"
+char *os_find_datadir(const char *argv0)
+{
+    char *dir;
+    char *p = NULL;
+    char *res;
+    char buf[PATH_MAX];
+    size_t max_len;
+
+#if defined(__linux__)
+    {
+        int len;
+        len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+        if (len > 0) {
+            buf[len] = 0;
+            p = buf;
+        }
+    }
+#elif defined(__FreeBSD__)
+    {
+        static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+        size_t len = sizeof(buf) - 1;
+
+        *buf = '\0';
+        if (!sysctl(mib, sizeof(mib)/sizeof(*mib), buf, &len, NULL, 0) &&
+            *buf) {
+            buf[sizeof(buf) - 1] = '\0';
+            p = buf;
+        }
+    }
+#endif
+    /* If we don't have any way of figuring out the actual executable
+       location then try argv[0].  */
+    if (!p) {
+        p = realpath(argv0, buf);
+        if (!p) {
+            return NULL;
+        }
+    }
+    dir = dirname(p);
+    dir = dirname(dir);
+
+    max_len = strlen(dir) +
+        MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
+    res = qemu_mallocz(max_len);
+    snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+    if (access(res, R_OK)) {
+        snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
+        if (access(res, R_OK)) {
+            qemu_free(res);
+            res = NULL;
+        }
+    }
+
+    return res;
+}
+#undef SHARE_SUFFIX
+#undef BUILD_SUFFIX
diff --git a/os-win32.c b/os-win32.c
index a936f7a..1758538 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -181,3 +181,26 @@ void os_setup_early_signal_handling(void)
         }
     }
 }
+
+/* Look for support files in the same directory as the executable.  */
+char *os_find_datadir(const char *argv0)
+{
+    char *p;
+    char buf[MAX_PATH];
+    DWORD len;
+
+    len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
+    if (len == 0) {
+        return NULL;
+    }
+
+    buf[len] = 0;
+    p = buf + len - 1;
+    while (p != buf && *p != '\\')
+        p--;
+    *p = 0;
+    if (access(buf, R_OK) == 0) {
+        return qemu_strdup(buf);
+    }
+    return NULL;
+}
diff --git a/sysemu.h b/sysemu.h
index bb05cf4..72f3734 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,7 +79,9 @@ int qemu_loadvm_state(QEMUFile *f);
 /* SLIRP */
 void do_info_slirp(Monitor *mon);
 
+/* OS specific functions */
 void os_setup_early_signal_handling(void);
+char *os_find_datadir(const char *argv0);
 
 typedef enum DisplayType
 {
diff --git a/vl.c b/vl.c
index 807da7b..484cc44 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,95 +1986,6 @@ static int balloon_parse(const char *arg)
     return -1;
 }
 
-#ifdef _WIN32
-/* Look for support files in the same directory as the executable.  */
-static char *find_datadir(const char *argv0)
-{
-    char *p;
-    char buf[MAX_PATH];
-    DWORD len;
-
-    len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
-    if (len == 0) {
-        return NULL;
-    }
-
-    buf[len] = 0;
-    p = buf + len - 1;
-    while (p != buf && *p != '\\')
-        p--;
-    *p = 0;
-    if (access(buf, R_OK) == 0) {
-        return qemu_strdup(buf);
-    }
-    return NULL;
-}
-#else /* !_WIN32 */
-
-/* Find a likely location for support files using the location of the binary.
-   For installed binaries this will be "$bindir/../share/qemu".  When
-   running from the build tree this will be "$bindir/../pc-bios".  */
-#define SHARE_SUFFIX "/share/qemu"
-#define BUILD_SUFFIX "/pc-bios"
-static char *find_datadir(const char *argv0)
-{
-    char *dir;
-    char *p = NULL;
-    char *res;
-    char buf[PATH_MAX];
-    size_t max_len;
-
-#if defined(__linux__)
-    {
-        int len;
-        len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
-        if (len > 0) {
-            buf[len] = 0;
-            p = buf;
-        }
-    }
-#elif defined(__FreeBSD__)
-    {
-        static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
-        size_t len = sizeof(buf) - 1;
-
-        *buf = '\0';
-        if (!sysctl(mib, sizeof(mib)/sizeof(*mib), buf, &len, NULL, 0) &&
-            *buf) {
-            buf[sizeof(buf) - 1] = '\0';
-            p = buf;
-        }
-    }
-#endif
-    /* If we don't have any way of figuring out the actual executable
-       location then try argv[0].  */
-    if (!p) {
-        p = realpath(argv0, buf);
-        if (!p) {
-            return NULL;
-        }
-    }
-    dir = dirname(p);
-    dir = dirname(dir);
-
-    max_len = strlen(dir) +
-        MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
-    res = qemu_mallocz(max_len);
-    snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
-    if (access(res, R_OK)) {
-        snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
-        if (access(res, R_OK)) {
-            qemu_free(res);
-            res = NULL;
-        }
-    }
-
-    return res;
-}
-#undef SHARE_SUFFIX
-#undef BUILD_SUFFIX
-#endif
-
 char *qemu_find_file(int type, const char *name)
 {
     int len;
@@ -3223,7 +3134,7 @@ int main(int argc, char **argv, char **envp)
     /* If no data_dir is specified then try to find it relative to the
        executable path.  */
     if (!data_dir) {
-        data_dir = find_datadir(argv[0]);
+        data_dir = os_find_datadir(argv[0]);
     }
     /* If all else fails use the install patch specified when building.  */
     if (!data_dir) {
commit 8d963e6ae700b2a46dd3a2bde5d1e5f925702f47
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:22 2010 +0200

    Move main signal handler setup to os specificfiles.
    
    Move main signal handler setup to os specific files.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 948f662..01dbec2 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 /* Needed early for CONFIG_BSD etc. */
 #include "config-host.h"
@@ -39,3 +41,28 @@ void os_setup_early_signal_handling(void)
     act.sa_handler = SIG_IGN;
     sigaction(SIGPIPE, &act, NULL);
 }
+
+static void termsig_handler(int signal)
+{
+    qemu_system_shutdown_request();
+}
+
+static void sigchld_handler(int signal)
+{
+    waitpid(-1, NULL, WNOHANG);
+}
+
+void os_setup_signal_handling(void)
+{
+    struct sigaction act;
+
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = termsig_handler;
+    sigaction(SIGINT,  &act, NULL);
+    sigaction(SIGHUP,  &act, NULL);
+    sigaction(SIGTERM, &act, NULL);
+
+    act.sa_handler = sigchld_handler;
+    act.sa_flags = SA_NOCLDSTOP;
+    sigaction(SIGCHLD, &act, NULL);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 96d1036..ff5adb1 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,4 +30,6 @@ static inline void os_host_main_loop_wait(int *timeout)
 {
 }
 
+void os_setup_signal_handling(void);
+
 #endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 4d1cac8..e7e2ee3 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -41,4 +41,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 
 void os_host_main_loop_wait(int *timeout);
+
+static inline void os_setup_signal_handling(void) {}
+
 #endif
diff --git a/vl.c b/vl.c
index 4fcedbf..807da7b 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,35 +1986,6 @@ static int balloon_parse(const char *arg)
     return -1;
 }
 
-#ifndef _WIN32
-
-static void termsig_handler(int signal)
-{
-    qemu_system_shutdown_request();
-}
-
-static void sigchld_handler(int signal)
-{
-    waitpid(-1, NULL, WNOHANG);
-}
-
-static void sighandler_setup(void)
-{
-    struct sigaction act;
-
-    memset(&act, 0, sizeof(act));
-    act.sa_handler = termsig_handler;
-    sigaction(SIGINT,  &act, NULL);
-    sigaction(SIGHUP,  &act, NULL);
-    sigaction(SIGTERM, &act, NULL);
-
-    act.sa_handler = sigchld_handler;
-    act.sa_flags = SA_NOCLDSTOP;
-    sigaction(SIGCHLD, &act, NULL);
-}
-
-#endif
-
 #ifdef _WIN32
 /* Look for support files in the same directory as the executable.  */
 static char *find_datadir(const char *argv0)
@@ -3556,10 +3527,8 @@ int main(int argc, char **argv, char **envp)
 
     cpu_synchronize_all_post_init();
 
-#ifndef _WIN32
     /* must be after terminal init, SDL library changes signal handlers */
-    sighandler_setup();
-#endif
+    os_setup_signal_handling();
 
     set_numa_modes();
 
commit fe98ac146109e307d7e19486dcfebbc89259d34d
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:21 2010 +0200

    Rename os_setup_signal_handling() to os_setup_early_signal_handling()
    
    Rename os_setup_signal_handling() to os_setup_early_signal_handling()
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-posix.c b/os-posix.c
index 914a4d1..948f662 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -31,7 +31,7 @@
 #include "config-host.h"
 #include "sysemu.h"
 
-void os_setup_signal_handling(void)
+void os_setup_early_signal_handling(void)
 {
     struct sigaction act;
     sigfillset(&act.sa_mask);
diff --git a/os-win32.c b/os-win32.c
index dfa90bc..a936f7a 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -159,7 +159,7 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type)
     return TRUE;
 }
 
-void os_setup_signal_handling(void)
+void os_setup_early_signal_handling(void)
 {
     /* Note: cpu_interrupt() is currently not SMP safe, so we force
        QEMU to run on a single CPU */
diff --git a/sysemu.h b/sysemu.h
index e3643ad..bb05cf4 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,7 +79,7 @@ int qemu_loadvm_state(QEMUFile *f);
 /* SLIRP */
 void do_info_slirp(Monitor *mon);
 
-void os_setup_signal_handling(void);
+void os_setup_early_signal_handling(void);
 
 typedef enum DisplayType
 {
diff --git a/vl.c b/vl.c
index 8638c62..4fcedbf 100644
--- a/vl.c
+++ b/vl.c
@@ -2451,7 +2451,7 @@ int main(int argc, char **argv, char **envp)
     qemu_cache_utils_init(envp);
 
     QLIST_INIT (&vm_change_state_head);
-    os_setup_signal_handling();
+    os_setup_early_signal_handling();
 
     module_call_init(MODULE_INIT_MACHINE);
     machine = find_default_machine();
commit 69bd73b1b027f56ad68ac83aa5628c89fa05c10f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:20 2010 +0200

    Move win32 early signal handling setup to os_setup_signal_handling()
    
    Move win32 early signal handling setup to os_setup_signal_handling()
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-win32.c b/os-win32.c
index 1f7e28b..dfa90bc 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -152,3 +152,32 @@ void os_host_main_loop_wait(int *timeout)
 
     *timeout = 0;
 }
+
+static BOOL WINAPI qemu_ctrl_handler(DWORD type)
+{
+    exit(STATUS_CONTROL_C_EXIT);
+    return TRUE;
+}
+
+void os_setup_signal_handling(void)
+{
+    /* Note: cpu_interrupt() is currently not SMP safe, so we force
+       QEMU to run on a single CPU */
+    HANDLE h;
+    DWORD mask, smask;
+    int i;
+
+    SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
+
+    h = GetCurrentProcess();
+    if (GetProcessAffinityMask(h, &mask, &smask)) {
+        for(i = 0; i < 32; i++) {
+            if (mask & (1 << i))
+                break;
+        }
+        if (i != 32) {
+            mask = 1 << i;
+            SetProcessAffinityMask(h, mask);
+        }
+    }
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index ff5adb1..96d1036 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,6 +30,4 @@ static inline void os_host_main_loop_wait(int *timeout)
 {
 }
 
-void os_setup_signal_handling(void);
-
 #endif
diff --git a/sysemu.h b/sysemu.h
index 5e4feae..e3643ad 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,6 +79,8 @@ int qemu_loadvm_state(QEMUFile *f);
 /* SLIRP */
 void do_info_slirp(Monitor *mon);
 
+void os_setup_signal_handling(void);
+
 typedef enum DisplayType
 {
     DT_DEFAULT,
diff --git a/vl.c b/vl.c
index 5640d35..8638c62 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,14 +1986,6 @@ static int balloon_parse(const char *arg)
     return -1;
 }
 
-#ifdef _WIN32
-static BOOL WINAPI qemu_ctrl_handler(DWORD type)
-{
-    exit(STATUS_CONTROL_C_EXIT);
-    return TRUE;
-}
-#endif
-
 #ifndef _WIN32
 
 static void termsig_handler(int signal)
@@ -2459,29 +2451,7 @@ int main(int argc, char **argv, char **envp)
     qemu_cache_utils_init(envp);
 
     QLIST_INIT (&vm_change_state_head);
-#ifndef _WIN32
     os_setup_signal_handling();
-#else
-    SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
-    /* Note: cpu_interrupt() is currently not SMP safe, so we force
-       QEMU to run on a single CPU */
-    {
-        HANDLE h;
-        DWORD mask, smask;
-        int i;
-        h = GetCurrentProcess();
-        if (GetProcessAffinityMask(h, &mask, &smask)) {
-            for(i = 0; i < 32; i++) {
-                if (mask & (1 << i))
-                    break;
-            }
-            if (i != 32) {
-                mask = 1 << i;
-                SetProcessAffinityMask(h, mask);
-            }
-        }
-    }
-#endif
 
     module_call_init(MODULE_INIT_MACHINE);
     machine = find_default_machine();
commit 86b645e753b9396f8cc5b74a9eadf2d36f76ae5c
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:19 2010 +0200

    Introduce os-posix.c and create os_setup_signal_handling()
    
    Introcuce os-posix.c and move posix specific signal handling
    there.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 58fdb03..2d94677 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -145,6 +145,7 @@ hw-obj-$(CONFIG_NAND) += nand.o
 hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
 hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
 hw-obj-$(CONFIG_WIN32) += os-win32.o
+hw-obj-$(CONFIG_POSIX) += os-posix.o
 
 hw-obj-$(CONFIG_M48T59) += m48t59.o
 hw-obj-$(CONFIG_ESCC) += escc.o
diff --git a/os-posix.c b/os-posix.c
new file mode 100644
index 0000000..914a4d1
--- /dev/null
+++ b/os-posix.c
@@ -0,0 +1,41 @@
+/*
+ * os-posix.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+/* Needed early for CONFIG_BSD etc. */
+#include "config-host.h"
+#include "sysemu.h"
+
+void os_setup_signal_handling(void)
+{
+    struct sigaction act;
+    sigfillset(&act.sa_mask);
+    act.sa_flags = 0;
+    act.sa_handler = SIG_IGN;
+    sigaction(SIGPIPE, &act, NULL);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 96d1036..ff5adb1 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,4 +30,6 @@ static inline void os_host_main_loop_wait(int *timeout)
 {
 }
 
+void os_setup_signal_handling(void);
+
 #endif
diff --git a/vl.c b/vl.c
index 3bbfd22..5640d35 100644
--- a/vl.c
+++ b/vl.c
@@ -2460,13 +2460,7 @@ int main(int argc, char **argv, char **envp)
 
     QLIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
-    {
-        struct sigaction act;
-        sigfillset(&act.sa_mask);
-        act.sa_flags = 0;
-        act.sa_handler = SIG_IGN;
-        sigaction(SIGPIPE, &act, NULL);
-    }
+    os_setup_signal_handling();
 #else
     SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
     /* Note: cpu_interrupt() is currently not SMP safe, so we force
commit 0d93ca7c3b4c93a87723e3397daf6df2034b455a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:18 2010 +0200

    vl.c: Move host_main_loop_wait() to OS specific files.
    
    Move host_main_loop_wait() to OS specific files. Create
    qemu-os-posix.h and provide empty inline for the POSIX case.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/os-win32.c b/os-win32.c
index 5a464cc..1f7e28b 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -109,3 +109,46 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
     if (found)
         w->num--;
 }
+
+void os_host_main_loop_wait(int *timeout)
+{
+    int ret, ret2, i;
+    PollingEntry *pe;
+
+    /* XXX: need to suppress polling by better using win32 events */
+    ret = 0;
+    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
+        ret |= pe->func(pe->opaque);
+    }
+    if (ret == 0) {
+        int err;
+        WaitObjects *w = &wait_objects;
+
+        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
+            if (w->func[ret - WAIT_OBJECT_0])
+                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+
+            /* Check for additional signaled events */
+            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+
+                /* Check if event is signaled */
+                ret2 = WaitForSingleObject(w->events[i], 0);
+                if(ret2 == WAIT_OBJECT_0) {
+                    if (w->func[i])
+                        w->func[i](w->opaque[i]);
+                } else if (ret2 == WAIT_TIMEOUT) {
+                } else {
+                    err = GetLastError();
+                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+                }
+            }
+        } else if (ret == WAIT_TIMEOUT) {
+        } else {
+            err = GetLastError();
+            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
+        }
+    }
+
+    *timeout = 0;
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
new file mode 100644
index 0000000..96d1036
--- /dev/null
+++ b/qemu-os-posix.h
@@ -0,0 +1,33 @@
+/*
+ * posix specific declarations
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * 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 QEMU_OS_POSIX_H
+#define QEMU_OS_POSIX_H
+
+static inline void os_host_main_loop_wait(int *timeout)
+{
+}
+
+#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index be108ad..4d1cac8 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -40,4 +40,5 @@ typedef void WaitObjectFunc(void *opaque);
 int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
 
+void os_host_main_loop_wait(int *timeout);
 #endif
diff --git a/sysemu.h b/sysemu.h
index 13fc9a9..5e4feae 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -12,6 +12,10 @@
 #include "qemu-os-win32.h"
 #endif
 
+#ifdef CONFIG_POSIX
+#include "qemu-os-posix.h"
+#endif
+
 /* vl.c */
 extern const char *bios_name;
 
diff --git a/vl.c b/vl.c
index 73a3915..3bbfd22 100644
--- a/vl.c
+++ b/vl.c
@@ -1722,56 +1722,6 @@ void qemu_system_powerdown_request(void)
     qemu_notify_event();
 }
 
-#ifdef _WIN32
-static void host_main_loop_wait(int *timeout)
-{
-    int ret, ret2, i;
-    PollingEntry *pe;
-
-
-    /* XXX: need to suppress polling by better using win32 events */
-    ret = 0;
-    for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
-        ret |= pe->func(pe->opaque);
-    }
-    if (ret == 0) {
-        int err;
-        WaitObjects *w = &wait_objects;
-
-        ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
-        if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
-            if (w->func[ret - WAIT_OBJECT_0])
-                w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
-            /* Check for additional signaled events */
-            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
-                /* Check if event is signaled */
-                ret2 = WaitForSingleObject(w->events[i], 0);
-                if(ret2 == WAIT_OBJECT_0) {
-                    if (w->func[i])
-                        w->func[i](w->opaque[i]);
-                } else if (ret2 == WAIT_TIMEOUT) {
-                } else {
-                    err = GetLastError();
-                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
-                }
-            }
-        } else if (ret == WAIT_TIMEOUT) {
-        } else {
-            err = GetLastError();
-            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
-        }
-    }
-
-    *timeout = 0;
-}
-#else
-static void host_main_loop_wait(int *timeout)
-{
-}
-#endif
-
 void main_loop_wait(int nonblocking)
 {
     IOHandlerRecord *ioh;
@@ -1787,7 +1737,7 @@ void main_loop_wait(int nonblocking)
         qemu_bh_update_timeout(&timeout);
     }
 
-    host_main_loop_wait(&timeout);
+    os_host_main_loop_wait(&timeout);
 
     /* poll any events */
     /* XXX: separate device handlers from system ones */
commit 19113504dea4504f69d414f72f8a18d3c1a941d5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:17 2010 +0200

    Introduce os-win32.c and move polling functions from vl.c
    
    This introduces os-win32.c. It is meant to carry win32 specific
    functions thata are not relevant for all of QEMU as well as win32
    versions of various pieces like signal handling etc.
    
    Move win32 polling handler helper functions from vl.c to os-win32.c
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.objs b/Makefile.objs
index 9796dcb..58fdb03 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -144,6 +144,7 @@ hw-obj-$(CONFIG_ECC) += ecc.o
 hw-obj-$(CONFIG_NAND) += nand.o
 hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
 hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+hw-obj-$(CONFIG_WIN32) += os-win32.o
 
 hw-obj-$(CONFIG_M48T59) += m48t59.o
 hw-obj-$(CONFIG_ESCC) += escc.o
diff --git a/os-win32.c b/os-win32.c
new file mode 100644
index 0000000..5a464cc
--- /dev/null
+++ b/os-win32.c
@@ -0,0 +1,111 @@
+/*
+ * os-win32.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * 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 <windows.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "config-host.h"
+#include "sysemu.h"
+
+/***********************************************************/
+/* Polling handling */
+
+typedef struct PollingEntry {
+    PollingFunc *func;
+    void *opaque;
+    struct PollingEntry *next;
+} PollingEntry;
+
+static PollingEntry *first_polling_entry;
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    pe = qemu_mallocz(sizeof(PollingEntry));
+    pe->func = func;
+    pe->opaque = opaque;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
+    *ppe = pe;
+    return 0;
+}
+
+void qemu_del_polling_cb(PollingFunc *func, void *opaque)
+{
+    PollingEntry **ppe, *pe;
+    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
+        pe = *ppe;
+        if (pe->func == func && pe->opaque == opaque) {
+            *ppe = pe->next;
+            qemu_free(pe);
+            break;
+        }
+    }
+}
+
+/***********************************************************/
+/* Wait objects support */
+typedef struct WaitObjects {
+    int num;
+    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
+    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
+} WaitObjects;
+
+static WaitObjects wait_objects = {0};
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    WaitObjects *w = &wait_objects;
+
+    if (w->num >= MAXIMUM_WAIT_OBJECTS)
+        return -1;
+    w->events[w->num] = handle;
+    w->func[w->num] = func;
+    w->opaque[w->num] = opaque;
+    w->num++;
+    return 0;
+}
+
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+    int i, found;
+    WaitObjects *w = &wait_objects;
+
+    found = 0;
+    for (i = 0; i < w->num; i++) {
+        if (w->events[i] == handle)
+            found = 1;
+        if (found) {
+            w->events[i] = w->events[i + 1];
+            w->func[i] = w->func[i + 1];
+            w->opaque[i] = w->opaque[i + 1];
+        }
+    }
+    if (found)
+        w->num--;
+}
diff --git a/vl.c b/vl.c
index a9be190..73a3915 100644
--- a/vl.c
+++ b/vl.c
@@ -1497,86 +1497,6 @@ int qemu_set_fd_handler(int fd,
     return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
 }
 
-#ifdef _WIN32
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
-    PollingFunc *func;
-    void *opaque;
-    struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    pe = qemu_mallocz(sizeof(PollingEntry));
-    pe->func = func;
-    pe->opaque = opaque;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
-    *ppe = pe;
-    return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
-    PollingEntry **ppe, *pe;
-    for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
-        pe = *ppe;
-        if (pe->func == func && pe->opaque == opaque) {
-            *ppe = pe->next;
-            qemu_free(pe);
-            break;
-        }
-    }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
-    int num;
-    HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
-    WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
-    void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    WaitObjects *w = &wait_objects;
-
-    if (w->num >= MAXIMUM_WAIT_OBJECTS)
-        return -1;
-    w->events[w->num] = handle;
-    w->func[w->num] = func;
-    w->opaque[w->num] = opaque;
-    w->num++;
-    return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
-    int i, found;
-    WaitObjects *w = &wait_objects;
-
-    found = 0;
-    for (i = 0; i < w->num; i++) {
-        if (w->events[i] == handle)
-            found = 1;
-        if (found) {
-            w->events[i] = w->events[i + 1];
-            w->func[i] = w->func[i + 1];
-            w->opaque[i] = w->opaque[i + 1];
-        }
-    }
-    if (found)
-        w->num--;
-}
-#endif
-
 /***********************************************************/
 /* machine registration */
 
commit 39626c037585b4ad9f83b86854ac14c9b9523db5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:16 2010 +0200

    Create qemu-os-win32.h and move WIN32 specific declarations there
    
    Create qemu-os-win32.h for WIN32 specific declarations. Move polling
    handling declaration into this file from sysemu.h
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-os-win32.h b/qemu-os-win32.h
new file mode 100644
index 0000000..be108ad
--- /dev/null
+++ b/qemu-os-win32.h
@@ -0,0 +1,43 @@
+/*
+ * win32 specific declarations
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * 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 QEMU_OS_WIN32_H
+#define QEMU_OS_WIN32_H
+
+/* Polling handling */
+
+/* return TRUE if no sleep should be done afterwards */
+typedef int PollingFunc(void *opaque);
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque);
+void qemu_del_polling_cb(PollingFunc *func, void *opaque);
+
+/* Wait objects handling */
+typedef void WaitObjectFunc(void *opaque);
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+
+#endif
diff --git a/sysemu.h b/sysemu.h
index 879446a..13fc9a9 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -9,6 +9,7 @@
 
 #ifdef _WIN32
 #include <windows.h>
+#include "qemu-os-win32.h"
 #endif
 
 /* vl.c */
@@ -71,22 +72,6 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
 void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
-#ifdef _WIN32
-/* Polling handling */
-
-/* return TRUE if no sleep should be done afterwards */
-typedef int PollingFunc(void *opaque);
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque);
-void qemu_del_polling_cb(PollingFunc *func, void *opaque);
-
-/* Wait objects handling */
-typedef void WaitObjectFunc(void *opaque);
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-#endif
-
 /* SLIRP */
 void do_info_slirp(Monitor *mon);
 
commit ddc9120e90199e3fe93116928de13a2dd72fa35a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jun 10 11:42:15 2010 +0200

    vl.c: Remove double include of netinet/in.h for Solaris
    
    vl.c: netinet/in.h is already included once above for the
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Andreas Faerber <afaerber at opensolaris.org>
    Acked-by: Juan Quintela <quintela at redhat.com>
    Acked-by: Richard Henderson <rth at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/vl.c b/vl.c
index 3d7ce52..a9be190 100644
--- a/vl.c
+++ b/vl.c
@@ -70,7 +70,6 @@
 #include <sys/ethernet.h>
 #include <sys/sockio.h>
 #include <netinet/arp.h>
-#include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h> // must come after ip.h
commit 41ba834146f1d8b9cbc09a9f25f5c6b84bf405d9
Author: Paul Brook <paul at codesourcery.com>
Date:   Fri Jun 11 20:01:00 2010 +0100

    NEON vldN optimization
    
    When combining multiple values as part of a NEON array load, do explcit
    shift/or rather than using gen_bfi.  This voids redundant mask
    operations.
    
    Signed-off-by: Paul Brook <paul at codesourcery.com>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0eccca5..a28e2ff 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3854,7 +3854,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tcg_gen_addi_i32(addr, addr, stride);
                             tmp2 = gen_ld16u(addr, IS_USER(s));
                             tcg_gen_addi_i32(addr, addr, stride);
-                            gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
+                            tcg_gen_shli_i32(tmp2, tmp2, 16);
+                            tcg_gen_or_i32(tmp, tmp, tmp2);
                             dead_tmp(tmp2);
                             neon_store_reg(rd, pass, tmp);
                         } else {
@@ -3875,7 +3876,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
                                 if (n == 0) {
                                     tmp2 = tmp;
                                 } else {
-                                    gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
+                                    tcg_gen_shli_i32(tmp, tmp, n * 8);
+                                    tcg_gen_or_i32(tmp2, tmp2, tmp);
                                     dead_tmp(tmp);
                                 }
                             }
commit 02e95918b82efde24db1d759300ec3c61bd694b3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Wed Jun 2 09:06:03 2010 +0200

    hxtool: Fix line number reporting on SQMP/EQMP errors
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hxtool b/hxtool
index d499dc0..7ca83ed 100644
--- a/hxtool
+++ b/hxtool
@@ -59,6 +59,7 @@ hxtoqmp()
 {
     IFS=
     flag=0
+    line=1
     while read -r str; do
         case "$str" in
             HXCOMM*)
@@ -87,6 +88,7 @@ hxtoqmp()
             test $flag -eq 1 && echo "$str"
             ;;
         esac
+        line=$((line+1))
     done
 }
 
commit 28e91a681a284b02b18cdbeee011430e5d061533
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon May 24 09:39:53 2010 +0200

    remove unnecessary lookaheads
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-lexer.c b/json-lexer.c
index 5ea64a7..c736f42 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -29,7 +29,6 @@
 
 enum json_lexer_state {
     ERROR = 0,
-    IN_DONE_STRING,
     IN_DQ_UCODE3,
     IN_DQ_UCODE2,
     IN_DQ_UCODE1,
@@ -57,9 +56,7 @@ enum json_lexer_state {
     IN_ESCAPE_I,
     IN_ESCAPE_I6,
     IN_ESCAPE_I64,
-    IN_ESCAPE_DONE,
     IN_WHITESPACE,
-    IN_OPERATOR_DONE,
     IN_START,
 };
 
@@ -72,10 +69,6 @@ enum json_lexer_state {
             (json_lexer[(old_state)][0] == (terminal))
 
 static const uint8_t json_lexer[][256] =  {
-    [IN_DONE_STRING] = {
-        TERMINAL(JSON_STRING),
-    },
-
     /* double quote string */
     [IN_DQ_UCODE3] = {
         ['0' ... '9'] = IN_DQ_STRING,
@@ -112,7 +105,7 @@ static const uint8_t json_lexer[][256] =  {
     [IN_DQ_STRING] = {
         [1 ... 0xFF] = IN_DQ_STRING,
         ['\\'] = IN_DQ_STRING_ESCAPE,
-        ['"'] = IN_DONE_STRING,
+        ['"'] = JSON_STRING,
     },
 
     /* single quote string */
@@ -151,7 +144,7 @@ static const uint8_t json_lexer[][256] =  {
     [IN_SQ_STRING] = {
         [1 ... 0xFF] = IN_SQ_STRING,
         ['\\'] = IN_SQ_STRING_ESCAPE,
-        ['\''] = IN_DONE_STRING,
+        ['\''] = JSON_STRING,
     },
 
     /* Zero */
@@ -217,27 +210,18 @@ static const uint8_t json_lexer[][256] =  {
         ['\n'] = IN_WHITESPACE,
     },        
 
-    /* operator */
-    [IN_OPERATOR_DONE] = {
-        TERMINAL(JSON_OPERATOR),
-    },
-
     /* escape */
-    [IN_ESCAPE_DONE] = {
-        TERMINAL(JSON_ESCAPE),
-    },
-
     [IN_ESCAPE_LL] = {
-        ['d'] = IN_ESCAPE_DONE,
+        ['d'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_L] = {
-        ['d'] = IN_ESCAPE_DONE,
+        ['d'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_LL,
     },
 
     [IN_ESCAPE_I64] = {
-        ['d'] = IN_ESCAPE_DONE,
+        ['d'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_I6] = {
@@ -249,11 +233,11 @@ static const uint8_t json_lexer[][256] =  {
     },
 
     [IN_ESCAPE] = {
-        ['d'] = IN_ESCAPE_DONE,
-        ['i'] = IN_ESCAPE_DONE,
-        ['p'] = IN_ESCAPE_DONE,
-        ['s'] = IN_ESCAPE_DONE,
-        ['f'] = IN_ESCAPE_DONE,
+        ['d'] = JSON_ESCAPE,
+        ['i'] = JSON_ESCAPE,
+        ['p'] = JSON_ESCAPE,
+        ['s'] = JSON_ESCAPE,
+        ['f'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_L,
         ['I'] = IN_ESCAPE_I,
     },
@@ -265,12 +249,12 @@ static const uint8_t json_lexer[][256] =  {
         ['0'] = IN_ZERO,
         ['1' ... '9'] = IN_NONZERO_NUMBER,
         ['-'] = IN_NEG_NONZERO_NUMBER,
-        ['{'] = IN_OPERATOR_DONE,
-        ['}'] = IN_OPERATOR_DONE,
-        ['['] = IN_OPERATOR_DONE,
-        [']'] = IN_OPERATOR_DONE,
-        [','] = IN_OPERATOR_DONE,
-        [':'] = IN_OPERATOR_DONE,
+        ['{'] = JSON_OPERATOR,
+        ['}'] = JSON_OPERATOR,
+        ['['] = JSON_OPERATOR,
+        [']'] = JSON_OPERATOR,
+        [','] = JSON_OPERATOR,
+        [':'] = JSON_OPERATOR,
         ['a' ... 'z'] = IN_KEYWORD,
         ['%'] = IN_ESCAPE,
         [' '] = IN_WHITESPACE,
commit f7c052747e4b139df16e1d5b7851f4729acc2bb7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon May 24 09:39:52 2010 +0200

    implement optional lookahead in json lexer
    
    Not requiring one extra character when lookahead is not necessary
    ensures that clients behave properly even if they, for example,
    send QMP requests without a trailing newline.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-lexer.c b/json-lexer.c
index 1d9b81f..5ea64a7 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -65,6 +65,12 @@ enum json_lexer_state {
 
 #define TERMINAL(state) [0 ... 0x7F] = (state)
 
+/* Return whether TERMINAL is a terminal state and the transition to it
+   from OLD_STATE required lookahead.  This happens whenever the table
+   below uses the TERMINAL macro.  */
+#define TERMINAL_NEEDED_LOOKAHEAD(old_state, terminal) \
+            (json_lexer[(old_state)][0] == (terminal))
+
 static const uint8_t json_lexer[][256] =  {
     [IN_DONE_STRING] = {
         TERMINAL(JSON_STRING),
@@ -284,35 +290,41 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
 
 static int json_lexer_feed_char(JSONLexer *lexer, char ch)
 {
+    int char_consumed, new_state;
+
     lexer->x++;
     if (ch == '\n') {
         lexer->x = 0;
         lexer->y++;
     }
 
-    lexer->state = json_lexer[lexer->state][(uint8_t)ch];
-
-    switch (lexer->state) {
-    case JSON_OPERATOR:
-    case JSON_ESCAPE:
-    case JSON_INTEGER:
-    case JSON_FLOAT:
-    case JSON_KEYWORD:
-    case JSON_STRING:
-        lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
-    case JSON_SKIP:
-        lexer->state = json_lexer[IN_START][(uint8_t)ch];
-        QDECREF(lexer->token);
-        lexer->token = qstring_new();
-        break;
-    case ERROR:
-        return -EINVAL;
-    default:
-        break;
-    }
-
-    qstring_append_chr(lexer->token, ch);
+    do {
+        new_state = json_lexer[lexer->state][(uint8_t)ch];
+        char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
+        if (char_consumed) {
+            qstring_append_chr(lexer->token, ch);
+        }
 
+        switch (new_state) {
+        case JSON_OPERATOR:
+        case JSON_ESCAPE:
+        case JSON_INTEGER:
+        case JSON_FLOAT:
+        case JSON_KEYWORD:
+        case JSON_STRING:
+            lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
+        case JSON_SKIP:
+            QDECREF(lexer->token);
+            lexer->token = qstring_new();
+            new_state = IN_START;
+            break;
+        case ERROR:
+            return -EINVAL;
+        default:
+            break;
+        }
+        lexer->state = new_state;
+    } while (!char_consumed);
     return 0;
 }
 
@@ -334,7 +346,7 @@ int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size)
 
 int json_lexer_flush(JSONLexer *lexer)
 {
-    return json_lexer_feed_char(lexer, 0);
+    return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0);
 }
 
 void json_lexer_destroy(JSONLexer *lexer)
commit 7f8fca7c8add770d6533c44d2d001c0442ed0371
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon May 24 09:39:51 2010 +0200

    add some tests for invalid JSON
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/check-qjson.c b/check-qjson.c
index d365799..2e52450 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -638,11 +638,90 @@ START_TEST(simple_varargs)
 }
 END_TEST
 
+START_TEST(empty_input)
+{
+    QObject *obj = qobject_from_json("");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_string)
+{
+    QObject *obj = qobject_from_json("\"abc");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_sq_string)
+{
+    QObject *obj = qobject_from_json("'abc");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_escape)
+{
+    QObject *obj = qobject_from_json("\"abc\\\"");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array)
+{
+    QObject *obj = qobject_from_json("[32");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array_comma)
+{
+    QObject *obj = qobject_from_json("[32,");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(invalid_array_comma)
+{
+    QObject *obj = qobject_from_json("[32,}");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict)
+{
+    QObject *obj = qobject_from_json("{'abc':32");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict_comma)
+{
+    QObject *obj = qobject_from_json("{'abc':32,");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+#if 0
+START_TEST(invalid_dict_comma)
+{
+    QObject *obj = qobject_from_json("{'abc':32,}");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_literal)
+{
+    QObject *obj = qobject_from_json("nul");
+    fail_unless(obj == NULL);
+}
+END_TEST
+#endif
+
 static Suite *qjson_suite(void)
 {
     Suite *suite;
     TCase *string_literals, *number_literals, *keyword_literals;
-    TCase *dicts, *lists, *whitespace, *varargs;
+    TCase *dicts, *lists, *whitespace, *varargs, *errors;
 
     string_literals = tcase_create("String Literals");
     tcase_add_test(string_literals, simple_string);
@@ -668,6 +747,22 @@ static Suite *qjson_suite(void)
     varargs = tcase_create("Varargs");
     tcase_add_test(varargs, simple_varargs);
 
+    errors = tcase_create("Invalid JSON");
+    tcase_add_test(errors, empty_input);
+    tcase_add_test(errors, unterminated_string);
+    tcase_add_test(errors, unterminated_escape);
+    tcase_add_test(errors, unterminated_sq_string);
+    tcase_add_test(errors, unterminated_array);
+    tcase_add_test(errors, unterminated_array_comma);
+    tcase_add_test(errors, invalid_array_comma);
+    tcase_add_test(errors, unterminated_dict);
+    tcase_add_test(errors, unterminated_dict_comma);
+#if 0
+    /* FIXME: this print parse error messages on stderr.  */
+    tcase_add_test(errors, invalid_dict_comma);
+    tcase_add_test(errors, unterminated_literal);
+#endif
+
     suite = suite_create("QJSON test-suite");
     suite_add_tcase(suite, string_literals);
     suite_add_tcase(suite, number_literals);
@@ -676,6 +771,7 @@ static Suite *qjson_suite(void)
     suite_add_tcase(suite, lists);
     suite_add_tcase(suite, whitespace);
     suite_add_tcase(suite, varargs);
+    suite_add_tcase(suite, errors);
 
     return suite;
 }
commit 2e89c0688993447ed62a1832dcd97c19c878a382
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed May 19 17:17:05 2010 -0300

    json-streamer: Don't use qdict_put_obj()
    
    It's not needed, use qobject_put() instead and get a cleaner code.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-streamer.c b/json-streamer.c
index 610ffea..f7e7a68 100644
--- a/json-streamer.c
+++ b/json-streamer.c
@@ -43,11 +43,11 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
     }
 
     dict = qdict_new();
-    qdict_put_obj(dict, "type", QOBJECT(qint_from_int(type)));
+    qdict_put(dict, "type", qint_from_int(type));
     QINCREF(token);
-    qdict_put_obj(dict, "token", QOBJECT(token));
-    qdict_put_obj(dict, "x", QOBJECT(qint_from_int(x)));
-    qdict_put_obj(dict, "y", QOBJECT(qint_from_int(y)));
+    qdict_put(dict, "token", token);
+    qdict_put(dict, "x", qint_from_int(x));
+    qdict_put(dict, "y", qint_from_int(y));
 
     qlist_append(parser->tokens, dict);
 
commit ecb50f5fefe7e1360818bd199218a295d87df042
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon May 17 17:59:00 2010 -0300

    json-lexer: Drop 'buf'
    
    QString supports adding a single char, 'buf' is unneeded.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-lexer.c b/json-lexer.c
index 5cc7e6c..1d9b81f 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -284,8 +284,6 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
 
 static int json_lexer_feed_char(JSONLexer *lexer, char ch)
 {
-    char buf[2];
-
     lexer->x++;
     if (ch == '\n') {
         lexer->x = 0;
@@ -313,10 +311,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch)
         break;
     }
 
-    buf[0] = ch;
-    buf[1] = 0;
-
-    qstring_append(lexer->token, buf);
+    qstring_append_chr(lexer->token, ch);
 
     return 0;
 }
commit d22b0bd7fc85f991275ffc60a550ed42f4c1b04c
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed May 19 17:08:37 2010 -0300

    check-qjson: Add more escape tests
    
    While there make the fail_unless() calls print error messages.
    
    IMPORTANT: The test for "\/" is failing, don't know why.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/check-qjson.c b/check-qjson.c
index 109e777..d365799 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -29,6 +29,13 @@ START_TEST(escaped_string)
         const char *decoded;
         int skip;
     } test_cases[] = {
+        { "\"\\b\"", "\b" },
+        { "\"\\f\"", "\f" },
+        { "\"\\n\"", "\n" },
+        { "\"\\r\"", "\r" },
+        { "\"\\t\"", "\t" },
+        { "\"\\/\"", "\\/" },
+        { "\"\\\\\"", "\\" },
         { "\"\\\"\"", "\"" },
         { "\"hello world \\\"embedded string\\\"\"",
           "hello world \"embedded string\"" },
@@ -49,11 +56,14 @@ START_TEST(escaped_string)
         fail_unless(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
+                    "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
 
         if (test_cases[i].skip == 0) {
             str = qobject_to_json(obj);
-            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
+                        "%s != %s\n", qstring_get_str(str),
+                                      test_cases[i].encoded);
 
             qobject_decref(obj);
         }
commit bd0326950f99faa8e50cf52499dd1af42829aa93
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed May 19 17:06:15 2010 -0300

    qjson: Handle "\f"
    
    It's valid JSON and should be handled.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-parser.c b/json-parser.c
index b55d763..83212bc 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -206,6 +206,10 @@ static QString *qstring_from_escaped_str(JSONParserContext *ctxt, QObject *token
                 qstring_append(str, "\b");
                 ptr++;
                 break;
+            case 'f':
+                qstring_append(str, "\f");
+                ptr++;
+                break;
             case 'n':
                 qstring_append(str, "\n");
                 ptr++;
diff --git a/qjson.c b/qjson.c
index 483c667..e4ee433 100644
--- a/qjson.c
+++ b/qjson.c
@@ -158,6 +158,9 @@ static void to_json(const QObject *obj, QString *str)
                 case '\b':
                     qstring_append(str, "\\b");
                     break;
+                case '\f':
+                    qstring_append(str, "\\f");
+                    break;
                 case '\n':
                     qstring_append(str, "\\n");
                     break;
commit 1041ba7a14260b490f3062f428b014b415a23f38
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed May 19 16:57:28 2010 -0300

    json-lexer: Handle missing escapes
    
    The JSON escape sequence "\/" and "\\" are valid and should be
    handled.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-lexer.c b/json-lexer.c
index 0b145d1..5cc7e6c 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -97,6 +97,8 @@ static const uint8_t json_lexer[][256] =  {
         ['n'] =  IN_DQ_STRING,
         ['r'] =  IN_DQ_STRING,
         ['t'] =  IN_DQ_STRING,
+        ['/'] = IN_DQ_STRING,
+        ['\\'] = IN_DQ_STRING,
         ['\''] = IN_DQ_STRING,
         ['\"'] = IN_DQ_STRING,
         ['u'] = IN_DQ_UCODE0,
@@ -134,6 +136,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,
         ['u'] = IN_SQ_UCODE0,
commit 03308f6c2746a756a8404d00caa20f8f35248167
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon May 17 17:50:01 2010 -0300

    json-lexer: Initialize 'x' and 'y'
    
    The 'lexer' variable is passed by the caller, it can contain anything
    (eg. garbage).
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/json-lexer.c b/json-lexer.c
index 9d64920..0b145d1 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -275,6 +275,7 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
     lexer->emit = func;
     lexer->state = IN_START;
     lexer->token = qstring_new();
+    lexer->x = lexer->y = 0;
 }
 
 static int json_lexer_feed_char(JSONLexer *lexer, char ch)
commit 0e2029a063405091ee34170ef71aa321715e4357
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Jun 11 18:39:47 2010 +0200

    tcg: fix DEF macro after commit c61aaf7a388c4ad95d8b546fdb9267dc01183317
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 30b5106..3a18b76 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,7 +69,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
                         tcg_target_long value, tcg_target_long addend);
 
 static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
+#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
 #include "tcg-opc.h"
 #undef DEF
 };
commit 28d7cc493e8b58f63fda05eb7df2552f5d420459
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:09 2010 -0700

    tcg-s390: Adjust compilation flags.
    
    Force -m31/-m64 based on s390/s390x target.
    
    Force -march=z990.  The TCG backend will always require the
    long-displacement facility, so the compiler may as well make
    use of that as well.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 927e104..ced4d2f 100755
--- a/configure
+++ b/configure
@@ -720,7 +720,12 @@ case "$cpu" in
            fi
            ;;
     s390)
-           QEMU_CFLAGS="-march=z900 $QEMU_CFLAGS"
+           QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
+           LDFLAGS="-m31 $LDFLAGS"
+           ;;
+    s390x)
+           QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS"
+           LDFLAGS="-m64 $LDFLAGS"
            ;;
     i386)
            QEMU_CFLAGS="-m32 $QEMU_CFLAGS"
commit 6a1621b917352122ad025e102f450de382dae407
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:12 2010 -0700

    tcg-s390: Compute is_write in cpu_signal_handler.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/cpu-exec.c b/cpu-exec.c
index c776605..026980a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -1156,11 +1156,47 @@ int cpu_signal_handler(int host_signum, void *pinfo,
     siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
-    int is_write;
+    uint16_t *pinsn;
+    int is_write = 0;
 
     pc = uc->uc_mcontext.psw.addr;
-    /* XXX: compute is_write */
-    is_write = 0;
+
+    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
+       of the normal 2 arguments.  The 3rd argument contains the "int_code"
+       from the hardware which does in fact contain the is_write value.
+       The rt signal handler, as far as I can tell, does not give this value
+       at all.  Not that we could get to it from here even if it were.  */
+    /* ??? This is not even close to complete, since it ignores all
+       of the read-modify-write instructions.  */
+    pinsn = (uint16_t *)pc;
+    switch (pinsn[0] >> 8) {
+    case 0x50: /* ST */
+    case 0x42: /* STC */
+    case 0x40: /* STH */
+        is_write = 1;
+        break;
+    case 0xc4: /* RIL format insns */
+        switch (pinsn[0] & 0xf) {
+        case 0xf: /* STRL */
+        case 0xb: /* STGRL */
+        case 0x7: /* STHRL */
+            is_write = 1;
+        }
+        break;
+    case 0xe3: /* RXY format insns */
+        switch (pinsn[2] & 0xff) {
+        case 0x50: /* STY */
+        case 0x24: /* STG */
+        case 0x72: /* STCY */
+        case 0x70: /* STHY */
+        case 0x8e: /* STPQ */
+        case 0x3f: /* STRVH */
+        case 0x3e: /* STRV */
+        case 0x2f: /* STRVG */
+            is_write = 1;
+        }
+        break;
+    }
     return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                              is_write, &uc->uc_sigmask, puc);
 }
commit 4d58be0628bf1d30b8c1b3600f0ce44db1b38b2f
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:11 2010 -0700

    s390x: Don't use a linker script for user-only.
    
    The default placement of the application at 0x80000000 is fine,
    and will avoid the default placement for most other guests.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index fa7f299..927e104 100755
--- a/configure
+++ b/configure
@@ -2763,6 +2763,9 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
     # -static is used to avoid g1/g3 usage by the dynamic linker
     ldflags="$linker_script -static $ldflags"
     ;;
+  alpha | s390x)
+    # The default placement of the application is fine.
+    ;;
   *)
     ldflags="$linker_script $ldflags"
     ;;
commit d35b261c7a94be9e2fcad5484343544d58ff99be
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:10 2010 -0700

    s390x: Avoid _llseek.
    
    There's no _llseek on s390x either.  Replace the existing
    test for __x86_64__ with a functional test for __NR_llseek.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8222cb9..e94f1ee 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -208,7 +208,7 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count)
 _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
 #endif
 _syscall2(int, sys_getpriority, int, which, int, who);
-#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
+#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 #endif
@@ -5933,7 +5933,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR__llseek /* Not on alpha */
     case TARGET_NR__llseek:
         {
-#if defined (__x86_64__)
+#if !defined(__NR_llseek)
             ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
             if (put_user_s64(ret, arg4))
                 goto efault;
commit eba0b89379b3af98b51a8c1559868de89f5f713e
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:14 2010 -0700

    tcg-s390: Allocate the code_gen_buffer near the main program.
    
    This allows the use of direct calls to the helpers,
    and a direct branch back to the epilogue.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/exec.c b/exec.c
index aedfda4..4273797 100644
--- a/exec.c
+++ b/exec.c
@@ -519,6 +519,13 @@ static void code_gen_alloc(unsigned long tb_size)
         start = (void *) 0x01000000UL;
         if (code_gen_buffer_size > 16 * 1024 * 1024)
             code_gen_buffer_size = 16 * 1024 * 1024;
+#elif defined(__s390x__)
+        /* Map the buffer so that we can use direct calls and branches.  */
+        /* We have a +- 4GB range on the branches; leave some slop.  */
+        if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
+            code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
+        }
+        start = (void *)0x90000000UL;
 #endif
         code_gen_buffer = mmap(start, code_gen_buffer_size,
                                PROT_WRITE | PROT_READ | PROT_EXEC,
commit 1bcaae666fdcda03f768c2894091ec2e441abb57
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:13 2010 -0700

    tcg-s390: Icache flush is a no-op.
    
    Before gcc 4.2, __builtin___clear_cache doesn't exist, and
    afterward the gcc s390 backend implements it as nothing.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index d8a2955..d7fe0c7 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -94,9 +94,4 @@ enum {
 
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-#if QEMU_GNUC_PREREQ(4, 1)
-    __builtin___clear_cache((char *) start, (char *) stop);
-#else
-#error not implemented
-#endif
 }
commit dc397ca35e332770ede6899122e5d012bd92c37c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 10 20:52:47 2010 +0200

    tcg-i386: fix andi r, r, 0xff
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8b902ab..bb19a95 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -679,7 +679,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
                 rexw = 0;
             }
         }
-        if (val == 0xffu) {
+        if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
             tcg_out_ext8u(s, r0, r0);
             return;
         }
commit 447d681e8b23fec360c95131c0b037d82dce495c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 10 20:40:24 2010 +0200

    tcg-i386: remove use of _Bool that slipped code review
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 4d95200..8b902ab 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -656,7 +656,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
        partial flags update stalls on Pentium4 and are not recommended
        by current Intel optimization manuals.  */
     if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
-        _Bool is_inc = (c == ARITH_ADD) ^ (val < 0);
+        int is_inc = (c == ARITH_ADD) ^ (val < 0);
         if (TCG_TARGET_REG_BITS == 64) {
             /* The single-byte increment encodings are re-tasked as the
                REX prefixes.  Use the MODRM encoding.  */
commit 85948643b8df28ca87e41a1c4c7f16a66b4ac6cd
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Thu Jun 10 17:57:39 2010 +0000

    esp: lower IRQ on soft reset
    
    42f1ced228c9b616cfa2b69846025271618e4ef5 removed irq lowering
    during reset. However, for chip reset command and DMA reset signal,
    its actually the correct thing to do.
    
    Lower IRQ on soft reset only.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/esp.c b/hw/esp.c
index 0a8cf6e..7740879 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -419,7 +419,7 @@ static void handle_ti(ESPState *s)
     }
 }
 
-static void esp_reset(DeviceState *d)
+static void esp_hard_reset(DeviceState *d)
 {
     ESPState *s = container_of(d, ESPState, busdev.qdev);
 
@@ -435,10 +435,19 @@ static void esp_reset(DeviceState *d)
     s->rregs[ESP_CFG1] = 7;
 }
 
+static void esp_soft_reset(DeviceState *d)
+{
+    ESPState *s = container_of(d, ESPState, busdev.qdev);
+
+    qemu_irq_lower(s->irq);
+    esp_hard_reset(d);
+}
+
 static void parent_esp_reset(void *opaque, int irq, int level)
 {
-    if (level)
-        esp_reset(opaque);
+    if (level) {
+        esp_soft_reset(opaque);
+    }
 }
 
 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -528,7 +537,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             break;
         case CMD_RESET:
             DPRINTF("Chip reset (%2.2x)\n", val);
-            esp_reset(&s->busdev.qdev);
+            esp_soft_reset(&s->busdev.qdev);
             break;
         case CMD_BUSRESET:
             DPRINTF("Bus reset (%2.2x)\n", val);
@@ -679,7 +688,7 @@ static SysBusDeviceInfo esp_info = {
     .qdev.name  = "esp",
     .qdev.size  = sizeof(ESPState),
     .qdev.vmsd  = &vmstate_esp,
-    .qdev.reset = esp_reset,
+    .qdev.reset = esp_hard_reset,
     .qdev.props = (Property[]) {
         {.name = NULL}
     }
commit e163ae7b8f80dc4eb38445956929409601a8321c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu May 27 14:35:58 2010 +0900

    qbus: fix memory leak in qbus_free()
    
    BusState::name is allocated in qbus_create_inplace().
    So it should be freed by qbus_free().
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index aa2ce01..36f29ea 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -700,6 +700,7 @@ void qbus_free(BusState *bus)
         QLIST_REMOVE(bus, sibling);
         bus->parent->num_child_bus--;
     }
+    qemu_free((void*)bus->name);
     if (bus->qdev_allocated) {
         qemu_free(bus);
     }
commit bd418d90d0c67d7ea88420c6754a4677c09f91c1
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu May 27 14:37:09 2010 +0900

    multiboot: compilation fix with DEBUG_MULTIBOOT enabled.
    
    This patch fixes the following compilation errors in multiboot.c
    when DEBUG_MULTIBOOT is defined.
    Use TARGET_FMT_plx instead of %x for target_phys_addr_t.
    
      CC    i386-softmmu/multiboot.o
    cc1: warnings being treated as errors
    qemu/hw/multiboot.c: In function 'mb_add_mod':
    qemu/hw/multiboot.c:121: error: format '%08x' expects type 'unsigned int', but argument 4 has type 'target_phys_addr_t'
    qemu/hw/multiboot.c:121: error: format '%08x' expects type 'unsigned int', but argument 5 has type 'target_phys_addr_t'
    qemu/hw/multiboot.c: In function 'load_multiboot':
    qemu/hw/multiboot.c:279: error: format '%#x' expects type 'unsigned int', but argument 5 has type 'target_phys_addr_t'
    qemu/hw/multiboot.c:307: error: format '%x' expects type 'unsigned int', but argument 3 has type 'target_phys_addr_t'
    qemu/hw/multiboot.c:308: error: format '%x' expects type 'unsigned int', but argument 3 has type 'target_phys_addr_t'
    make[1]: *** [multiboot.o] Error 1
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index a1b665c..dc980e6 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -118,7 +118,8 @@ static void mb_add_mod(MultibootState *s,
     stl_p(p + MB_MOD_END,     end);
     stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
 
-    mb_debug("mod%02d: %08x - %08x\n", s->mb_mods_count, start, end);
+    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
+             s->mb_mods_count, start, end);
 
     s->mb_mods_count++;
 }
@@ -276,7 +277,7 @@ int load_multiboot(void *fw_cfg,
             mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
                        mbs.mb_buf_phys + offs + mb_mod_length, c);
 
-            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: %#x\n",
+            mb_debug("mod_start: %p\nmod_end:   %p\n  cmdline: "TARGET_FMT_plx"\n",
                      (char *)mbs.mb_buf + offs,
                      (char *)mbs.mb_buf + offs + mb_mod_length, c);
             initrd_filename = next_initrd+1;
@@ -304,8 +305,8 @@ int load_multiboot(void *fw_cfg,
     stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
 
     mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
-    mb_debug("           mb_buf_phys   = %x\n", mbs.mb_buf_phys);
-    mb_debug("           mod_start     = %x\n", mbs.mb_buf_phys + mbs.offset_mods);
+    mb_debug("           mb_buf_phys   = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
+    mb_debug("           mod_start     = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
     mb_debug("           mb_mods_count = %d\n", mbs.mb_mods_count);
 
     /* save bootinfo off the stack */
commit fe7f9567a6934566641751df233cb45675a9130c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu May 27 14:37:53 2010 +0900

    vga-isa-mm: remove one #ifdef CONFIG_BOCHS_VBE.
    
    remove one #ifdef CONFIG_BOCHS_VBE.
    Call vga_init_vbe() instead.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 2faefa5..8e31e36 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -121,10 +121,6 @@ int isa_vga_mm_init(target_phys_addr_t vram_base,
     s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
                                      s->vga.screen_dump, s->vga.text_update, s);
 
-#ifdef CONFIG_BOCHS_VBE
-    /* XXX: use optimized standard vga accesses */
-    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                 VGA_RAM_SIZE, s->vga.vram_offset);
-#endif
+    vga_init_vbe(&s->vga);
     return 0;
 }
commit 0f2ad63fcb75c9679ff7d47f6b2235dfc646de35
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu May 27 14:38:47 2010 +0900

    main: allocate gui_timer only once.
    
    fix memory leak.
    there is no need to allocate more than one gui_timer.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/vl.c b/vl.c
index 6d08ec8..3d7ce52 100644
--- a/vl.c
+++ b/vl.c
@@ -3794,6 +3794,7 @@ int main(int argc, char **argv, char **envp)
         if (dcl->dpy_refresh != NULL) {
             ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
             qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
+            break;
         }
         dcl = dcl->next;
     }
commit 60a3992e759d92b9111871b0881e65519c750b01
Merge: 77d4f95... 50e32ea...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Jun 10 09:21:43 2010 -0500

    Merge remote branch 'mst/for_anthony' into staging

commit 77d4f95e111a7c82bf21908f4de170b7e0e722bb
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Thu Jun 10 14:45:46 2010 +0200

    cris: Break out image loading to hw/cris-boot.c.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at axis.com>

diff --git a/Makefile.target b/Makefile.target
index d06c679..478b89d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -233,7 +233,10 @@ obj-microblaze-y += xilinx_ethlite.o
 obj-microblaze-$(CONFIG_FDT) += device_tree.o
 
 # Boards
-obj-cris-y = cris_pic_cpu.o etraxfs.o axis_dev88.o
+obj-cris-y = cris_pic_cpu.o
+obj-cris-y += cris-boot.o
+obj-cris-y += etraxfs.o axis_dev88.o
+obj-cris-y += axis_dev88.o
 
 # IO blocks
 obj-cris-y += etraxfs_dma.o
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 7d59c96..3ae4105 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -30,6 +30,7 @@
 #include "etraxfs.h"
 #include "loader.h"
 #include "elf.h"
+#include "cris-boot.h"
 
 #define D(x)
 #define DNAND(x)
@@ -240,28 +241,7 @@ static CPUWriteMemoryFunc * const gpio_write[] = {
 
 #define INTMEM_SIZE (128 * 1024)
 
-static struct {
-    uint32_t bootstrap_pc;
-    uint32_t regs[16];
-} loadargs;
-
-static void main_cpu_reset(void *opaque)
-{
-    int i;
-
-    CPUState *env = opaque;
-    cpu_reset(env);
-
-    env->pc = loadargs.bootstrap_pc;
-    for (i = 0; i < 16; i++) {
-        env->regs[i] = loadargs.regs[i];
-    }
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x80000000LL;
-}
+static struct cris_load_info li;
 
 static
 void axisdev88_init (ram_addr_t ram_size,
@@ -275,7 +255,6 @@ void axisdev88_init (ram_addr_t ram_size,
     qemu_irq irq[30], nmi[2], *cpu_irq;
     void *etraxfs_dmac;
     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
-    int kernel_size;
     int i;
     int nand_regs;
     int gpio_regs;
@@ -287,7 +266,6 @@ void axisdev88_init (ram_addr_t ram_size,
         cpu_model = "crisv32";
     }
     env = cpu_init(cpu_model);
-    qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
     phys_ram = qemu_ram_alloc(ram_size);
@@ -353,35 +331,14 @@ void axisdev88_init (ram_addr_t ram_size,
                              irq[0x14 + i]);
     }
 
-    if (kernel_filename) {
-        uint64_t entry, high;
-        int kcmdline_len;
-
-        /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
-           devboard SDK.  */
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               &entry, NULL, &high, 0, ELF_MACHINE, 0);
-        loadargs.bootstrap_pc = entry;
-        if (kernel_size < 0) {
-            /* Takes a kimage from the axis devboard SDK.  */
-            kernel_size = load_image_targphys(kernel_filename, 0x40004000,
-                                              ram_size);
-            loadargs.bootstrap_pc = 0x40004000;
-            loadargs.regs[9] = 0x40004000 + kernel_size;
-        }
-        loadargs.regs[8] = 0x56902387; /* RAM init magic.  */
-
-        if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
-            if (kcmdline_len > 256) {
-                fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
-                exit(1);
-            }
-            /* Let the kernel know we are modifying the cmdline.  */
-            loadargs.regs[10] = 0x87109563;
-            loadargs.regs[11] = 0x40000000;
-            pstrcpy_targphys("cmdline", loadargs.regs[11], 256, kernel_cmdline);
-        }
+    if (!kernel_filename) {
+        fprintf(stderr, "Kernel image must be specified\n");
+        exit(1);
     }
+
+    li.image_filename = kernel_filename;
+    li.cmdline = kernel_cmdline;
+    cris_load_image(env, &li);
 }
 
 static QEMUMachine axisdev88_machine = {
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
new file mode 100644
index 0000000..2ef17f6
--- /dev/null
+++ b/hw/cris-boot.c
@@ -0,0 +1,97 @@
+/*
+ * CRIS image loading.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * 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 "hw.h"
+#include "sysemu.h"
+#include "loader.h"
+#include "elf.h"
+#include "cris-boot.h"
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    struct cris_load_info *li;
+
+    li = env->load_info;
+
+    cpu_reset(env);
+
+    if (!li) {
+        /* nothing more to do.  */
+        return;
+    }
+
+    env->pc = li->entry;
+
+    if (li->image_filename) {
+        env->regs[8] = 0x56902387; /* RAM boot magic.  */
+        env->regs[9] = 0x40004000 + li->image_size;
+    }
+
+    if (li->cmdline) {
+        /* Let the kernel know we are modifying the cmdline.  */
+        env->regs[10] = 0x87109563;
+        env->regs[11] = 0x40000000;
+    }
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0x80000000LL;
+}
+
+void cris_load_image(CPUState *env, struct cris_load_info *li)
+{
+    uint64_t entry, high;
+    int kcmdline_len;
+    int image_size;
+
+    env->load_info = li;
+    /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
+       devboard SDK.  */
+    image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+                          &entry, NULL, &high, 0, ELF_MACHINE, 0);
+    li->entry = entry;
+    if (image_size < 0) {
+        /* Takes a kimage from the axis devboard SDK.  */
+        image_size = load_image_targphys(li->image_filename, 0x40004000,
+                                         ram_size);
+        li->entry = 0x40004000;
+    }
+
+    if (image_size < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                li->image_filename);
+        exit(1);
+    }
+
+    if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
+        if (kcmdline_len > 256) {
+            fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
+            exit(1);
+        }
+        pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
+    }
+    qemu_register_reset(main_cpu_reset, env);
+}
diff --git a/hw/cris-boot.h b/hw/cris-boot.h
new file mode 100644
index 0000000..e9caf8d
--- /dev/null
+++ b/hw/cris-boot.h
@@ -0,0 +1,11 @@
+
+struct cris_load_info
+{
+    const char *image_filename;
+    const char *cmdline;
+    int image_size;
+
+    target_phys_addr_t entry;
+};
+
+void cris_load_image(CPUState *env, struct cris_load_info *li);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index b88d00a..01bf929 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -30,23 +30,17 @@
 #include "etraxfs.h"
 #include "loader.h"
 #include "elf.h"
+#include "cris-boot.h"
 
 #define FLASH_SIZE 0x2000000
 #define INTMEM_SIZE (128 * 1024)
 
-static uint32_t bootstrap_pc;
+static struct cris_load_info li;
 
-static void main_cpu_reset(void *opaque)
+static void flash_cpu_reset(void *opaque)
 {
     CPUState *env = opaque;
     cpu_reset(env);
-
-    env->pc = bootstrap_pc;
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0x80000000LL;
 }
 
 static
@@ -61,7 +55,6 @@ void bareetraxfs_init (ram_addr_t ram_size,
     qemu_irq irq[30], nmi[2], *cpu_irq; 
     void *etraxfs_dmac;
     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
-    int kernel_size;
     DriveInfo *dinfo;
     int i;
     ram_addr_t phys_ram;
@@ -73,7 +66,6 @@ void bareetraxfs_init (ram_addr_t ram_size,
         cpu_model = "crisv32";
     }
     env = cpu_init(cpu_model);
-    qemu_register_reset(main_cpu_reset, env);
 
     /* allocate RAM */
     phys_ram = qemu_ram_alloc(ram_size);
@@ -137,38 +129,19 @@ void bareetraxfs_init (ram_addr_t ram_size,
     }
 
     if (kernel_filename) {
-        uint64_t entry, high;
-        int kcmdline_len;
-
-        /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis 
-           devboard SDK.  */
-        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
-                               &entry, NULL, &high, 0, ELF_MACHINE, 0);
-        bootstrap_pc = entry;
-        if (kernel_size < 0) {
-            /* Takes a kimage from the axis devboard SDK.  */
-            kernel_size = load_image_targphys(kernel_filename, 0x40004000,
-                                              ram_size);
-            bootstrap_pc = 0x40004000;
-            env->regs[9] = 0x40004000 + kernel_size;
+        li.image_filename = kernel_filename;
+        li.cmdline = kernel_cmdline;
+        cris_load_image(env, &li);
+    } else {
+        if (!dinfo) {
+            fprintf(stderr,
+                    "Provide a kernel image or a flash image to boot from.\n");
+           exit(1);
         }
-        env->regs[8] = 0x56902387; /* RAM init magic.  */
-
-        if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
-            if (kcmdline_len > 256) {
-                fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
-                exit(1);
-            }
-            /* Let the kernel know we are modifying the cmdline.  */
-            env->regs[10] = 0x87109563;
-            env->regs[11] = 0x40000000;
-            pstrcpy_targphys("cmdline", env->regs[11], 256, kernel_cmdline);
-        }
-    }
-    env->pc = bootstrap_pc;
 
-    printf ("pc =%x\n", env->pc);
-    printf ("ram size =%ld\n", ram_size);
+        /* Nothing more to do for flash images, those boot from addr 0.  */
+        qemu_register_reset(flash_cpu_reset, env);
+    }
 }
 
 static QEMUMachine bareetraxfs_machine = {
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 063a240..a62d57c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -155,6 +155,8 @@ typedef struct CPUCRISState {
 		uint32_t lo;
 	} tlbsets[2][4][16];
 
+	void *load_info;
+
 	CPU_COMMON
 } CPUCRISState;
 
commit 2024c53950fe2886e460ca3a5d3d2ce0f06bf0f8
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:17 2010 -0700

    s390: Disassemble some general-instruction-extension insns.
    
    The full general-instruction-extension facility was added to binutils
    after the change to GPLv3.  This is not the entire extension, just
    what we're using in TCG.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/s390-dis.c b/s390-dis.c
index db460f8..8abcdf0 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -172,6 +172,31 @@ static const struct s390_operand s390_operands[];
    the instruction may be optional.  */
 #define S390_OPERAND_OPTIONAL 0x400
 
+/* QEMU-ADD */
+/* ??? Not quite the format the assembler takes, but easy to implement
+   without recourse to the table generator.  */
+#define S390_OPERAND_CCODE  0x800
+
+static const char s390_ccode_name[16][4] = {
+    "n",    /* 0000 */
+    "o",    /* 0001 */
+    "h",    /* 0010 */
+    "nle",  /* 0011 */
+    "l",    /* 0100 */
+    "nhe",  /* 0101 */
+    "lh",   /* 0110 */
+    "ne",   /* 0111 */
+    "e",    /* 1000 */
+    "nlh",  /* 1001 */
+    "he",   /* 1010 */
+    "nl",   /* 1011 */
+    "le",   /* 1100 */
+    "nh",   /* 1101 */
+    "no",   /* 1110 */
+    "a"     /* 1111 */
+};
+/* QEMU-END */
+
 #endif /* S390_H */
 
 static int init_flag = 0;
@@ -325,13 +350,16 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 	    continue;
 
 	  /* The instruction is valid.  */
-	  if (opcode->operands[0] != 0)
-	    (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
-	  else
-	    (*info->fprintf_func) (info->stream, "%s", opcode->name);
+/* QEMU-MOD */
+         (*info->fprintf_func) (info->stream, "%s", opcode->name);
+
+         if (s390_operands[opcode->operands[0]].flags & S390_OPERAND_CCODE)
+           separator = 0;
+         else
+           separator = '\t';
+/* QEMU-END */
 
 	  /* Extract the operands.  */
-	  separator = 0;
 	  for (opindex = opcode->operands; *opindex != 0; opindex++)
 	    {
 	      unsigned int value;
@@ -363,6 +391,15 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 		(*info->print_address_func) (memaddr + (int) value, info);
 	      else if (operand->flags & S390_OPERAND_SIGNED)
 		(*info->fprintf_func) (info->stream, "%i", (int) value);
+/* QEMU-ADD */
+              else if (operand->flags & S390_OPERAND_CCODE)
+                {
+		  (*info->fprintf_func) (info->stream, "%s",
+                                         s390_ccode_name[(int) value]);
+                  separator = '\t';
+                  continue;
+                }
+/* QEMU-END */
 	      else
 		(*info->fprintf_func) (info->stream, "%u", value);
 
@@ -543,8 +580,16 @@ static const struct s390_operand s390_operands[] =
 #define M_16   42                 /* 4 bit optional mask starting at 16 */
   { 4, 16, S390_OPERAND_OPTIONAL },
 #define RO_28  43                 /* optional GPR starting at position 28 */
-  { 4, 28, (S390_OPERAND_GPR | S390_OPERAND_OPTIONAL) }
-
+  { 4, 28, (S390_OPERAND_GPR | S390_OPERAND_OPTIONAL) },
+
+/* QEMU-ADD: */
+#define M4_12 44                  /* 4-bit condition-code starting at 12 */
+  { 4, 12, S390_OPERAND_CCODE },
+#define M4_32 45                  /* 4-bit condition-code starting at 32 */
+  { 4, 32, S390_OPERAND_CCODE },
+#define I8_32 46                  /* 8 bit signed value starting at 32 */
+  { 8, 32, S390_OPERAND_SIGNED },
+/* QEMU-END */
 };
 
 
@@ -755,6 +800,14 @@ static const struct s390_operand s390_operands[] =
 #define MASK_S_RD        { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
 #define MASK_SSF_RRDRD   { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
 
+/* QEMU-ADD: */
+#define INSTR_RIE_MRRP   6, { M4_32,R_8,R_12,J16_16,0,0 }	/* e.g. crj */
+#define MASK_RIE_MRRP    { 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff }
+
+#define INSTR_RIE_MRIP   6, { M4_12,R_8,I8_32,J16_16,0,0 }      /* e.g. cij */
+#define MASK_RIE_MRIP    { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+/* QEMU-END */
+
 /* The opcode formats table (blueprints for .insn pseudo mnemonic).  */
 
 static const struct s390_opcode s390_opformats[] =
@@ -1092,6 +1145,10 @@ static const struct s390_opcode s390_opcodes[] =
   { "agfi", OP16(0xc208LL), MASK_RIL_RI, INSTR_RIL_RI, 2, 4},
   { "slfi", OP16(0xc205LL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
   { "slgfi", OP16(0xc204LL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
+/* QEMU-ADD: */
+  { "msfi",  OP16(0xc201ll), MASK_RIL_RI, INSTR_RIL_RI, 3, 6},
+  { "msgfi", OP16(0xc200ll), MASK_RIL_RI, INSTR_RIL_RI, 3, 6},
+/* QEMU-END */
   { "jg", OP16(0xc0f4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
   { "jgno", OP16(0xc0e4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
   { "jgnh", OP16(0xc0d4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
@@ -1716,7 +1773,23 @@ static const struct s390_opcode s390_opcodes[] =
   { "pfpo", OP16(0x010aLL), MASK_E, INSTR_E, 2, 5},
   { "sckpf", OP16(0x0107LL), MASK_E, INSTR_E, 3, 0},
   { "upt", OP16(0x0102LL), MASK_E, INSTR_E, 3, 0},
-  { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0}
+  { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0},
+
+/* QEMU-ADD: */
+  { "crj",   OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "cgrj",  OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "clrj",  OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+
+  { "cij",   OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "cgij",  OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "clij",  OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+
+  { "lrl",   OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lgrl",  OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+/* QEMU-END */
 };
 
 static const int s390_num_opcodes =
commit 402ce448af52a9dcb635b2f2020c469feeece3f5
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jun 4 12:14:16 2010 -0700

    s390: Update disassembler to the last GPLv2 from binutils.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/s390-dis.c b/s390-dis.c
index 86dd84f..db460f8 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -1,3 +1,4 @@
+/* opcodes/s390-dis.c revision 1.12 */
 /* s390-dis.c -- Disassemble S390 instructions
    Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -15,11 +16,14 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
-#include <stdio.h>
+#include "qemu-common.h"
 #include "dis-asm.h"
 
+/* include/opcode/s390.h revision 1.9 */
 /* s390.h -- Header file for S390 opcode table
    Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -37,7 +41,9 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 #ifndef S390_H
 #define S390_H
@@ -57,7 +63,8 @@ enum s390_opcode_cpu_val
     S390_OPCODE_Z900,
     S390_OPCODE_Z990,
     S390_OPCODE_Z9_109,
-    S390_OPCODE_Z9_EC
+    S390_OPCODE_Z9_EC,
+    S390_OPCODE_Z10
   };
 
 /* The opcode table is an array of struct s390_opcode.  */
@@ -95,12 +102,13 @@ struct s390_opcode
 /* The table itself is sorted by major opcode number, and is otherwise
    in the order in which the disassembler should consider
    instructions.  */
-extern const struct s390_opcode s390_opcodes[];
-extern const int                s390_num_opcodes;
+/* QEMU: Mark these static.  */
+static const struct s390_opcode s390_opcodes[];
+static const int                s390_num_opcodes;
 
 /* A opcode format table for the .insn pseudo mnemonic.  */
-extern const struct s390_opcode s390_opformats[];
-extern const int                s390_num_opformats;
+static const struct s390_opcode s390_opformats[];
+static const int                s390_num_opformats;
 
 /* Values defined for the flags field of a struct powerpc_opcode.  */
 
@@ -121,7 +129,7 @@ struct s390_operand
 /* Elements in the table are retrieved by indexing with values from
    the operands field of the powerpc_opcodes table.  */
 
-extern const struct s390_operand s390_operands[];
+static const struct s390_operand s390_operands[];
 
 /* Values defined for the flags field of a struct s390_operand.  */
 
@@ -164,12 +172,13 @@ extern const struct s390_operand s390_operands[];
    the instruction may be optional.  */
 #define S390_OPERAND_OPTIONAL 0x400
 
-	#endif /* S390_H */
-
+#endif /* S390_H */
 
 static int init_flag = 0;
 static int opc_index[256];
-static int current_arch_mask = 0;
+
+/* QEMU: We've disabled the architecture check below.  */
+/* static int current_arch_mask = 0; */
 
 /* Set up index table for first opcode byte.  */
 
@@ -188,17 +197,21 @@ init_disasm (struct disassemble_info *info)
 	     (opcode[1].opcode[0] == opcode->opcode[0]))
 	opcode++;
     }
-//  switch (info->mach)
-//    {
-//    case bfd_mach_s390_31:
+
+#ifdef QEMU_DISABLE
+  switch (info->mach)
+    {
+    case bfd_mach_s390_31:
       current_arch_mask = 1 << S390_OPCODE_ESA;
-//      break;
-//    case bfd_mach_s390_64:
-//      current_arch_mask = 1 << S390_OPCODE_ZARCH;
-//      break;
-//    default:
-//      abort ();
-//    }
+      break;
+    case bfd_mach_s390_64:
+      current_arch_mask = 1 << S390_OPCODE_ZARCH;
+      break;
+    default:
+      abort ();
+    }
+#endif /* QEMU_DISABLE */
+
   init_flag = 1;
 }
 
@@ -297,9 +310,12 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 	  const struct s390_operand *operand;
 	  const unsigned char *opindex;
 
+#ifdef QEMU_DISABLE
 	  /* Check architecture.  */
 	  if (!(opcode->modes & current_arch_mask))
 	    continue;
+#endif /* QEMU_DISABLE */
+
 	  /* Check signature of the opcode.  */
 	  if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
 	      || (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
@@ -392,6 +408,8 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
       return 1;
     }
 }
+
+/* opcodes/s390-opc.c revision 1.16 */
 /* s390-opc.c -- S390 opcode list
    Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -409,9 +427,9 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
-
-#include <stdio.h>
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* This file holds the S390 opcode table.  The opcode table
    includes almost all of the extended instruction mnemonics.  This
@@ -427,7 +445,7 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
 /* The operands table.
    The fields are bits, shift, insert, extract, flags.  */
 
-const struct s390_operand s390_operands[] =
+static const struct s390_operand s390_operands[] =
 {
 #define UNUSED 0
   { 0, 0, 0 },                    /* Indicates the end of the operand list */
@@ -739,7 +757,7 @@ const struct s390_operand s390_operands[] =
 
 /* The opcode formats table (blueprints for .insn pseudo mnemonic).  */
 
-const struct s390_opcode s390_opformats[] =
+static const struct s390_opcode s390_opformats[] =
   {
   { "e",	OP8(0x00LL),	MASK_E,		INSTR_E,	3, 0 },
   { "ri",	OP8(0x00LL),	MASK_RI_RI,	INSTR_RI_RI,	3, 0 },
@@ -765,9 +783,10 @@ const struct s390_opcode s390_opformats[] =
   { "ssf",	OP8(0x00LL),	MASK_SSF_RRDRD,	INSTR_SSF_RRDRD,3, 0 },
 };
 
-const int s390_num_opformats =
+static const int s390_num_opformats =
   sizeof (s390_opformats) / sizeof (s390_opformats[0]);
 
+/* include "s390-opc.tab" generated from opcodes/s390-opc.txt rev 1.17 */
 /* The opcode table. This file was generated by s390-mkopc.
 
    The format of the opcode table is:
@@ -783,7 +802,7 @@ const int s390_num_opformats =
    The disassembler reads the table in order and prints the first
    instruction which matches.  */
 
-const struct s390_opcode s390_opcodes[] =
+static const struct s390_opcode s390_opcodes[] =
   {
   { "dp", OP8(0xfdLL), MASK_SS_LLRDRD, INSTR_SS_LLRDRD, 3, 0},
   { "mp", OP8(0xfcLL), MASK_SS_LLRDRD, INSTR_SS_LLRDRD, 3, 0},
@@ -1700,5 +1719,5 @@ const struct s390_opcode s390_opcodes[] =
   { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0}
 };
 
-const int s390_num_opcodes =
+static const int s390_num_opcodes =
   sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);
commit 5d8a4f8f4aa5b63eb3cc2a2234ffb8d4f0a2af50
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Jun 3 17:35:17 2010 -0700

    tcg-i386: Merge 64-bit generation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 46b8e39..fa7f299 100755
--- a/configure
+++ b/configure
@@ -2643,6 +2643,8 @@ if test "$ARCH" = "sparc64" ; then
   cflags="-I\$(SRC_PATH)/tcg/sparc $cflags"
 elif test "$ARCH" = "s390x" ; then
   cflags="-I\$(SRC_PATH)/tcg/s390 $cflags"
+elif test "$ARCH" = "x86_64" ; then
+  cflags="-I\$(SRC_PATH)/tcg/i386 $cflags"
 else
   cflags="-I\$(SRC_PATH)/tcg/\$(ARCH) $cflags"
 fi
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 147ba17..4d95200 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -24,18 +24,33 @@
 
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
-    "%eax",
-    "%ecx",
-    "%edx",
-    "%ebx",
-    "%esp",
-    "%ebp",
-    "%esi",
-    "%edi",
+#if TCG_TARGET_REG_BITS == 64
+    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+#else
+    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+#endif
 };
 #endif
 
 static const int tcg_target_reg_alloc_order[] = {
+#if TCG_TARGET_REG_BITS == 64
+    TCG_REG_RBP,
+    TCG_REG_RBX,
+    TCG_REG_R12,
+    TCG_REG_R13,
+    TCG_REG_R14,
+    TCG_REG_R15,
+    TCG_REG_R10,
+    TCG_REG_R11,
+    TCG_REG_R9,
+    TCG_REG_R8,
+    TCG_REG_RCX,
+    TCG_REG_RDX,
+    TCG_REG_RSI,
+    TCG_REG_RDI,
+    TCG_REG_RAX,
+#else
     TCG_REG_EBX,
     TCG_REG_ESI,
     TCG_REG_EDI,
@@ -43,10 +58,28 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_ECX,
     TCG_REG_EDX,
     TCG_REG_EAX,
+#endif
 };
 
-static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
-static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
+static const int tcg_target_call_iarg_regs[] = {
+#if TCG_TARGET_REG_BITS == 64
+    TCG_REG_RDI,
+    TCG_REG_RSI,
+    TCG_REG_RDX,
+    TCG_REG_RCX,
+    TCG_REG_R8,
+    TCG_REG_R9,
+#else
+    TCG_REG_EAX,
+    TCG_REG_EDX,
+    TCG_REG_ECX
+#endif
+};
+
+static const int tcg_target_call_oarg_regs[2] = {
+    TCG_REG_EAX,
+    TCG_REG_EDX
+};
 
 static uint8_t *tb_ret_addr;
 
@@ -55,14 +88,15 @@ static void patch_reloc(uint8_t *code_ptr, int type,
 {
     value += addend;
     switch(type) {
-    case R_386_32:
-        *(uint32_t *)code_ptr = value;
-        break;
     case R_386_PC32:
-        *(uint32_t *)code_ptr = value - (long)code_ptr;
+        value -= (uintptr_t)code_ptr;
+        if (value != (int32_t)value) {
+            tcg_abort();
+        }
+        *(uint32_t *)code_ptr = value;
         break;
     case R_386_PC8:
-        value -= (long)code_ptr;
+        value -= (uintptr_t)code_ptr;
         if (value != (int8_t)value) {
             tcg_abort();
         }
@@ -76,6 +110,10 @@ static void patch_reloc(uint8_t *code_ptr, int type,
 /* maximum number of register used for input function arguments */
 static inline int tcg_target_get_call_iarg_regs_count(int flags)
 {
+    if (TCG_TARGET_REG_BITS == 64) {
+        return 6;
+    }
+
     flags &= TCG_CALL_TYPE_MASK;
     switch(flags) {
     case TCG_CALL_TYPE_STD:
@@ -122,20 +160,42 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
         break;
     case 'q':
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xf);
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_regset_set32(ct->u.regs, 0, 0xffff);
+        } else {
+            tcg_regset_set32(ct->u.regs, 0, 0xf);
+        }
         break;
     case 'r':
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xff);
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_regset_set32(ct->u.regs, 0, 0xffff);
+        } else {
+            tcg_regset_set32(ct->u.regs, 0, 0xff);
+        }
         break;
 
         /* qemu_ld/st address constraint */
     case 'L':
         ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_regset_set32(ct->u.regs, 0, 0xffff);
+            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
+            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
+        } else {
+            tcg_regset_set32(ct->u.regs, 0, 0xff);
+            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
+            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
+        }
+        break;
+
+    case 'e':
+        ct->ct |= TCG_CT_CONST_S32;
+        break;
+    case 'Z':
+        ct->ct |= TCG_CT_CONST_U32;
         break;
+
     default:
         return -1;
     }
@@ -148,16 +208,38 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 static inline int tcg_target_const_match(tcg_target_long val,
                                          const TCGArgConstraint *arg_ct)
 {
-    int ct;
-    ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST)
+    int ct = arg_ct->ct;
+    if (ct & TCG_CT_CONST) {
         return 1;
-    else
-        return 0;
+    }
+    if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
+        return 1;
+    }
+    if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
+        return 1;
+    }
+    return 0;
 }
 
+#if TCG_TARGET_REG_BITS == 64
+# define LOWREGMASK(x)	((x) & 7)
+#else
+# define LOWREGMASK(x)	(x)
+#endif
+
 #define P_EXT		0x100		/* 0x0f opcode prefix */
 #define P_DATA16	0x200		/* 0x66 opcode prefix */
+#if TCG_TARGET_REG_BITS == 64
+# define P_ADDR32	0x400		/* 0x67 opcode prefix */
+# define P_REXW		0x800		/* Set REX.W = 1 */
+# define P_REXB_R	0x1000		/* REG field as byte register */
+# define P_REXB_RM	0x2000		/* R/M field as byte register */
+#else
+# define P_ADDR32	0
+# define P_REXW		0
+# define P_REXB_R	0
+# define P_REXB_RM	0
+#endif
 
 #define OPC_ARITH_EvIz	(0x81)
 #define OPC_ARITH_EvIb	(0x83)
@@ -179,9 +261,11 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define OPC_MOVB_EvGv	(0x88)		/* stores, more or less */
 #define OPC_MOVL_EvGv	(0x89)		/* stores, more or less */
 #define OPC_MOVL_GvEv	(0x8b)		/* loads, more or less */
+#define OPC_MOVL_EvIz	(0xc7)
 #define OPC_MOVL_Iv     (0xb8)
 #define OPC_MOVSBL	(0xbe | P_EXT)
 #define OPC_MOVSWL	(0xbf | P_EXT)
+#define OPC_MOVSLQ	(0x63 | P_REXW)
 #define OPC_MOVZBL	(0xb6 | P_EXT)
 #define OPC_MOVZWL	(0xb7 | P_EXT)
 #define OPC_POP_r32	(0x58)
@@ -189,7 +273,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define OPC_PUSH_Iv	(0x68)
 #define OPC_PUSH_Ib	(0x6a)
 #define OPC_RET		(0xc3)
-#define OPC_SETCC	(0x90 | P_EXT)	/* ... plus condition code */
+#define OPC_SETCC	(0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
 #define OPC_SHIFT_1	(0xd1)
 #define OPC_SHIFT_Ib	(0xc1)
 #define OPC_SHIFT_cl	(0xd3)
@@ -226,6 +310,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define EXT3_IDIV  7
 
 /* Group 5 opcode extensions for 0xff.  To be used with OPC_GRP5.  */
+#define EXT5_INC_Ev	0
+#define EXT5_DEC_Ev	1
 #define EXT5_CALLN_Ev	2
 #define EXT5_JMPN_Ev	4
 
@@ -261,7 +347,45 @@ static const uint8_t tcg_cond_to_jcc[10] = {
     [TCG_COND_GTU] = JCC_JA,
 };
 
-static inline void tcg_out_opc(TCGContext *s, int opc)
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
+{
+    int rex;
+
+    if (opc & P_DATA16) {
+        /* We should never be asking for both 16 and 64-bit operation.  */
+        assert((opc & P_REXW) == 0);
+        tcg_out8(s, 0x66);
+    }
+    if (opc & P_ADDR32) {
+        tcg_out8(s, 0x67);
+    }
+
+    rex = 0;
+    rex |= (opc & P_REXW) >> 8;		/* REX.W */
+    rex |= (r & 8) >> 1;		/* REX.R */
+    rex |= (x & 8) >> 2;		/* REX.X */
+    rex |= (rm & 8) >> 3;		/* REX.B */
+
+    /* P_REXB_{R,RM} indicates that the given register is the low byte.
+       For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
+       as otherwise the encoding indicates %[abcd]h.  Note that the values
+       that are ORed in merely indicate that the REX byte must be present;
+       those bits get discarded in output.  */
+    rex |= opc & (r >= 4 ? P_REXB_R : 0);
+    rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
+
+    if (rex) {
+        tcg_out8(s, (uint8_t)(rex | 0x40));
+    }
+
+    if (opc & P_EXT) {
+        tcg_out8(s, 0x0f);
+    }
+    tcg_out8(s, opc);
+}
+#else
+static void tcg_out_opc(TCGContext *s, int opc)
 {
     if (opc & P_DATA16) {
         tcg_out8(s, 0x66);
@@ -271,36 +395,69 @@ static inline void tcg_out_opc(TCGContext *s, int opc)
     }
     tcg_out8(s, opc);
 }
+/* Discard the register arguments to tcg_out_opc early, so as not to penalize
+   the 32-bit compilation paths.  This method works with all versions of gcc,
+   whereas relying on optimization may not be able to exclude them.  */
+#define tcg_out_opc(s, opc, r, rm, x)  (tcg_out_opc)(s, opc)
+#endif
 
-static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
+static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
 {
-    tcg_out_opc(s, opc);
-    tcg_out8(s, 0xc0 | (r << 3) | rm);
+    tcg_out_opc(s, opc, r, rm, 0);
+    tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
 }
 
 /* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
-   We handle either RM and INDEX missing with a -1 value.  */
+   We handle either RM and INDEX missing with a negative value.  In 64-bit
+   mode for absolute addresses, ~RM is the size of the immediate operand
+   that will follow the instruction.  */
 
 static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
-                                     int index, int shift, int32_t offset)
+                                     int index, int shift,
+                                     tcg_target_long offset)
 {
     int mod, len;
 
-    if (index == -1 && rm == -1) {
-        /* Absolute address.  */
-        tcg_out_opc(s, opc);
-        tcg_out8(s, (r << 3) | 5);
-        tcg_out32(s, offset);
-        return;
-    }
+    if (index < 0 && rm < 0) {
+        if (TCG_TARGET_REG_BITS == 64) {
+            /* Try for a rip-relative addressing mode.  This has replaced
+               the 32-bit-mode absolute addressing encoding.  */
+            tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
+            tcg_target_long disp = offset - pc;
+            if (disp == (int32_t)disp) {
+                tcg_out_opc(s, opc, r, 0, 0);
+                tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
+                tcg_out32(s, disp);
+                return;
+            }
 
-    tcg_out_opc(s, opc);
+            /* Try for an absolute address encoding.  This requires the
+               use of the MODRM+SIB encoding and is therefore larger than
+               rip-relative addressing.  */
+            if (offset == (int32_t)offset) {
+                tcg_out_opc(s, opc, r, 0, 0);
+                tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
+                tcg_out8(s, (4 << 3) | 5);
+                tcg_out32(s, offset);
+                return;
+            }
+
+            /* ??? The memory isn't directly addressable.  */
+            tcg_abort();
+        } else {
+            /* Absolute address.  */
+            tcg_out_opc(s, opc, r, 0, 0);
+            tcg_out8(s, (r << 3) | 5);
+            tcg_out32(s, offset);
+            return;
+        }
+    }
 
     /* Find the length of the immediate addend.  Note that the encoding
        that would be used for (%ebp) indicates absolute addressing.  */
-    if (rm == -1) {
+    if (rm < 0) {
         mod = 0, len = 4, rm = 5;
-    } else if (offset == 0 && rm != TCG_REG_EBP) {
+    } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
         mod = 0, len = 0;
     } else if (offset == (int8_t)offset) {
         mod = 0x40, len = 1;
@@ -310,22 +467,25 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
 
     /* Use a single byte MODRM format if possible.  Note that the encoding
        that would be used for %esp is the escape to the two byte form.  */
-    if (index == -1 && rm != TCG_REG_ESP) {
+    if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
         /* Single byte MODRM format.  */
-        tcg_out8(s, mod | (r << 3) | rm);
+        tcg_out_opc(s, opc, r, rm, 0);
+        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
     } else {
         /* Two byte MODRM+SIB format.  */
 
         /* Note that the encoding that would place %esp into the index
-           field indicates no index register.  */
-        if (index == -1) {
+           field indicates no index register.  In 64-bit mode, the REX.X
+           bit counts, so %r12 can be used as the index.  */
+        if (index < 0) {
             index = 4;
         } else {
             assert(index != TCG_REG_ESP);
         }
 
-        tcg_out8(s, mod | (r << 3) | 4);
-        tcg_out8(s, (shift << 6) | (index << 3) | rm);
+        tcg_out_opc(s, opc, r, rm, index);
+        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
+        tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
     }
 
     if (len == 1) {
@@ -335,9 +495,9 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
     }
 }
 
-/* rm == -1 means no register index */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
-                                        int32_t offset)
+/* A simplification of the above with no index or shift.  */
+static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
+                                        int rm, tcg_target_long offset)
 {
     tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
 }
@@ -345,58 +505,75 @@ static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
 /* Generate dest op= src.  Uses the same ARITH_* codes as tgen_arithi.  */
 static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
 {
-    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
+    /* Propagate an opcode prefix, such as P_REXW.  */
+    int ext = subop & ~0x7;
+    subop &= 0x7;
+
+    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
 }
 
 static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     if (arg != ret) {
-        tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
+        int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+        tcg_out_modrm(s, opc, ret, arg);
     }
 }
 
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
-                                int ret, int32_t arg)
+static void tcg_out_movi(TCGContext *s, TCGType type,
+                         int ret, tcg_target_long arg)
 {
     if (arg == 0) {
         tgen_arithr(s, ARITH_XOR, ret, ret);
+        return;
+    } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
+        tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
+        tcg_out32(s, arg);
+    } else if (arg == (int32_t)arg) {
+        tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
+        tcg_out32(s, arg);
     } else {
-        tcg_out8(s, OPC_MOVL_Iv + ret);
+        tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
         tcg_out32(s, arg);
+        tcg_out32(s, arg >> 31 >> 1);
     }
 }
 
 static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
 {
     if (val == (int8_t)val) {
-        tcg_out_opc(s, OPC_PUSH_Ib);
+        tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
         tcg_out8(s, val);
-    } else {
-        tcg_out_opc(s, OPC_PUSH_Iv);
+    } else if (val == (int32_t)val) {
+        tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
         tcg_out32(s, val);
+    } else {
+        tcg_abort();
     }
 }
 
 static inline void tcg_out_push(TCGContext *s, int reg)
 {
-    tcg_out_opc(s, OPC_PUSH_r32 + reg);
+    tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
 }
 
 static inline void tcg_out_pop(TCGContext *s, int reg)
 {
-    tcg_out_opc(s, OPC_POP_r32 + reg);
+    tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
 }
 
 static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
                               int arg1, tcg_target_long arg2)
 {
-    tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
+    int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+    tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
 }
 
 static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                               int arg1, tcg_target_long arg2)
 {
-    tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
+    int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+    tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
 }
 
 static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
@@ -406,35 +583,35 @@ static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
     subopc &= 0x7;
 
     if (count == 1) {
-        tcg_out_modrm(s, OPC_SHIFT_1 | ext, subopc, reg);
+        tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
     } else {
-        tcg_out_modrm(s, OPC_SHIFT_Ib | ext, subopc, reg);
+        tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
         tcg_out8(s, count);
     }
 }
 
 static inline void tcg_out_bswap32(TCGContext *s, int reg)
 {
-    tcg_out_opc(s, OPC_BSWAP + reg);
+    tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
 }
 
 static inline void tcg_out_rolw_8(TCGContext *s, int reg)
 {
-    tcg_out_shifti(s, SHIFT_ROL | P_DATA16, reg, 8);
+    tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
 }
 
 static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
 {
     /* movzbl */
-    assert(src < 4);
-    tcg_out_modrm(s, OPC_MOVZBL, dest, src);
+    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
+    tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
 }
 
-static void tcg_out_ext8s(TCGContext *s, int dest, int src)
+static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
 {
     /* movsbl */
-    assert(src < 4);
-    tcg_out_modrm(s, OPC_MOVSBL, dest, src);
+    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
+    tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
 }
 
 static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
@@ -443,38 +620,94 @@ static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
     tcg_out_modrm(s, OPC_MOVZWL, dest, src);
 }
 
-static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
+static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
 {
-    /* movswl */
-    tcg_out_modrm(s, OPC_MOVSWL, dest, src);
+    /* movsw[lq] */
+    tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
 }
 
-static inline void tgen_arithi(TCGContext *s, int c, int r0,
-                               int32_t val, int cf)
+static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
 {
+    /* 32-bit mov zero extends.  */
+    tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
+}
+
+static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
+{
+    tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
+}
+
+static inline void tcg_out_bswap64(TCGContext *s, int reg)
+{
+    tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
+}
+
+static void tgen_arithi(TCGContext *s, int c, int r0,
+                        tcg_target_long val, int cf)
+{
+    int rexw = 0;
+
+    if (TCG_TARGET_REG_BITS == 64) {
+        rexw = c & -8;
+        c &= 7;
+    }
+
     /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
        partial flags update stalls on Pentium4 and are not recommended
        by current Intel optimization manuals.  */
     if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
-        int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
-        tcg_out_opc(s, opc + r0);
-    } else if (val == (int8_t)val) {
-        tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
+        _Bool is_inc = (c == ARITH_ADD) ^ (val < 0);
+        if (TCG_TARGET_REG_BITS == 64) {
+            /* The single-byte increment encodings are re-tasked as the
+               REX prefixes.  Use the MODRM encoding.  */
+            tcg_out_modrm(s, OPC_GRP5 + rexw,
+                          (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
+        } else {
+            tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
+        }
+        return;
+    }
+
+    if (c == ARITH_AND) {
+        if (TCG_TARGET_REG_BITS == 64) {
+            if (val == 0xffffffffu) {
+                tcg_out_ext32u(s, r0, r0);
+                return;
+            }
+            if (val == (uint32_t)val) {
+                /* AND with no high bits set can use a 32-bit operation.  */
+                rexw = 0;
+            }
+        }
+        if (val == 0xffu) {
+            tcg_out_ext8u(s, r0, r0);
+            return;
+        }
+        if (val == 0xffffu) {
+            tcg_out_ext16u(s, r0, r0);
+            return;
+        }
+    }
+
+    if (val == (int8_t)val) {
+        tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
         tcg_out8(s, val);
-    } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
-        tcg_out_ext8u(s, r0, r0);
-    } else if (c == ARITH_AND && val == 0xffffu) {
-        tcg_out_ext16u(s, r0, r0);
-    } else {
-        tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
+        return;
+    }
+    if (rexw == 0 || val == (int32_t)val) {
+        tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
         tcg_out32(s, val);
+        return;
     }
+
+    tcg_abort();
 }
 
 static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
 {
-    if (val != 0)
-        tgen_arithi(s, ARITH_ADD, reg, val, 0);
+    if (val != 0) {
+        tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
+    }
 }
 
 /* Use SMALL != 0 to force a short forward branch.  */
@@ -501,7 +734,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
                 tcg_out8(s, OPC_JMP_long);
                 tcg_out32(s, val - 5);
             } else {
-                tcg_out_opc(s, OPC_JCC_long + opc);
+                tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
                 tcg_out32(s, val - 6);
             }
         }
@@ -517,7 +750,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
         if (opc == -1) {
             tcg_out8(s, OPC_JMP_long);
         } else {
-            tcg_out_opc(s, OPC_JCC_long + opc);
+            tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
         }
         tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
         s->code_ptr += 4;
@@ -525,28 +758,37 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
 }
 
 static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
-                        int const_arg2)
+                        int const_arg2, int rexw)
 {
     if (const_arg2) {
         if (arg2 == 0) {
             /* test r, r */
-            tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
+            tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
         } else {
-            tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
+            tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
         }
     } else {
-        tgen_arithr(s, ARITH_CMP, arg1, arg2);
+        tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
     }
 }
 
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
-                           TCGArg arg1, TCGArg arg2, int const_arg2,
-                           int label_index, int small)
+static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
+                             TCGArg arg1, TCGArg arg2, int const_arg2,
+                             int label_index, int small)
 {
-    tcg_out_cmp(s, arg1, arg2, const_arg2);
+    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
     tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
 }
 
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
+                             TCGArg arg1, TCGArg arg2, int const_arg2,
+                             int label_index, int small)
+{
+    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
+    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
+}
+#else
 /* 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,
@@ -556,87 +798,97 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
     label_next = gen_new_label();
     switch(args[4]) {
     case TCG_COND_EQ:
-        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
-                       label_next, 1);
-        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
+                         label_next, 1);
+        tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
+                         args[5], small);
         break;
     case TCG_COND_NE:
-        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
-                       args[5], small);
-        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
+                         args[5], small);
+        tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
+                         args[5], small);
         break;
     case TCG_COND_LT:
-        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_LE:
-        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_GT:
-        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_GE:
-        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_LTU:
-        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_LEU:
-        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_GTU:
-        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     case TCG_COND_GEU:
-        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
+                         args[5], small);
         tcg_out_jxx(s, JCC_JNE, label_next, 1);
-        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
-                       args[5], small);
+        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
+                         args[5], small);
         break;
     default:
         tcg_abort();
     }
     tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
 }
+#endif
 
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
-                            TCGArg arg1, TCGArg arg2, int const_arg2)
+static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
+                              TCGArg arg1, TCGArg arg2, int const_arg2)
 {
-    tcg_out_cmp(s, arg1, arg2, const_arg2);
+    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
     tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
     tcg_out_ext8u(s, dest, dest);
 }
 
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
+                              TCGArg arg1, TCGArg arg2, int const_arg2)
+{
+    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
+    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
+    tcg_out_ext8u(s, dest, dest);
+}
+#else
 static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
                              const int *const_args)
 {
@@ -678,11 +930,30 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
         tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
     }
 }
+#endif
+
+static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
+{
+    tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
+
+    if (disp == (int32_t)disp) {
+        tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
+        tcg_out32(s, disp);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
+        tcg_out_modrm(s, OPC_GRP5,
+                      call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
+    }
+}
+
+static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+{
+    tcg_out_branch(s, 1, dest);
+}
 
-static void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
 {
-    tcg_out_opc(s, OPC_CALL_Jz);
-    tcg_out32(s, dest - (tcg_target_long)s->code_ptr - 4);
+    tcg_out_branch(s, 0, dest);
 }
 
 #if defined(CONFIG_SOFTMMU)
@@ -718,11 +989,12 @@ static void *qemu_st_helpers[4] = {
    LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
    positions of the displacements of forward jumps to the TLB miss case.
 
-   EAX is loaded with the low part of the address.  In the TLB hit case,
-   it has been adjusted as indicated by the TLB and so is a host address.
-   In the TLB miss case, it continues to hold a guest address.
+   First argument register is loaded with the low part of the address.
+   In the TLB hit case, it has been adjusted as indicated by the TLB
+   and so is a host address.  In the TLB miss case, it continues to
+   hold a guest address.
 
-   EDX is clobbered.  */
+   Second argument register is clobbered.  */
 
 static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
                                     int mem_index, int s_bits,
@@ -730,32 +1002,42 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
                                     uint8_t **label_ptr, int which)
 {
     const int addrlo = args[addrlo_idx];
-    const int r0 = TCG_REG_EAX;
-    const int r1 = TCG_REG_EDX;
+    const int r0 = tcg_target_call_iarg_regs[0];
+    const int r1 = tcg_target_call_iarg_regs[1];
+    TCGType type = TCG_TYPE_I32;
+    int rexw = 0;
+
+    if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
+        type = TCG_TYPE_I64;
+        rexw = P_REXW;
+    }
 
-    tcg_out_mov(s, TCG_TYPE_I32, r1, addrlo);
-    tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
+    tcg_out_mov(s, type, r1, addrlo);
+    tcg_out_mov(s, type, r0, addrlo);
 
-    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+    tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
+                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 
-    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
-    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
+    tgen_arithi(s, ARITH_AND + rexw, r0,
+                TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+    tgen_arithi(s, ARITH_AND + rexw, r1,
+                (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
 
-    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+    tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
                              offsetof(CPUState, tlb_table[mem_index][0])
                              + which);
 
     /* cmp 0(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
+    tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
 
-    tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
+    tcg_out_mov(s, type, r0, addrlo);
 
     /* jne label1 */
     tcg_out8(s, OPC_JCC_short + JCC_JNE);
     label_ptr[0] = s->code_ptr;
     s->code_ptr++;
 
-    if (TARGET_LONG_BITS == 64) {
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
         /* cmp 4(r1), addrhi */
         tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
 
@@ -768,7 +1050,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
     /* TLB Hit.  */
 
     /* add addend(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+    tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
                          offsetof(CPUTLBEntry, addend) - which);
 }
 #endif
@@ -783,26 +1065,24 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
 #endif
     switch (sizeop) {
     case 0:
-        /* movzbl */
         tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
         break;
     case 0 | 4:
-        /* movsbl */
-        tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
+        tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
         break;
     case 1:
-        /* movzwl */
         tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
         if (bswap) {
             tcg_out_rolw_8(s, datalo);
         }
         break;
     case 1 | 4:
-        /* movswl */
-        tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
         if (bswap) {
+            tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
             tcg_out_rolw_8(s, datalo);
-            tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
+            tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
+        } else {
+            tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
         }
         break;
     case 2:
@@ -811,22 +1091,40 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
             tcg_out_bswap32(s, datalo);
         }
         break;
-    case 3:
+#if TCG_TARGET_REG_BITS == 64
+    case 2 | 4:
         if (bswap) {
-            int t = datalo;
-            datalo = datahi;
-            datahi = t;
-        }
-        if (base != datalo) {
             tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
-            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+            tcg_out_bswap32(s, datalo);
+            tcg_out_ext32s(s, datalo, datalo);
         } else {
-            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
-            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+            tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
         }
-        if (bswap) {
-            tcg_out_bswap32(s, datalo);
-            tcg_out_bswap32(s, datahi);
+        break;
+#endif
+    case 3:
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
+            if (bswap) {
+                tcg_out_bswap64(s, datalo);
+            }
+        } else {
+            if (bswap) {
+                int t = datalo;
+                datalo = datahi;
+                datahi = t;
+            }
+            if (base != datalo) {
+                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+            } else {
+                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+            }
+            if (bswap) {
+                tcg_out_bswap32(s, datalo);
+                tcg_out_bswap32(s, datahi);
+            }
         }
         break;
     default:
@@ -849,20 +1147,21 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     data_reg = args[0];
     addrlo_idx = 1;
-    if (opc == 3) {
+    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
         data_reg2 = args[1];
         addrlo_idx = 2;
     }
 
 #if defined(CONFIG_SOFTMMU)
-    mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
     s_bits = opc & 3;
 
     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                      label_ptr, offsetof(CPUTLBEntry, addr_read));
 
     /* TLB Hit.  */
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
+                           tcg_target_call_iarg_regs[0], 0, opc);
 
     /* jmp label2 */
     tcg_out8(s, OPC_JMP_short);
@@ -873,14 +1172,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     /* label1: */
     *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
-    if (TARGET_LONG_BITS == 64) {
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
         *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
     }
 
     /* XXX: move that code at the end of the TB */
-    /* EAX is already loaded.  */
+    /* The first argument is already loaded with addrlo.  */
     arg_idx = 1;
-    if (TARGET_LONG_BITS == 64) {
+    if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
         tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
                     args[addrlo_idx + 1]);
     }
@@ -890,10 +1189,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     switch(opc) {
     case 0 | 4:
-        tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
+        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
         break;
     case 1 | 4:
-        tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
+        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
         break;
     case 0:
         tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
@@ -902,26 +1201,52 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
         break;
     case 2:
-    default:
         tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
         break;
+#if TCG_TARGET_REG_BITS == 64
+    case 2 | 4:
+        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
+        break;
+#endif
     case 3:
-        if (data_reg == TCG_REG_EDX) {
+        if (TCG_TARGET_REG_BITS == 64) {
+            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
+        } else if (data_reg == TCG_REG_EDX) {
             /* xchg %edx, %eax */
-            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
+            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
             tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
         } else {
             tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
             tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
         }
         break;
+    default:
+        tcg_abort();
     }
 
     /* label2: */
     *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
-                           args[addrlo_idx], GUEST_BASE, opc);
+    {
+        int32_t offset = GUEST_BASE;
+        int base = args[addrlo_idx];
+
+        if (TCG_TARGET_REG_BITS == 64) {
+            /* ??? We assume all operations have left us with register
+               contents that are zero extended.  So far this appears to
+               be true.  If we want to enforce this, we can either do
+               an explicit zero-extension here, or (if GUEST_BASE == 0)
+               use the ADDR32 prefix.  For now, do nothing.  */
+
+            if (offset != GUEST_BASE) {
+                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
+                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
+                base = TCG_REG_RDI, offset = 0;
+            }
+        }
+
+        tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
+    }
 #endif
 }
 
@@ -936,12 +1261,12 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
     /* ??? Ideally we wouldn't need a scratch register.  For user-only,
        we could perform the bswap twice to restore the original value
        instead of moving to the scratch.  But as it is, the L constraint
-       means that EDX is definitely free here.  */
-    int scratch = TCG_REG_EDX;
+       means that the second argument reg is definitely free here.  */
+    int scratch = tcg_target_call_iarg_regs[1];
 
     switch (sizeop) {
     case 0:
-        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
+        tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
         break;
     case 1:
         if (bswap) {
@@ -949,9 +1274,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
             tcg_out_rolw_8(s, scratch);
             datalo = scratch;
         }
-        /* movw */
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
-                             datalo, base, ofs);
+        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
         break;
     case 2:
         if (bswap) {
@@ -962,7 +1285,14 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
         break;
     case 3:
-        if (bswap) {
+        if (TCG_TARGET_REG_BITS == 64) {
+            if (bswap) {
+                tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
+                tcg_out_bswap64(s, scratch);
+                datalo = scratch;
+            }
+            tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
+        } else if (bswap) {
             tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
             tcg_out_bswap32(s, scratch);
             tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
@@ -992,20 +1322,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     data_reg = args[0];
     addrlo_idx = 1;
-    if (opc == 3) {
+    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
         data_reg2 = args[1];
         addrlo_idx = 2;
     }
 
 #if defined(CONFIG_SOFTMMU)
-    mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
     s_bits = opc;
 
     tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
                      label_ptr, offsetof(CPUTLBEntry, addr_write));
 
     /* TLB Hit.  */
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2,
+                           tcg_target_call_iarg_regs[0], 0, opc);
 
     /* jmp label2 */
     tcg_out8(s, OPC_JMP_short);
@@ -1016,12 +1347,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     /* label1: */
     *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
-    if (TARGET_LONG_BITS == 64) {
+    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
         *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
     }
 
     /* XXX: move that code at the end of the TB */
-    if (TARGET_LONG_BITS == 32) {
+    if (TCG_TARGET_REG_BITS == 64) {
+        tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+                    TCG_REG_RSI, data_reg);
+        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
+        stack_adjust = 0;
+    } else if (TARGET_LONG_BITS == 32) {
         tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
         if (opc == 3) {
             tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
@@ -1058,7 +1394,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
 
-    if (stack_adjust == 4) {
+    if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
         /* Pop and discard.  This is 2 bytes smaller than the add.  */
         tcg_out_pop(s, TCG_REG_ECX);
     } else if (stack_adjust != 0) {
@@ -1068,21 +1404,48 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     /* label2: */
     *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2,
-                           args[addrlo_idx], GUEST_BASE, opc);
+    {
+        int32_t offset = GUEST_BASE;
+        int base = args[addrlo_idx];
+
+        if (TCG_TARGET_REG_BITS == 64) {
+            /* ??? We assume all operations have left us with register
+               contents that are zero extended.  So far this appears to
+               be true.  If we want to enforce this, we can either do
+               an explicit zero-extension here, or (if GUEST_BASE == 0)
+               use the ADDR32 prefix.  For now, do nothing.  */
+
+            if (offset != GUEST_BASE) {
+                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
+                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
+                base = TCG_REG_RDI, offset = 0;
+            }
+        }
+
+        tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
+    }
 #endif
 }
 
 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                               const TCGArg *args, const int *const_args)
 {
-    int c;
+    int c, rexw = 0;
+
+#if TCG_TARGET_REG_BITS == 64
+# define OP_32_64(x) \
+        case glue(glue(INDEX_op_, x), _i64): \
+            rexw = P_REXW; /* FALLTHRU */    \
+        case glue(glue(INDEX_op_, x), _i32)
+#else
+# define OP_32_64(x) \
+        case glue(glue(INDEX_op_, x), _i32)
+#endif
 
     switch(opc) {
     case INDEX_op_exit_tb:
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
-        tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
-        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
+        tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
         break;
     case INDEX_op_goto_tb:
         if (s->tb_jmp_offset) {
@@ -1107,8 +1470,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_jmp:
         if (const_args[0]) {
-            tcg_out8(s, OPC_JMP_long);
-            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
+            tcg_out_jmp(s, args[0]);
         } else {
             /* jmp *reg */
             tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
@@ -1120,38 +1482,43 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_movi_i32:
         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
         break;
-    case INDEX_op_ld8u_i32:
-        /* movzbl */
+    OP_32_64(ld8u):
+        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
         tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
         break;
-    case INDEX_op_ld8s_i32:
-        /* movsbl */
-        tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
+    OP_32_64(ld8s):
+        tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
         break;
-    case INDEX_op_ld16u_i32:
-        /* movzwl */
+    OP_32_64(ld16u):
+        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
         tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
         break;
-    case INDEX_op_ld16s_i32:
-        /* movswl */
-        tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
+    OP_32_64(ld16s):
+        tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
         break;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_ld32u_i64:
+#endif
     case INDEX_op_ld_i32:
         tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
         break;
-    case INDEX_op_st8_i32:
-        /* movb */
-        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
+
+    OP_32_64(st8):
+        tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
+                             args[0], args[1], args[2]);
         break;
-    case INDEX_op_st16_i32:
-        /* movw */
+    OP_32_64(st16):
         tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
                              args[0], args[1], args[2]);
         break;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_st32_i64:
+#endif
     case INDEX_op_st_i32:
         tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
         break;
-    case INDEX_op_add_i32:
+
+    OP_32_64(add):
         /* For 3-operand addition, use LEA.  */
         if (args[0] != args[1]) {
             TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
@@ -1161,147 +1528,117 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
             } else if (a0 == a2) {
                 /* Watch out for dest = src + dest, since we've removed
                    the matching constraint on the add.  */
-                tgen_arithr(s, ARITH_ADD, a0, a1);
+                tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
                 break;
             }
 
-            tcg_out_modrm_sib_offset(s, OPC_LEA, a0, a1, a2, 0, c3);
+            tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
             break;
         }
         c = ARITH_ADD;
         goto gen_arith;
-    case INDEX_op_sub_i32:
+    OP_32_64(sub):
         c = ARITH_SUB;
         goto gen_arith;
-    case INDEX_op_and_i32:
+    OP_32_64(and):
         c = ARITH_AND;
         goto gen_arith;
-    case INDEX_op_or_i32:
+    OP_32_64(or):
         c = ARITH_OR;
         goto gen_arith;
-    case INDEX_op_xor_i32:
+    OP_32_64(xor):
         c = ARITH_XOR;
         goto gen_arith;
     gen_arith:
         if (const_args[2]) {
-            tgen_arithi(s, c, args[0], args[2], 0);
+            tgen_arithi(s, c + rexw, args[0], args[2], 0);
         } else {
-            tgen_arithr(s, c, args[0], args[2]);
+            tgen_arithr(s, c + rexw, args[0], args[2]);
         }
         break;
-    case INDEX_op_mul_i32:
+
+    OP_32_64(mul):
         if (const_args[2]) {
             int32_t val;
             val = args[2];
             if (val == (int8_t)val) {
-                tcg_out_modrm(s, OPC_IMUL_GvEvIb, args[0], args[0]);
+                tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
                 tcg_out8(s, val);
             } else {
-                tcg_out_modrm(s, OPC_IMUL_GvEvIz, args[0], args[0]);
+                tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
                 tcg_out32(s, val);
             }
         } else {
-            tcg_out_modrm(s, OPC_IMUL_GvEv, args[0], args[2]);
+            tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
         }
         break;
-    case INDEX_op_mulu2_i32:
-        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
-        break;
-    case INDEX_op_div2_i32:
-        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_IDIV, args[4]);
+
+    OP_32_64(div2):
+        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
         break;
-    case INDEX_op_divu2_i32:
-        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_DIV, args[4]);
+    OP_32_64(divu2):
+        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
         break;
-    case INDEX_op_shl_i32:
+
+    OP_32_64(shl):
         c = SHIFT_SHL;
-    gen_shift32:
-        if (const_args[2]) {
-            tcg_out_shifti(s, c, args[0], args[2]);
-        } else {
-            tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
-        }
-        break;
-    case INDEX_op_shr_i32:
+        goto gen_shift;
+    OP_32_64(shr):
         c = SHIFT_SHR;
-        goto gen_shift32;
-    case INDEX_op_sar_i32:
+        goto gen_shift;
+    OP_32_64(sar):
         c = SHIFT_SAR;
-        goto gen_shift32;
-    case INDEX_op_rotl_i32:
+        goto gen_shift;
+    OP_32_64(rotl):
         c = SHIFT_ROL;
-        goto gen_shift32;
-    case INDEX_op_rotr_i32:
+        goto gen_shift;
+    OP_32_64(rotr):
         c = SHIFT_ROR;
-        goto gen_shift32;
-
-    case INDEX_op_add2_i32:
-        if (const_args[4]) {
-            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
-        } else {
-            tgen_arithr(s, ARITH_ADD, args[0], args[4]);
-        }
-        if (const_args[5]) {
-            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
+        goto gen_shift;
+    gen_shift:
+        if (const_args[2]) {
+            tcg_out_shifti(s, c + rexw, args[0], args[2]);
         } else {
-            tgen_arithr(s, ARITH_ADC, args[1], args[5]);
-        }
-        break;
-    case INDEX_op_sub2_i32:
-        if (const_args[4]) {
-            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
-        } else {
-            tgen_arithr(s, ARITH_SUB, args[0], args[4]);
-        }
-        if (const_args[5]) {
-            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
-        } else {
-            tgen_arithr(s, ARITH_SBB, args[1], args[5]);
+            tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
         }
         break;
+
     case INDEX_op_brcond_i32:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
-                       args[3], 0);
+        tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
+                         args[3], 0);
         break;
-    case INDEX_op_brcond2_i32:
-        tcg_out_brcond2(s, args, const_args, 0);
+    case INDEX_op_setcond_i32:
+        tcg_out_setcond32(s, args[3], args[0], args[1],
+                          args[2], const_args[2]);
         break;
 
-    case INDEX_op_bswap16_i32:
+    OP_32_64(bswap16):
         tcg_out_rolw_8(s, args[0]);
         break;
-    case INDEX_op_bswap32_i32:
+    OP_32_64(bswap32):
         tcg_out_bswap32(s, args[0]);
         break;
 
-    case INDEX_op_neg_i32:
-        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, args[0]);
+    OP_32_64(neg):
+        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
         break;
-
-    case INDEX_op_not_i32:
-        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NOT, args[0]);
+    OP_32_64(not):
+        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
         break;
 
-    case INDEX_op_ext8s_i32:
-        tcg_out_ext8s(s, args[0], args[1]);
+    OP_32_64(ext8s):
+        tcg_out_ext8s(s, args[0], args[1], rexw);
         break;
-    case INDEX_op_ext16s_i32:
-        tcg_out_ext16s(s, args[0], args[1]);
+    OP_32_64(ext16s):
+        tcg_out_ext16s(s, args[0], args[1], rexw);
         break;
-    case INDEX_op_ext8u_i32:
+    OP_32_64(ext8u):
         tcg_out_ext8u(s, args[0], args[1]);
         break;
-    case INDEX_op_ext16u_i32:
+    OP_32_64(ext16u):
         tcg_out_ext16u(s, args[0], args[1]);
         break;
 
-    case INDEX_op_setcond_i32:
-        tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
-        break;
-    case INDEX_op_setcond2_i32:
-        tcg_out_setcond2(s, args, const_args);
-        break;
-
     case INDEX_op_qemu_ld8u:
         tcg_out_qemu_ld(s, args, 0);
         break;
@@ -1314,6 +1651,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_qemu_ld16s:
         tcg_out_qemu_ld(s, args, 1 | 4);
         break;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_qemu_ld32u:
+#endif
     case INDEX_op_qemu_ld32:
         tcg_out_qemu_ld(s, args, 2);
         break;
@@ -1334,9 +1674,82 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_qemu_st(s, args, 3);
         break;
 
+#if TCG_TARGET_REG_BITS == 32
+    case INDEX_op_brcond2_i32:
+        tcg_out_brcond2(s, args, const_args, 0);
+        break;
+    case INDEX_op_setcond2_i32:
+        tcg_out_setcond2(s, args, const_args);
+        break;
+    case INDEX_op_mulu2_i32:
+        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
+        break;
+    case INDEX_op_add2_i32:
+        if (const_args[4]) {
+            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
+        } else {
+            tgen_arithr(s, ARITH_ADD, args[0], args[4]);
+        }
+        if (const_args[5]) {
+            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
+        } else {
+            tgen_arithr(s, ARITH_ADC, args[1], args[5]);
+        }
+        break;
+    case INDEX_op_sub2_i32:
+        if (const_args[4]) {
+            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
+        } else {
+            tgen_arithr(s, ARITH_SUB, args[0], args[4]);
+        }
+        if (const_args[5]) {
+            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
+        } else {
+            tgen_arithr(s, ARITH_SBB, args[1], args[5]);
+        }
+        break;
+#else /* TCG_TARGET_REG_BITS == 64 */
+    case INDEX_op_movi_i64:
+        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
+        break;
+    case INDEX_op_ld32s_i64:
+        tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_ld_i64:
+        tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_st_i64:
+        tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+        break;
+    case INDEX_op_qemu_ld32s:
+        tcg_out_qemu_ld(s, args, 2 | 4);
+        break;
+
+    case INDEX_op_brcond_i64:
+        tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
+                         args[3], 0);
+        break;
+    case INDEX_op_setcond_i64:
+        tcg_out_setcond64(s, args[3], args[0], args[1],
+                          args[2], const_args[2]);
+        break;
+
+    case INDEX_op_bswap64_i64:
+        tcg_out_bswap64(s, args[0]);
+        break;
+    case INDEX_op_ext32u_i64:
+        tcg_out_ext32u(s, args[0], args[1]);
+        break;
+    case INDEX_op_ext32s_i64:
+        tcg_out_ext32s(s, args[0], args[1]);
+        break;
+#endif
+
     default:
         tcg_abort();
     }
+
+#undef OP_32_64
 }
 
 static const TCGTargetOpDef x86_op_defs[] = {
@@ -1359,7 +1772,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_add_i32, { "r", "r", "ri" } },
     { INDEX_op_sub_i32, { "r", "0", "ri" } },
     { INDEX_op_mul_i32, { "r", "0", "ri" } },
-    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
     { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
     { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
     { INDEX_op_and_i32, { "r", "0", "ri" } },
@@ -1374,10 +1786,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
 
     { INDEX_op_brcond_i32, { "r", "ri" } },
 
-    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
-    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
-    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
-
     { INDEX_op_bswap16_i32, { "r", "0" } },
     { INDEX_op_bswap32_i32, { "r", "0" } },
 
@@ -1391,9 +1799,75 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_ext16u_i32, { "r", "r" } },
 
     { INDEX_op_setcond_i32, { "q", "r", "ri" } },
+
+#if TCG_TARGET_REG_BITS == 32
+    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
+    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
+    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
+    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
     { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
+#else
+    { INDEX_op_mov_i64, { "r", "r" } },
+    { INDEX_op_movi_i64, { "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_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", "0", "re" } },
+    { INDEX_op_mul_i64, { "r", "0", "re" } },
+    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
+    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
+    { INDEX_op_sub_i64, { "r", "0", "re" } },
+    { INDEX_op_and_i64, { "r", "0", "reZ" } },
+    { INDEX_op_or_i64, { "r", "0", "re" } },
+    { INDEX_op_xor_i64, { "r", "0", "re" } },
+
+    { INDEX_op_shl_i64, { "r", "0", "ci" } },
+    { INDEX_op_shr_i64, { "r", "0", "ci" } },
+    { INDEX_op_sar_i64, { "r", "0", "ci" } },
+    { INDEX_op_rotl_i64, { "r", "0", "ci" } },
+    { INDEX_op_rotr_i64, { "r", "0", "ci" } },
+
+    { INDEX_op_brcond_i64, { "r", "re" } },
+    { INDEX_op_setcond_i64, { "r", "r", "re" } },
+
+    { INDEX_op_bswap16_i64, { "r", "0" } },
+    { INDEX_op_bswap32_i64, { "r", "0" } },
+    { INDEX_op_bswap64_i64, { "r", "0" } },
+    { INDEX_op_neg_i64, { "r", "0" } },
+    { INDEX_op_not_i64, { "r", "0" } },
+
+    { INDEX_op_ext8s_i64, { "r", "r" } },
+    { INDEX_op_ext16s_i64, { "r", "r" } },
+    { INDEX_op_ext32s_i64, { "r", "r" } },
+    { INDEX_op_ext8u_i64, { "r", "r" } },
+    { INDEX_op_ext16u_i64, { "r", "r" } },
+    { INDEX_op_ext32u_i64, { "r", "r" } },
+#endif
 
-#if TARGET_LONG_BITS == 32
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_qemu_ld8u, { "r", "L" } },
+    { INDEX_op_qemu_ld8s, { "r", "L" } },
+    { INDEX_op_qemu_ld16u, { "r", "L" } },
+    { INDEX_op_qemu_ld16s, { "r", "L" } },
+    { INDEX_op_qemu_ld32, { "r", "L" } },
+    { INDEX_op_qemu_ld32u, { "r", "L" } },
+    { INDEX_op_qemu_ld32s, { "r", "L" } },
+    { INDEX_op_qemu_ld64, { "r", "L" } },
+
+    { INDEX_op_qemu_st8, { "L", "L" } },
+    { INDEX_op_qemu_st16, { "L", "L" } },
+    { INDEX_op_qemu_st32, { "L", "L" } },
+    { INDEX_op_qemu_st64, { "L", "L" } },
+#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
     { INDEX_op_qemu_ld8u, { "r", "L" } },
     { INDEX_op_qemu_ld8s, { "r", "L" } },
     { INDEX_op_qemu_ld16u, { "r", "L" } },
@@ -1422,11 +1896,19 @@ static const TCGTargetOpDef x86_op_defs[] = {
 };
 
 static int tcg_target_callee_save_regs[] = {
-    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
-                             need to save */
+#if TCG_TARGET_REG_BITS == 64
+    TCG_REG_RBP,
+    TCG_REG_RBX,
+    TCG_REG_R12,
+    TCG_REG_R13,
+    /* TCG_REG_R14, */ /* Currently used for the global env. */
+    TCG_REG_R15,
+#else
+    /* TCG_REG_EBP, */ /* Currently used for the global env. */
     TCG_REG_EBX,
     TCG_REG_ESI,
     TCG_REG_EDI,
+#endif
 };
 
 /* Generate global QEMU prologue and epilogue code */
@@ -1435,27 +1917,34 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     int i, frame_size, push_size, stack_addend;
 
     /* TB prologue */
-    /* save all callee saved registers */
-    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+
+    /* Save all callee saved registers.  */
+    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
         tcg_out_push(s, tcg_target_callee_save_regs[i]);
     }
-    /* reserve some stack space */
-    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
+
+    /* Reserve some stack space.  */
+    push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
+    push_size *= TCG_TARGET_REG_BITS / 8;
+
     frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
         ~(TCG_TARGET_STACK_ALIGN - 1);
     stack_addend = frame_size - push_size;
     tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
 
-    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
+    /* jmp *tb.  */
+    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
 
     /* TB epilogue */
     tb_ret_addr = s->code_ptr;
+
     tcg_out_addi(s, TCG_REG_ESP, stack_addend);
-    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
+
+    for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
         tcg_out_pop(s, tcg_target_callee_save_regs[i]);
     }
-    tcg_out_opc(s, OPC_RET);
+    tcg_out_opc(s, OPC_RET, 0, 0, 0);
 }
 
 static void tcg_target_init(TCGContext *s)
@@ -1466,12 +1955,25 @@ static void tcg_target_init(TCGContext *s)
         tcg_abort();
 #endif
 
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
+    if (TCG_TARGET_REG_BITS == 64) {
+        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
+        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
+    } else {
+        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
+    }
 
     tcg_regset_clear(tcg_target_call_clobber_regs);
     tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
     tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
     tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
+    if (TCG_TARGET_REG_BITS == 64) {
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
+        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
+    }
 
     tcg_regset_clear(s->reserved_regs);
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index ca1d730..bfafbfc 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -23,10 +23,18 @@
  */
 #define TCG_TARGET_I386 1
 
-#define TCG_TARGET_REG_BITS 32
+#if defined(__x86_64__)
+# define TCG_TARGET_REG_BITS 64
+#else
+# define TCG_TARGET_REG_BITS 32
+#endif
 //#define TCG_TARGET_WORDS_BIGENDIAN
 
-#define TCG_TARGET_NB_REGS 8
+#if TCG_TARGET_REG_BITS == 64
+# define TCG_TARGET_NB_REGS 16
+#else
+# define TCG_TARGET_NB_REGS 8
+#endif
 
 enum {
     TCG_REG_EAX = 0,
@@ -37,8 +45,30 @@ enum {
     TCG_REG_EBP,
     TCG_REG_ESI,
     TCG_REG_EDI,
+
+    /* 64-bit registers; always define the symbols to avoid
+       too much if-deffing.  */
+    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_RAX = TCG_REG_EAX,
+    TCG_REG_RCX = TCG_REG_ECX,
+    TCG_REG_RDX = TCG_REG_EDX,
+    TCG_REG_RBX = TCG_REG_EBX,
+    TCG_REG_RSP = TCG_REG_ESP,
+    TCG_REG_RBP = TCG_REG_EBP,
+    TCG_REG_RSI = TCG_REG_ESI,
+    TCG_REG_RDI = TCG_REG_EDI,
 };
 
+#define TCG_CT_CONST_S32 0x100
+#define TCG_CT_CONST_U32 0x200
+
 /* used for function call generation */
 #define TCG_REG_CALL_STACK TCG_REG_ESP 
 #define TCG_TARGET_STACK_ALIGN 16
@@ -61,10 +91,35 @@ enum {
 // #define TCG_TARGET_HAS_nand_i32
 // #define TCG_TARGET_HAS_nor_i32
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_div2_i64
+#define TCG_TARGET_HAS_rot_i64
+#define TCG_TARGET_HAS_ext8s_i64
+#define TCG_TARGET_HAS_ext16s_i64
+#define TCG_TARGET_HAS_ext32s_i64
+#define TCG_TARGET_HAS_ext8u_i64
+#define TCG_TARGET_HAS_ext16u_i64
+#define TCG_TARGET_HAS_ext32u_i64
+#define TCG_TARGET_HAS_bswap16_i64
+#define TCG_TARGET_HAS_bswap32_i64
+#define TCG_TARGET_HAS_bswap64_i64
+#define TCG_TARGET_HAS_neg_i64
+#define TCG_TARGET_HAS_not_i64
+// #define TCG_TARGET_HAS_andc_i64
+// #define TCG_TARGET_HAS_orc_i64
+// #define TCG_TARGET_HAS_eqv_i64
+// #define TCG_TARGET_HAS_nand_i64
+// #define TCG_TARGET_HAS_nor_i64
+#endif
+
 #define TCG_TARGET_HAS_GUEST_BASE
 
 /* Note: must be synced with dyngen-exec.h */
-#define TCG_AREG0 TCG_REG_EBP
+#if TCG_TARGET_REG_BITS == 64
+# define TCG_AREG0 TCG_REG_R14
+#else
+# define TCG_AREG0 TCG_REG_EBP
+#endif
 
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
deleted file mode 100644
index 490666e..0000000
--- a/tcg/x86_64/tcg-target.c
+++ /dev/null
@@ -1,1445 +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 NDEBUG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
-    "%rax",
-    "%rcx",
-    "%rdx",
-    "%rbx",
-    "%rsp",
-    "%rbp",
-    "%rsi",
-    "%rdi",
-    "%r8",
-    "%r9",
-    "%r10",
-    "%r11",
-    "%r12",
-    "%r13",
-    "%r14",
-    "%r15",
-};
-#endif
-
-static const int tcg_target_reg_alloc_order[] = {
-    TCG_REG_RBP,
-    TCG_REG_RBX,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R9,
-    TCG_REG_R8,
-    TCG_REG_RCX,
-    TCG_REG_RDX,
-    TCG_REG_RSI,
-    TCG_REG_RDI,
-    TCG_REG_RAX,
-};
-
-static const int tcg_target_call_iarg_regs[6] = {
-    TCG_REG_RDI,
-    TCG_REG_RSI,
-    TCG_REG_RDX,
-    TCG_REG_RCX,
-    TCG_REG_R8,
-    TCG_REG_R9,
-};
-
-static const int tcg_target_call_oarg_regs[2] = {
-    TCG_REG_RAX, 
-    TCG_REG_RDX 
-};
-
-static uint8_t *tb_ret_addr;
-
-static void patch_reloc(uint8_t *code_ptr, int type, 
-                        tcg_target_long value, tcg_target_long addend)
-{
-    value += addend;
-    switch(type) {
-    case R_X86_64_32:
-        if (value != (uint32_t)value)
-            tcg_abort();
-        *(uint32_t *)code_ptr = value;
-        break;
-    case R_X86_64_32S:
-        if (value != (int32_t)value)
-            tcg_abort();
-        *(uint32_t *)code_ptr = value;
-        break;
-    case R_386_PC32:
-        value -= (long)code_ptr;
-        if (value != (int32_t)value)
-            tcg_abort();
-        *(uint32_t *)code_ptr = value;
-        break;
-    default:
-        tcg_abort();
-    }
-}
-
-/* maximum number of register used for input function arguments */
-static inline int tcg_target_get_call_iarg_regs_count(int flags)
-{
-    return 6;
-}
-
-/* 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':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RAX);
-        break;
-    case 'b':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RBX);
-        break;
-    case 'c':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RCX);
-        break;
-    case 'd':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RDX);
-        break;
-    case 'S':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RSI);
-        break;
-    case 'D':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set_reg(ct->u.regs, TCG_REG_RDI);
-        break;
-    case 'q':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xf);
-        break;
-    case 'r':
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffff);
-        break;
-    case 'L': /* qemu_ld/st constraint */
-        ct->ct |= TCG_CT_REG;
-        tcg_regset_set32(ct->u.regs, 0, 0xffff);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
-        tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
-        break;
-    case 'e':
-        ct->ct |= TCG_CT_CONST_S32;
-        break;
-    case 'Z':
-        ct->ct |= TCG_CT_CONST_U32;
-        break;
-    default:
-        return -1;
-    }
-    ct_str++;
-    *pct_str = ct_str;
-    return 0;
-}
-
-/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
-                                         const TCGArgConstraint *arg_ct)
-{
-    int ct;
-    ct = arg_ct->ct;
-    if (ct & TCG_CT_CONST)
-        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
-        return 0;
-}
-
-#define ARITH_ADD 0
-#define ARITH_OR  1
-#define ARITH_ADC 2
-#define ARITH_SBB 3
-#define ARITH_AND 4
-#define ARITH_SUB 5
-#define ARITH_XOR 6
-#define ARITH_CMP 7
-
-#define SHIFT_ROL 0
-#define SHIFT_ROR 1
-#define SHIFT_SHL 4
-#define SHIFT_SHR 5
-#define SHIFT_SAR 7
-
-#define JCC_JMP (-1)
-#define JCC_JO  0x0
-#define JCC_JNO 0x1
-#define JCC_JB  0x2
-#define JCC_JAE 0x3
-#define JCC_JE  0x4
-#define JCC_JNE 0x5
-#define JCC_JBE 0x6
-#define JCC_JA  0x7
-#define JCC_JS  0x8
-#define JCC_JNS 0x9
-#define JCC_JP  0xa
-#define JCC_JNP 0xb
-#define JCC_JL  0xc
-#define JCC_JGE 0xd
-#define JCC_JLE 0xe
-#define JCC_JG  0xf
-
-#define P_EXT		0x100		/* 0x0f opcode prefix */
-#define P_REXW		0x200		/* set rex.w = 1 */
-#define P_REXB_R	0x400		/* REG field as byte register */
-#define P_REXB_RM	0x800		/* R/M field as byte register */
-                                  
-static const uint8_t tcg_cond_to_jcc[10] = {
-    [TCG_COND_EQ] = JCC_JE,
-    [TCG_COND_NE] = JCC_JNE,
-    [TCG_COND_LT] = JCC_JL,
-    [TCG_COND_GE] = JCC_JGE,
-    [TCG_COND_LE] = JCC_JLE,
-    [TCG_COND_GT] = JCC_JG,
-    [TCG_COND_LTU] = JCC_JB,
-    [TCG_COND_GEU] = JCC_JAE,
-    [TCG_COND_LEU] = JCC_JBE,
-    [TCG_COND_GTU] = JCC_JA,
-};
-
-static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
-{
-    int rex = 0;
-
-    rex |= (opc & P_REXW) >> 6;		/* REX.W */
-    rex |= (r & 8) >> 1;		/* REX.R */
-    rex |= (x & 8) >> 2;		/* REX.X */
-    rex |= (rm & 8) >> 3;		/* REX.B */
-
-    /* P_REXB_{R,RM} indicates that the given register is the low byte.
-       For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
-       as otherwise the encoding indicates %[abcd]h.  Note that the values
-       that are ORed in merely indicate that the REX byte must be present;
-       those bits get discarded in output.  */
-    rex |= opc & (r >= 4 ? P_REXB_R : 0);
-    rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
-
-    if (rex) {
-        tcg_out8(s, (uint8_t)(rex | 0x40));
-    }
-    if (opc & P_EXT) {
-        tcg_out8(s, 0x0f);
-    }
-    tcg_out8(s, opc & 0xff);
-}
-
-static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
-{
-    tcg_out_opc(s, opc, r, rm, 0);
-    tcg_out8(s, 0xc0 | ((r & 7) << 3) | (rm & 7));
-}
-
-/* rm < 0 means no register index plus (-rm - 1 immediate bytes) */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, 
-                                        tcg_target_long offset)
-{
-    if (rm < 0) {
-        tcg_target_long val;
-        tcg_out_opc(s, opc, r, 0, 0);
-        val = offset - ((tcg_target_long)s->code_ptr + 5 + (-rm - 1));
-        if (val == (int32_t)val) {
-            /* eip relative */
-            tcg_out8(s, 0x05 | ((r & 7) << 3));
-            tcg_out32(s, val);
-        } else if (offset == (int32_t)offset) {
-            tcg_out8(s, 0x04 | ((r & 7) << 3));
-            tcg_out8(s, 0x25); /* sib */
-            tcg_out32(s, offset);
-        } else {
-            tcg_abort();
-        }
-    } else if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
-        tcg_out_opc(s, opc, r, rm, 0);
-        if ((rm & 7) == TCG_REG_RSP) {
-            tcg_out8(s, 0x04 | ((r & 7) << 3));
-            tcg_out8(s, 0x24);
-        } else {
-            tcg_out8(s, 0x00 | ((r & 7) << 3) | (rm & 7));
-        }
-    } else if ((int8_t)offset == offset) {
-        tcg_out_opc(s, opc, r, rm, 0);
-        if ((rm & 7) == TCG_REG_RSP) {
-            tcg_out8(s, 0x44 | ((r & 7) << 3));
-            tcg_out8(s, 0x24);
-        } else {
-            tcg_out8(s, 0x40 | ((r & 7) << 3) | (rm & 7));
-        }
-        tcg_out8(s, offset);
-    } else {
-        tcg_out_opc(s, opc, r, rm, 0);
-        if ((rm & 7) == TCG_REG_RSP) {
-            tcg_out8(s, 0x84 | ((r & 7) << 3));
-            tcg_out8(s, 0x24);
-        } else {
-            tcg_out8(s, 0x80 | ((r & 7) << 3) | (rm & 7));
-        }
-        tcg_out32(s, offset);
-    }
-}
-
-#if defined(CONFIG_SOFTMMU)
-/* XXX: incomplete. index must be different from ESP */
-static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm, 
-                                  int index, int shift,
-                                  tcg_target_long offset)
-{
-    int mod;
-    if (rm == -1)
-        tcg_abort();
-    if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
-        mod = 0;
-    } else if (offset == (int8_t)offset) {
-        mod = 0x40;
-    } else if (offset == (int32_t)offset) {
-        mod = 0x80;
-    } else {
-        tcg_abort();
-    }
-    if (index == -1) {
-        tcg_out_opc(s, opc, r, rm, 0);
-        if ((rm & 7) == TCG_REG_RSP) {
-            tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
-            tcg_out8(s, 0x04 | (rm & 7));
-        } else {
-            tcg_out8(s, mod | ((r & 7) << 3) | (rm & 7));
-        }
-    } else {
-        tcg_out_opc(s, opc, r, rm, index);
-        tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
-        tcg_out8(s, (shift << 6) | ((index & 7) << 3) | (rm & 7));
-    }
-    if (mod == 0x40) {
-        tcg_out8(s, offset);
-    } else if (mod == 0x80) {
-        tcg_out32(s, offset);
-    }
-}
-#endif
-
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
-{
-    int rexw = (type == TCG_TYPE_I64 ? P_REXW : 0);
-    tcg_out_modrm(s, 0x8b | rexw, ret, arg);
-}
-
-static inline void tcg_out_movi(TCGContext *s, TCGType type, 
-                                int ret, tcg_target_long arg)
-{
-    if (arg == 0) {
-        tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret); /* xor r0,r0 */
-    } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
-        tcg_out_opc(s, 0xb8 + (ret & 7), 0, ret, 0);
-        tcg_out32(s, arg);
-    } else if (arg == (int32_t)arg) {
-        tcg_out_modrm(s, 0xc7 | P_REXW, 0, ret);
-        tcg_out32(s, arg);
-    } else {
-        tcg_out_opc(s, (0xb8 + (ret & 7)) | P_REXW, 0, ret, 0);
-        tcg_out32(s, arg);
-        tcg_out32(s, arg >> 32);
-    }
-}
-
-static void tcg_out_goto(TCGContext *s, int call, uint8_t *target)
-{
-    int32_t disp;
-
-    disp = target - s->code_ptr - 5;
-    if (disp == (target - s->code_ptr - 5)) {
-        tcg_out8(s, call ? 0xe8 : 0xe9);
-        tcg_out32(s, disp);
-    } else {
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (tcg_target_long) target);
-        tcg_out_modrm(s, 0xff, call ? 2 : 4, TCG_REG_R10);
-    }
-}
-
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
-                              int arg1, tcg_target_long arg2)
-{
-    if (type == TCG_TYPE_I32)
-        tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */
-    else
-        tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */
-}
-
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
-                              int arg1, tcg_target_long arg2)
-{
-    if (type == TCG_TYPE_I32)
-        tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */
-    else
-        tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */
-}
-
-static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val)
-{
-    if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
-        /* inc */
-        tcg_out_modrm(s, 0xff, 0, r0);
-    } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
-        /* dec */
-        tcg_out_modrm(s, 0xff, 1, r0);
-    } else if (val == (int8_t)val) {
-        tcg_out_modrm(s, 0x83, c, r0);
-        tcg_out8(s, val);
-    } else if (c == ARITH_AND && val == 0xffu) {
-        /* movzbl */
-        tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, r0, r0);
-    } else if (c == ARITH_AND && val == 0xffffu) {
-        /* movzwl */
-        tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
-    } else {
-        tcg_out_modrm(s, 0x81, c, r0);
-        tcg_out32(s, val);
-    }
-}
-
-static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val)
-{
-    if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
-        /* inc */
-        tcg_out_modrm(s, 0xff | P_REXW, 0, r0);
-    } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
-        /* dec */
-        tcg_out_modrm(s, 0xff | P_REXW, 1, r0);
-    } else if (c == ARITH_AND && val == 0xffffffffu) {
-        /* 32-bit mov zero extends */
-        tcg_out_modrm(s, 0x8b, r0, r0);
-    } else if (c == ARITH_AND && val == (uint32_t)val) {
-        /* AND with no high bits set can use a 32-bit operation.  */
-        tgen_arithi32(s, c, r0, (uint32_t)val);
-    } else if (val == (int8_t)val) {
-        tcg_out_modrm(s, 0x83 | P_REXW, c, r0);
-        tcg_out8(s, val);
-    } else if (val == (int32_t)val) {
-        tcg_out_modrm(s, 0x81 | P_REXW, c, r0);
-        tcg_out32(s, val);
-    } else {
-        tcg_abort();
-    }
-}
-
-static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
-{
-    if (val != 0)
-        tgen_arithi64(s, ARITH_ADD, reg, val);
-}
-
-static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
-{
-    int32_t val, val1;
-    TCGLabel *l = &s->labels[label_index];
-    
-    if (l->has_value) {
-        val = l->u.value - (tcg_target_long)s->code_ptr;
-        val1 = val - 2;
-        if ((int8_t)val1 == val1) {
-            if (opc == -1)
-                tcg_out8(s, 0xeb);
-            else
-                tcg_out8(s, 0x70 + opc);
-            tcg_out8(s, val1);
-        } else {
-            if (opc == -1) {
-                tcg_out8(s, 0xe9);
-                tcg_out32(s, val - 5);
-            } else {
-                tcg_out8(s, 0x0f);
-                tcg_out8(s, 0x80 + opc);
-                tcg_out32(s, val - 6);
-            }
-        }
-    } else {
-        if (opc == -1) {
-            tcg_out8(s, 0xe9);
-        } else {
-            tcg_out8(s, 0x0f);
-            tcg_out8(s, 0x80 + opc);
-        }
-        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
-        s->code_ptr += 4;
-    }
-}
-
-static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
-                        int const_arg2, int rexw)
-{
-    if (const_arg2) {
-        if (arg2 == 0) {
-            /* test r, r */
-            tcg_out_modrm(s, 0x85 | rexw, arg1, arg1);
-        } else {
-            if (rexw) {
-                tgen_arithi64(s, ARITH_CMP, arg1, arg2);
-            } else {
-                tgen_arithi32(s, ARITH_CMP, arg1, arg2);
-            }
-        }
-    } else {
-        tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1);
-    }
-}
-
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
-                           TCGArg arg1, TCGArg arg2, int const_arg2,
-                           int label_index, int rexw)
-{
-    tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
-    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
-}
-
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
-                            TCGArg arg1, TCGArg arg2, int const_arg2, int rexw)
-{
-    tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
-    /* setcc */
-    tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT | P_REXB_RM, 0, dest);
-    tgen_arithi32(s, ARITH_AND, dest, 0xff);
-}
-
-#if defined(CONFIG_SOFTMMU)
-
-#include "../../softmmu_defs.h"
-
-static void *qemu_ld_helpers[4] = {
-    __ldb_mmu,
-    __ldw_mmu,
-    __ldl_mmu,
-    __ldq_mmu,
-};
-
-static void *qemu_st_helpers[4] = {
-    __stb_mmu,
-    __stw_mmu,
-    __stl_mmu,
-    __stq_mmu,
-};
-#endif
-
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
-                            int opc)
-{
-    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
-    int32_t offset;
-#if defined(CONFIG_SOFTMMU)
-    uint8_t *label1_ptr, *label2_ptr;
-#endif
-
-    data_reg = *args++;
-    addr_reg = *args++;
-    mem_index = *args;
-    s_bits = opc & 3;
-
-    r0 = TCG_REG_RDI;
-    r1 = TCG_REG_RSI;
-
-#if TARGET_LONG_BITS == 32
-    rexw = 0;
-#else
-    rexw = P_REXW;
-#endif
-#if defined(CONFIG_SOFTMMU)
-    tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
-    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
- 
-    tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
-    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
-    
-    tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
-    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-    
-    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
-    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-
-    /* lea offset(r1, env), r1 */
-    tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
-                          offsetof(CPUState, tlb_table[mem_index][0].addr_read));
-
-    /* cmp 0(r1), r0 */
-    tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-    
-    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-    
-    /* je label1 */
-    tcg_out8(s, 0x70 + JCC_JE);
-    label1_ptr = s->code_ptr;
-    s->code_ptr++;
-
-    /* XXX: move that code at the end of the TB */
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index);
-    tcg_out_goto(s, 1, qemu_ld_helpers[s_bits]);
-
-    switch(opc) {
-    case 0 | 4:
-        /* movsbq */
-        tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
-        break;
-    case 1 | 4:
-        /* movswq */
-        tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
-        break;
-    case 2 | 4:
-        /* movslq */
-        tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
-        break;
-    case 0:
-        /* movzbq */
-        tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
-        break;
-    case 1:
-        /* movzwq */
-        tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
-        break;
-    case 2:
-    default:
-        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_RAX);
-        break;
-    case 3:
-        tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
-        break;
-    }
-
-    /* jmp label2 */
-    tcg_out8(s, 0xeb);
-    label2_ptr = s->code_ptr;
-    s->code_ptr++;
-    
-    /* label1: */
-    *label1_ptr = s->code_ptr - label1_ptr - 1;
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
-                         offsetof(CPUTLBEntry, addr_read));
-    offset = 0;
-#else
-    if (GUEST_BASE == (int32_t)GUEST_BASE) {
-        r0 = addr_reg;
-        offset = GUEST_BASE;
-    } else {
-        offset = 0;
-        /* movq $GUEST_BASE, r0 */
-        tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
-        tcg_out32(s, GUEST_BASE);
-        tcg_out32(s, GUEST_BASE >> 32);
-        /* addq addr_reg, r0 */
-        tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
-    }
-#endif    
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
-    switch(opc) {
-    case 0:
-        /* movzbl */
-        tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset);
-        break;
-    case 0 | 4:
-        /* movsbX */
-        tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset);
-        break;
-    case 1:
-        /* movzwl */
-        tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
-        if (bswap) {
-            /* rolw $8, data_reg */
-            tcg_out8(s, 0x66); 
-            tcg_out_modrm(s, 0xc1, 0, data_reg);
-            tcg_out8(s, 8);
-        }
-        break;
-    case 1 | 4:
-        if (bswap) {
-            /* movzwl */
-            tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
-            /* rolw $8, data_reg */
-            tcg_out8(s, 0x66); 
-            tcg_out_modrm(s, 0xc1, 0, data_reg);
-            tcg_out8(s, 8);
-
-            /* movswX data_reg, data_reg */
-            tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
-        } else {
-            /* movswX */
-            tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset);
-        }
-        break;
-    case 2:
-        /* movl (r0), data_reg */
-        tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
-        if (bswap) {
-            /* bswap */
-            tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
-        }
-        break;
-    case 2 | 4:
-        if (bswap) {
-            /* movl (r0), data_reg */
-            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
-            /* bswap */
-            tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
-            /* movslq */
-            tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
-        } else {
-            /* movslq */
-            tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset);
-        }
-        break;
-    case 3:
-        /* movq (r0), data_reg */
-        tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset);
-        if (bswap) {
-            /* bswap */
-            tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
-        }
-        break;
-    default:
-        tcg_abort();
-    }
-
-#if defined(CONFIG_SOFTMMU)
-    /* label2: */
-    *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
-}
-
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
-                            int opc)
-{
-    int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
-    int32_t offset;
-#if defined(CONFIG_SOFTMMU)
-    uint8_t *label1_ptr, *label2_ptr;
-#endif
-
-    data_reg = *args++;
-    addr_reg = *args++;
-    mem_index = *args;
-
-    s_bits = opc;
-
-    r0 = TCG_REG_RDI;
-    r1 = TCG_REG_RSI;
-
-#if TARGET_LONG_BITS == 32
-    rexw = 0;
-#else
-    rexw = P_REXW;
-#endif
-#if defined(CONFIG_SOFTMMU)
-    tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
-    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
- 
-    tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
-    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
-    
-    tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
-    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-    
-    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
-    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-
-    /* lea offset(r1, env), r1 */
-    tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
-                          offsetof(CPUState, tlb_table[mem_index][0].addr_write));
-
-    /* cmp 0(r1), r0 */
-    tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-
-    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-
-    /* je label1 */
-    tcg_out8(s, 0x70 + JCC_JE);
-    label1_ptr = s->code_ptr;
-    s->code_ptr++;
-
-    /* XXX: move that code at the end of the TB */
-    switch(opc) {
-    case 0:
-        /* movzbl */
-        tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, TCG_REG_RSI, data_reg);
-        break;
-    case 1:
-        /* movzwl */
-        tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
-        break;
-    case 2:
-        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RSI, data_reg);
-        break;
-    default:
-    case 3:
-        tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_RSI, data_reg);
-        break;
-    }
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
-    tcg_out_goto(s, 1, qemu_st_helpers[s_bits]);
-
-    /* jmp label2 */
-    tcg_out8(s, 0xeb);
-    label2_ptr = s->code_ptr;
-    s->code_ptr++;
-    
-    /* label1: */
-    *label1_ptr = s->code_ptr - label1_ptr - 1;
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 
-                         offsetof(CPUTLBEntry, addr_write));
-    offset = 0;
-#else
-    if (GUEST_BASE == (int32_t)GUEST_BASE) {
-        r0 = addr_reg;
-        offset = GUEST_BASE;
-    } else {
-        offset = 0;
-        /* movq $GUEST_BASE, r0 */
-        tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
-        tcg_out32(s, GUEST_BASE);
-        tcg_out32(s, GUEST_BASE >> 32);
-        /* addq addr_reg, r0 */
-        tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
-    }
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
-    switch(opc) {
-    case 0:
-        /* movb */
-        tcg_out_modrm_offset(s, 0x88 | P_REXB_R, data_reg, r0, offset);
-        break;
-    case 1:
-        if (bswap) {
-            tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
-            tcg_out8(s, 0x66); /* rolw $8, %ecx */
-            tcg_out_modrm(s, 0xc1, 0, r1);
-            tcg_out8(s, 8);
-            data_reg = r1;
-        }
-        /* movw */
-        tcg_out8(s, 0x66);
-        tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
-        break;
-    case 2:
-        if (bswap) {
-            tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
-            /* bswap data_reg */
-            tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
-            data_reg = r1;
-        }
-        /* movl */
-        tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
-        break;
-    case 3:
-        if (bswap) {
-            tcg_out_mov(s, TCG_TYPE_I64, r1, data_reg);
-            /* bswap data_reg */
-            tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
-            data_reg = r1;
-        }
-        /* movq */
-        tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset);
-        break;
-    default:
-        tcg_abort();
-    }
-
-#if defined(CONFIG_SOFTMMU)
-    /* label2: */
-    *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
-}
-
-static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
-                              const int *const_args)
-{
-    int c;
-    
-    switch(opc) {
-    case INDEX_op_exit_tb:
-        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
-        tcg_out_goto(s, 0, tb_ret_addr);
-        break;
-    case INDEX_op_goto_tb:
-        if (s->tb_jmp_offset) {
-            /* direct jump method */
-            tcg_out8(s, 0xe9); /* jmp im */
-            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
-            tcg_out32(s, 0);
-        } else {
-            /* indirect jump method */
-            /* jmp Ev */
-            tcg_out_modrm_offset(s, 0xff, 4, -1, 
-                                 (tcg_target_long)(s->tb_next + 
-                                                   args[0]));
-        }
-        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
-        break;
-    case INDEX_op_call:
-        if (const_args[0]) {
-            tcg_out_goto(s, 1, (void *) args[0]);
-        } else {
-            tcg_out_modrm(s, 0xff, 2, args[0]);
-        }
-        break;
-    case INDEX_op_jmp:
-        if (const_args[0]) {
-            tcg_out_goto(s, 0, (void *) args[0]);
-        } else {
-            tcg_out_modrm(s, 0xff, 4, args[0]);
-        }
-        break;
-    case INDEX_op_br:
-        tcg_out_jxx(s, JCC_JMP, args[0]);
-        break;
-    case INDEX_op_movi_i32:
-        tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
-        break;
-    case INDEX_op_movi_i64:
-        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
-        break;
-    case INDEX_op_ld8u_i32:
-    case INDEX_op_ld8u_i64:
-        /* movzbl */
-        tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld8s_i32:
-        /* movsbl */
-        tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld8s_i64:
-        /* movsbq */
-        tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld16u_i32:
-    case INDEX_op_ld16u_i64:
-        /* movzwl */
-        tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld16s_i32:
-        /* movswl */
-        tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld16s_i64:
-        /* movswq */
-        tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld_i32:
-    case INDEX_op_ld32u_i64:
-        /* movl */
-        tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld32s_i64:
-        /* movslq */
-        tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_ld_i64:
-        /* movq */
-        tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);
-        break;
-        
-    case INDEX_op_st8_i32:
-    case INDEX_op_st8_i64:
-        /* movb */
-        tcg_out_modrm_offset(s, 0x88 | P_REXB_R, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st16_i32:
-    case INDEX_op_st16_i64:
-        /* movw */
-        tcg_out8(s, 0x66);
-        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st_i32:
-    case INDEX_op_st32_i64:
-        /* movl */
-        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
-        break;
-    case INDEX_op_st_i64:
-        /* movq */
-        tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);
-        break;
-
-    case INDEX_op_sub_i32:
-        c = ARITH_SUB;
-        goto gen_arith32;
-    case INDEX_op_and_i32:
-        c = ARITH_AND;
-        goto gen_arith32;
-    case INDEX_op_or_i32:
-        c = ARITH_OR;
-        goto gen_arith32;
-    case INDEX_op_xor_i32:
-        c = ARITH_XOR;
-        goto gen_arith32;
-    case INDEX_op_add_i32:
-        c = ARITH_ADD;
-    gen_arith32:
-        if (const_args[2]) {
-            tgen_arithi32(s, c, args[0], args[2]);
-        } else {
-            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
-        }
-        break;
-
-    case INDEX_op_sub_i64:
-        c = ARITH_SUB;
-        goto gen_arith64;
-    case INDEX_op_and_i64:
-        c = ARITH_AND;
-        goto gen_arith64;
-    case INDEX_op_or_i64:
-        c = ARITH_OR;
-        goto gen_arith64;
-    case INDEX_op_xor_i64:
-        c = ARITH_XOR;
-        goto gen_arith64;
-    case INDEX_op_add_i64:
-        c = ARITH_ADD;
-    gen_arith64:
-        if (const_args[2]) {
-            tgen_arithi64(s, c, args[0], args[2]);
-        } else {
-            tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]);
-        }
-        break;
-
-    case INDEX_op_mul_i32:
-        if (const_args[2]) {
-            int32_t val;
-            val = args[2];
-            if (val == (int8_t)val) {
-                tcg_out_modrm(s, 0x6b, args[0], args[0]);
-                tcg_out8(s, val);
-            } else {
-                tcg_out_modrm(s, 0x69, args[0], args[0]);
-                tcg_out32(s, val);
-            }
-        } else {
-            tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
-        }
-        break;
-    case INDEX_op_mul_i64:
-        if (const_args[2]) {
-            int32_t val;
-            val = args[2];
-            if (val == (int8_t)val) {
-                tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);
-                tcg_out8(s, val);
-            } else {
-                tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);
-                tcg_out32(s, val);
-            }
-        } else {
-            tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);
-        }
-        break;
-    case INDEX_op_div2_i32:
-        tcg_out_modrm(s, 0xf7, 7, args[4]);
-        break;
-    case INDEX_op_divu2_i32:
-        tcg_out_modrm(s, 0xf7, 6, args[4]);
-        break;
-    case INDEX_op_div2_i64:
-        tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);
-        break;
-    case INDEX_op_divu2_i64:
-        tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]);
-        break;
-
-    case INDEX_op_shl_i32:
-        c = SHIFT_SHL;
-    gen_shift32:
-        if (const_args[2]) {
-            if (args[2] == 1) {
-                tcg_out_modrm(s, 0xd1, c, args[0]);
-            } else {
-                tcg_out_modrm(s, 0xc1, c, args[0]);
-                tcg_out8(s, args[2]);
-            }
-        } else {
-            tcg_out_modrm(s, 0xd3, c, args[0]);
-        }
-        break;
-    case INDEX_op_shr_i32:
-        c = SHIFT_SHR;
-        goto gen_shift32;
-    case INDEX_op_sar_i32:
-        c = SHIFT_SAR;
-        goto gen_shift32;
-    case INDEX_op_rotl_i32:
-        c = SHIFT_ROL;
-        goto gen_shift32;
-    case INDEX_op_rotr_i32:
-        c = SHIFT_ROR;
-        goto gen_shift32;
-
-    case INDEX_op_shl_i64:
-        c = SHIFT_SHL;
-    gen_shift64:
-        if (const_args[2]) {
-            if (args[2] == 1) {
-                tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);
-            } else {
-                tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);
-                tcg_out8(s, args[2]);
-            }
-        } else {
-            tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);
-        }
-        break;
-    case INDEX_op_shr_i64:
-        c = SHIFT_SHR;
-        goto gen_shift64;
-    case INDEX_op_sar_i64:
-        c = SHIFT_SAR;
-        goto gen_shift64;
-    case INDEX_op_rotl_i64:
-        c = SHIFT_ROL;
-        goto gen_shift64;
-    case INDEX_op_rotr_i64:
-        c = SHIFT_ROR;
-        goto gen_shift64;
-
-    case INDEX_op_brcond_i32:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
-                       args[3], 0);
-        break;
-    case INDEX_op_brcond_i64:
-        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], 
-                       args[3], P_REXW);
-        break;
-
-    case INDEX_op_bswap16_i32:
-    case INDEX_op_bswap16_i64:
-        tcg_out8(s, 0x66);
-        tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
-        tcg_out8(s, 8);
-        break;
-    case INDEX_op_bswap32_i32:
-    case INDEX_op_bswap32_i64:
-        tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
-        break;
-    case INDEX_op_bswap64_i64:
-        tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
-        break;
-
-    case INDEX_op_neg_i32:
-        tcg_out_modrm(s, 0xf7, 3, args[0]);
-        break;
-    case INDEX_op_neg_i64:
-        tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
-        break;
-
-    case INDEX_op_not_i32:
-        tcg_out_modrm(s, 0xf7, 2, args[0]);
-        break;
-    case INDEX_op_not_i64:
-        tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
-        break;
-
-    case INDEX_op_ext8s_i32:
-        tcg_out_modrm(s, 0xbe | P_EXT | P_REXB_RM, args[0], args[1]);
-        break;
-    case INDEX_op_ext16s_i32:
-        tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
-        break;
-    case INDEX_op_ext8s_i64:
-        tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]);
-        break;
-    case INDEX_op_ext16s_i64:
-        tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]);
-        break;
-    case INDEX_op_ext32s_i64:
-        tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]);
-        break;
-    case INDEX_op_ext8u_i32:
-    case INDEX_op_ext8u_i64:
-        tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, args[0], args[1]);
-        break;
-    case INDEX_op_ext16u_i32:
-    case INDEX_op_ext16u_i64:
-        tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
-        break;
-    case INDEX_op_ext32u_i64:
-        tcg_out_modrm(s, 0x8b, args[0], args[1]);
-        break;
-
-    case INDEX_op_setcond_i32:
-        tcg_out_setcond(s, args[3], args[0], args[1], args[2],
-                        const_args[2], 0);
-        break;
-    case INDEX_op_setcond_i64:
-        tcg_out_setcond(s, args[3], args[0], args[1], args[2],
-                        const_args[2], P_REXW);
-        break;
-
-    case INDEX_op_qemu_ld8u:
-        tcg_out_qemu_ld(s, args, 0);
-        break;
-    case INDEX_op_qemu_ld8s:
-        tcg_out_qemu_ld(s, args, 0 | 4);
-        break;
-    case INDEX_op_qemu_ld16u:
-        tcg_out_qemu_ld(s, args, 1);
-        break;
-    case INDEX_op_qemu_ld16s:
-        tcg_out_qemu_ld(s, args, 1 | 4);
-        break;
-    case INDEX_op_qemu_ld32:
-    case INDEX_op_qemu_ld32u:
-        tcg_out_qemu_ld(s, args, 2);
-        break;
-    case INDEX_op_qemu_ld32s:
-        tcg_out_qemu_ld(s, args, 2 | 4);
-        break;
-    case INDEX_op_qemu_ld64:
-        tcg_out_qemu_ld(s, args, 3);
-        break;
-        
-    case INDEX_op_qemu_st8:
-        tcg_out_qemu_st(s, args, 0);
-        break;
-    case INDEX_op_qemu_st16:
-        tcg_out_qemu_st(s, args, 1);
-        break;
-    case INDEX_op_qemu_st32:
-        tcg_out_qemu_st(s, args, 2);
-        break;
-    case INDEX_op_qemu_st64:
-        tcg_out_qemu_st(s, args, 3);
-        break;
-
-    default:
-        tcg_abort();
-    }
-}
-
-static int tcg_target_callee_save_regs[] = {
-    TCG_REG_RBP,
-    TCG_REG_RBX,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    /*    TCG_REG_R14, */ /* currently used for the global env, so no
-                             need to save */
-    TCG_REG_R15,
-};
-
-static inline void tcg_out_push(TCGContext *s, int reg)
-{
-    tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
-}
-
-static inline void tcg_out_pop(TCGContext *s, int reg)
-{
-    tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
-}
-
-/* Generate global QEMU prologue and epilogue code */
-static void tcg_target_qemu_prologue(TCGContext *s)
-{
-    int i, frame_size, push_size, stack_addend;
-
-    /* TB prologue */
-    /* save all callee saved registers */
-    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
-        tcg_out_push(s, tcg_target_callee_save_regs[i]);
-
-    }
-    /* reserve some stack space */
-    push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
-    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
-    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
-        ~(TCG_TARGET_STACK_ALIGN - 1);
-    stack_addend = frame_size - push_size;
-    tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
-
-    tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
-    
-    /* TB epilogue */
-    tb_ret_addr = s->code_ptr;
-    tcg_out_addi(s, TCG_REG_RSP, stack_addend);
-    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
-        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
-    }
-    tcg_out8(s, 0xc3); /* ret */
-}
-
-static const TCGTargetOpDef x86_64_op_defs[] = {
-    { INDEX_op_exit_tb, { } },
-    { INDEX_op_goto_tb, { } },
-    { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */
-    { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */
-    { INDEX_op_br, { } },
-
-    { INDEX_op_mov_i32, { "r", "r" } },
-    { INDEX_op_movi_i32, { "r" } },
-    { 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_st8_i32, { "r", "r" } },
-    { INDEX_op_st16_i32, { "r", "r" } },
-    { INDEX_op_st_i32, { "r", "r" } },
-
-    { INDEX_op_add_i32, { "r", "0", "ri" } },
-    { INDEX_op_mul_i32, { "r", "0", "ri" } },
-    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
-    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
-    { INDEX_op_sub_i32, { "r", "0", "ri" } },
-    { INDEX_op_and_i32, { "r", "0", "ri" } },
-    { INDEX_op_or_i32, { "r", "0", "ri" } },
-    { INDEX_op_xor_i32, { "r", "0", "ri" } },
-
-    { INDEX_op_shl_i32, { "r", "0", "ci" } },
-    { INDEX_op_shr_i32, { "r", "0", "ci" } },
-    { INDEX_op_sar_i32, { "r", "0", "ci" } },
-    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
-    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
-
-    { INDEX_op_brcond_i32, { "r", "ri" } },
-
-    { INDEX_op_mov_i64, { "r", "r" } },
-    { INDEX_op_movi_i64, { "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_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", "0", "re" } },
-    { INDEX_op_mul_i64, { "r", "0", "re" } },
-    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
-    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
-    { INDEX_op_sub_i64, { "r", "0", "re" } },
-    { INDEX_op_and_i64, { "r", "0", "reZ" } },
-    { INDEX_op_or_i64, { "r", "0", "re" } },
-    { INDEX_op_xor_i64, { "r", "0", "re" } },
-
-    { INDEX_op_shl_i64, { "r", "0", "ci" } },
-    { INDEX_op_shr_i64, { "r", "0", "ci" } },
-    { INDEX_op_sar_i64, { "r", "0", "ci" } },
-    { INDEX_op_rotl_i64, { "r", "0", "ci" } },
-    { INDEX_op_rotr_i64, { "r", "0", "ci" } },
-
-    { INDEX_op_brcond_i64, { "r", "re" } },
-
-    { INDEX_op_bswap16_i32, { "r", "0" } },
-    { INDEX_op_bswap16_i64, { "r", "0" } },
-    { INDEX_op_bswap32_i32, { "r", "0" } },
-    { INDEX_op_bswap32_i64, { "r", "0" } },
-    { INDEX_op_bswap64_i64, { "r", "0" } },
-
-    { INDEX_op_neg_i32, { "r", "0" } },
-    { INDEX_op_neg_i64, { "r", "0" } },
-
-    { INDEX_op_not_i32, { "r", "0" } },
-    { INDEX_op_not_i64, { "r", "0" } },
-
-    { 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_ext8u_i32, { "r", "r"} },
-    { INDEX_op_ext16u_i32, { "r", "r"} },
-    { INDEX_op_ext8u_i64, { "r", "r"} },
-    { INDEX_op_ext16u_i64, { "r", "r"} },
-    { INDEX_op_ext32u_i64, { "r", "r"} },
-
-    { INDEX_op_setcond_i32, { "r", "r", "ri" } },
-    { INDEX_op_setcond_i64, { "r", "r", "re" } },
-
-    { INDEX_op_qemu_ld8u, { "r", "L" } },
-    { INDEX_op_qemu_ld8s, { "r", "L" } },
-    { INDEX_op_qemu_ld16u, { "r", "L" } },
-    { INDEX_op_qemu_ld16s, { "r", "L" } },
-    { INDEX_op_qemu_ld32, { "r", "L" } },
-    { INDEX_op_qemu_ld32u, { "r", "L" } },
-    { INDEX_op_qemu_ld32s, { "r", "L" } },
-    { INDEX_op_qemu_ld64, { "r", "L" } },
-
-    { INDEX_op_qemu_st8, { "L", "L" } },
-    { INDEX_op_qemu_st16, { "L", "L" } },
-    { INDEX_op_qemu_st32, { "L", "L" } },
-    { INDEX_op_qemu_st64, { "L", "L" } },
-
-    { -1 },
-};
-
-static void tcg_target_init(TCGContext *s)
-{
-#if !defined(CONFIG_USER_ONLY)
-    /* fail safe */
-    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
-        tcg_abort();
-#endif
-
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
-    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
-    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
-                     (1 << TCG_REG_RDI) | 
-                     (1 << TCG_REG_RSI) | 
-                     (1 << TCG_REG_RDX) |
-                     (1 << TCG_REG_RCX) |
-                     (1 << TCG_REG_R8) |
-                     (1 << TCG_REG_R9) |
-                     (1 << TCG_REG_RAX) |
-                     (1 << TCG_REG_R10) |
-                     (1 << TCG_REG_R11));
-    
-    tcg_regset_clear(s->reserved_regs);
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
-
-    tcg_add_target_add_op_defs(x86_64_op_defs);
-}
diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h
deleted file mode 100644
index e0eabaa..0000000
--- a/tcg/x86_64/tcg-target.h
+++ /dev/null
@@ -1,101 +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.
- */
-#define TCG_TARGET_X86_64 1
-
-#define TCG_TARGET_REG_BITS 64
-//#define TCG_TARGET_WORDS_BIGENDIAN
-
-#define TCG_TARGET_NB_REGS 16
-
-enum {
-    TCG_REG_RAX = 0,
-    TCG_REG_RCX,
-    TCG_REG_RDX,
-    TCG_REG_RBX,
-    TCG_REG_RSP,
-    TCG_REG_RBP,
-    TCG_REG_RSI,
-    TCG_REG_RDI,
-    TCG_REG_R8,
-    TCG_REG_R9,
-    TCG_REG_R10,
-    TCG_REG_R11,
-    TCG_REG_R12,
-    TCG_REG_R13,
-    TCG_REG_R14,
-    TCG_REG_R15,
-};
-
-#define TCG_CT_CONST_S32 0x100
-#define TCG_CT_CONST_U32 0x200
-
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_RSP 
-#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 0
-
-/* optional instructions */
-#define TCG_TARGET_HAS_div2_i32
-#define TCG_TARGET_HAS_div2_i64
-#define TCG_TARGET_HAS_bswap16_i32
-#define TCG_TARGET_HAS_bswap16_i64
-#define TCG_TARGET_HAS_bswap32_i32
-#define TCG_TARGET_HAS_bswap32_i64
-#define TCG_TARGET_HAS_bswap64_i64
-#define TCG_TARGET_HAS_neg_i32
-#define TCG_TARGET_HAS_neg_i64
-#define TCG_TARGET_HAS_not_i32
-#define TCG_TARGET_HAS_not_i64
-#define TCG_TARGET_HAS_ext8s_i32
-#define TCG_TARGET_HAS_ext16s_i32
-#define TCG_TARGET_HAS_ext8s_i64
-#define TCG_TARGET_HAS_ext16s_i64
-#define TCG_TARGET_HAS_ext32s_i64
-#define TCG_TARGET_HAS_ext8u_i32
-#define TCG_TARGET_HAS_ext16u_i32
-#define TCG_TARGET_HAS_ext8u_i64
-#define TCG_TARGET_HAS_ext16u_i64
-#define TCG_TARGET_HAS_ext32u_i64
-#define TCG_TARGET_HAS_rot_i32
-#define TCG_TARGET_HAS_rot_i64
-
-// #define TCG_TARGET_HAS_andc_i32
-// #define TCG_TARGET_HAS_andc_i64
-// #define TCG_TARGET_HAS_orc_i32
-// #define TCG_TARGET_HAS_orc_i64
-// #define TCG_TARGET_HAS_eqv_i32
-// #define TCG_TARGET_HAS_eqv_i64
-// #define TCG_TARGET_HAS_nand_i32
-// #define TCG_TARGET_HAS_nand_i64
-// #define TCG_TARGET_HAS_nor_i32
-// #define TCG_TARGET_HAS_nor_i64
-
-#define TCG_TARGET_HAS_GUEST_BASE
-
-/* Note: must be synced with dyngen-exec.h */
-#define TCG_AREG0 TCG_REG_R14
-
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
commit 1c0fd16018384daeb340b389a00768ceecc45611
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 10 00:14:02 2010 +0200

    configure: display sysconfdir in summary
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index b2edb37..46b8e39 100755
--- a/configure
+++ b/configure
@@ -2015,6 +2015,7 @@ fi
 echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $datadir`"
 echo "binary directory  `eval echo $bindir`"
+echo "config directory  `eval echo $sysconfdir`"
 if test "$mingw32" = "no" ; then
 echo "Manual directory  `eval echo $mandir`"
 echo "ELF interp prefix $interp_prefix"
commit ca35f780ac4654bfa086613c72b011448afff327
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:29 2010 +0200

    move computation of tools and roms outside of config-host.mak generation
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index cfecdd6..b2edb37 100755
--- a/configure
+++ b/configure
@@ -1991,6 +1991,27 @@ fi
 
 confdir=$sysconfdir$confsuffix
 
+tools=
+if test "$softmmu" = yes ; then
+  tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
+  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
+      tools="qemu-nbd\$(EXESUF) $tools"
+    if [ "$check_utests" = "yes" ]; then
+      tools="check-qint check-qstring check-qdict check-qlist $tools"
+      tools="check-qfloat check-qjson $tools"
+    fi
+  fi
+fi
+
+# Mac OS X ships with a broken assembler
+roms=
+if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
+        "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
+        "$softmmu" = yes ; then
+  roms="optionrom"
+fi
+
+
 echo "Install prefix    $prefix"
 echo "BIOS directory    `eval echo $datadir`"
 echo "binary directory  `eval echo $bindir`"
@@ -2293,26 +2314,7 @@ bsd)
 ;;
 esac
 
-tools=
-if test "$softmmu" = yes ; then
-  tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
-  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
-      tools="qemu-nbd\$(EXESUF) $tools"
-    if [ "$check_utests" = "yes" ]; then
-      tools="check-qint check-qstring check-qdict check-qlist $tools"
-      tools="check-qfloat check-qjson $tools"
-    fi
-  fi
-fi
 echo "TOOLS=$tools" >> $config_host_mak
-
-# Mac OS X ships with a broken assembler
-roms=
-if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
-        "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
-        "$softmmu" = yes ; then
-  roms="optionrom"
-fi
 echo "ROMS=$roms" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
commit 683035de789e3a0141b1c3bbfdc6180fbc67aaf1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:28 2010 +0200

    configure: move directory defaults earlier
    
    Unify with existing special-purpose configure code for win32.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index fa1b2d0..cfecdd6 100755
--- a/configure
+++ b/configure
@@ -65,14 +65,8 @@ path_of() {
 
 # default parameters
 cpu=""
-prefix=""
 interp_prefix="/usr/gnemul/qemu-%M"
 static="no"
-mandir=""
-datadir=""
-docdir=""
-bindir=""
-sysconfdir=""
 sparc_cpu=""
 cross_prefix=""
 cc="gcc"
@@ -280,6 +274,13 @@ strip_opt="yes"
 bigendian="no"
 mingw32="no"
 EXESUF=""
+prefix="/usr/local"
+mandir="\${prefix}/share/man"
+datadir="\${prefix}/share/qemu"
+docdir="\${prefix}/share/doc/qemu"
+bindir="\${prefix}/bin"
+sysconfdir="\${prefix}/etc"
+confsuffix="/qemu"
 slirp="yes"
 fmod_lib=""
 fmod_inc=""
@@ -454,6 +455,13 @@ if test "$mingw32" = "yes" ; then
   # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
   QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
   LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
+  prefix="c:/Program Files/Qemu"
+  mandir="\${prefix}"
+  datadir="\${prefix}"
+  docdir="\${prefix}"
+  bindir="\${prefix}"
+  sysconfdir="\${prefix}"
+  confsuffix=""
 fi
 
 # find source path
@@ -1981,33 +1989,6 @@ if test "$solaris" = "no" ; then
     fi
 fi
 
-if test "$mingw32" = "yes" ; then
-  if test -z "$prefix" ; then
-      prefix="c:/Program Files/Qemu"
-  fi
-  mansuffix=""
-  datasuffix=""
-  docsuffix=""
-  binsuffix=""
-  sysconfsuffix=""
-  confsuffix=""
-else
-  if test -z "$prefix" ; then
-      prefix="/usr/local"
-  fi
-  mansuffix="/share/man"
-  datasuffix="/share/qemu"
-  docsuffix="/share/doc/qemu"
-  binsuffix="/bin"
-  sysconfsuffix="/etc"
-  confsuffix="/qemu"
-fi
-
-: ${mandir:="\${prefix}$mansuffix"}
-: ${datadir:="\${prefix}$datasuffix"}
-: ${docdir:="\${prefix}$docsuffix"}
-: ${bindir:="\${prefix}$binsuffix"}
-: ${sysconfdir:="\${prefix}$sysconfsuffix"}
 confdir=$sysconfdir$confsuffix
 
 echo "Install prefix    $prefix"
commit 6bde81cb03898b725ae6f94050aa060772c836e8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:27 2010 +0200

    configure: ignore unknown --xyzdir options
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 5eb3ecd..fa1b2d0 100755
--- a/configure
+++ b/configure
@@ -673,6 +673,8 @@ for opt do
   ;;
   --enable-vhost-net) vhost_net="yes"
   ;;
+  --*dir)
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
commit 0b24e75f85c251b7ae699631768f129ddf03ae5e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:26 2010 +0200

    configure: introduce more --xyzdir options
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 9d8b4b3..5eb3ecd 100755
--- a/configure
+++ b/configure
@@ -68,6 +68,10 @@ cpu=""
 prefix=""
 interp_prefix="/usr/gnemul/qemu-%M"
 static="no"
+mandir=""
+datadir=""
+docdir=""
+bindir=""
 sysconfdir=""
 sparc_cpu=""
 cross_prefix=""
@@ -501,6 +505,14 @@ for opt do
     static="yes"
     LDFLAGS="-static $LDFLAGS"
   ;;
+  --mandir=*) mandir="$optarg"
+  ;;
+  --bindir=*) bindir="$optarg"
+  ;;
+  --datadir=*) datadir="$optarg"
+  ;;
+  --docdir=*) docdir="$optarg"
+  ;;
   --sysconfdir=*) sysconfdir="$optarg"
   ;;
   --disable-sdl) sdl="no"
@@ -755,7 +767,11 @@ echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
 echo "  --make=MAKE              use specified make [$make]"
 echo "  --install=INSTALL        use specified install [$install]"
 echo "  --static                 enable static build [$static]"
-echo "  --sysconfdir=PATH        install config in PATH"
+echo "  --mandir=PATH            install man pages in PATH"
+echo "  --datadir=PATH           install firmware in PATH"
+echo "  --docdir=PATH            install documentation in PATH"
+echo "  --bindir=PATH            install binaries in PATH"
+echo "  --sysconfdir=PATH        install config in PATH/qemu"
 echo "  --enable-debug-tcg       enable TCG debugging"
 echo "  --disable-debug-tcg      disable TCG debugging (default)"
 echo "  --enable-debug           enable common debug build options"
@@ -1985,10 +2001,10 @@ else
   confsuffix="/qemu"
 fi
 
-mandir="\${prefix}$mansuffix"
-datadir="\${prefix}$datasuffix"
-docdir="\${prefix}$docsuffix"
-bindir="\${prefix}$binsuffix"
+: ${mandir:="\${prefix}$mansuffix"}
+: ${datadir:="\${prefix}$datasuffix"}
+: ${docdir:="\${prefix}$docsuffix"}
+: ${bindir:="\${prefix}$binsuffix"}
 : ${sysconfdir:="\${prefix}$sysconfsuffix"}
 confdir=$sysconfdir$confsuffix
 
commit 1dabe05ce40010588a7b2485219a2692fe1e7472
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:25 2010 +0200

    configure: expand ${prefix} in create_config
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index c99461a..9d8b4b3 100755
--- a/configure
+++ b/configure
@@ -2073,8 +2073,7 @@ echo "mandir=$mandir" >> $config_host_mak
 echo "datadir=$datadir" >> $config_host_mak
 echo "sysconfdir=$sysconfdir" >> $config_host_mak
 echo "docdir=$docdir" >> $config_host_mak
-echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
-echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
+echo "confdir=$confdir" >> $config_host_mak
 
 case "$cpu" in
   i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
diff --git a/create_config b/create_config
index edcad25..23c0cd5 100755
--- a/create_config
+++ b/create_config
@@ -13,6 +13,15 @@ case $line in
     pkgversion=${line#*=}
     echo "#define QEMU_PKGVERSION \"$pkgversion\""
     ;;
+ prefix=* | *dir=*) # directory configuration
+    name=${line%=*}
+    value=${line#*=}
+    define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
+    eval "define_value=\"$value\""
+    echo "#define CONFIG_QEMU_$define_name \"$define_value\""
+    # save for the next definitions
+    eval "$name=\$define_value"
+    ;;
  CONFIG_AUDIO_DRIVERS=*)
     drivers=${line#*=}
     echo "#define CONFIG_AUDIO_DRIVERS \\"
diff --git a/vl.c b/vl.c
index 7121cd0..6d08ec8 100644
--- a/vl.c
+++ b/vl.c
@@ -3423,7 +3423,7 @@ int main(int argc, char **argv, char **envp)
     }
     /* If all else fails use the install patch specified when building.  */
     if (!data_dir) {
-        data_dir = CONFIG_QEMU_SHAREDIR;
+        data_dir = CONFIG_QEMU_DATADIR;
     }
 
     /*
commit 99d7cc75dd1f1167a02294804f993deb354d8159
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:24 2010 +0200

    configure: move all directory entries in config-host.mak close
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 23a056f..c99461a 100755
--- a/configure
+++ b/configure
@@ -2067,6 +2067,12 @@ printf "# Configured with:" >> $config_host_mak
 printf " '%s'" "$0" "$@" >> $config_host_mak
 echo >> $config_host_mak
 
+echo "prefix=$prefix" >> $config_host_mak
+echo "bindir=$bindir" >> $config_host_mak
+echo "mandir=$mandir" >> $config_host_mak
+echo "datadir=$datadir" >> $config_host_mak
+echo "sysconfdir=$sysconfdir" >> $config_host_mak
+echo "docdir=$docdir" >> $config_host_mak
 echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
 echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
 
@@ -2310,13 +2316,6 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
   roms="optionrom"
 fi
 echo "ROMS=$roms" >> $config_host_mak
-
-echo "prefix=$prefix" >> $config_host_mak
-echo "bindir=$bindir" >> $config_host_mak
-echo "mandir=$mandir" >> $config_host_mak
-echo "datadir=$datadir" >> $config_host_mak
-echo "sysconfdir=$sysconfdir" >> $config_host_mak
-echo "docdir=$docdir" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
 echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
commit f2b9e1e37d9f4eaae35a7b568f913093897b121e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:23 2010 +0200

    configure: unify handling of xyzdir variables
    
    Making an xyzdir variable for each directory prepares for the next
    patches introducing config-host.h defines and configure options for them.
    It also fixes the problem where overriding prefix at "make install"
    time did not override it for sysconfdir.
    
    Removes some of the differences between sysconfdir and other variables,
    the rest will go away later.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 6f282a3..23a056f 100755
--- a/configure
+++ b/configure
@@ -1985,14 +1985,18 @@ else
   confsuffix="/qemu"
 fi
 
-: ${sysconfdir:="${prefix}$sysconfsuffix"}
+mandir="\${prefix}$mansuffix"
+datadir="\${prefix}$datasuffix"
+docdir="\${prefix}$docsuffix"
+bindir="\${prefix}$binsuffix"
+: ${sysconfdir:="\${prefix}$sysconfsuffix"}
 confdir=$sysconfdir$confsuffix
 
 echo "Install prefix    $prefix"
-echo "BIOS directory    $prefix$datasuffix"
-echo "binary directory  $prefix$binsuffix"
+echo "BIOS directory    `eval echo $datadir`"
+echo "binary directory  `eval echo $bindir`"
 if test "$mingw32" = "no" ; then
-echo "Manual directory  $prefix$mansuffix"
+echo "Manual directory  `eval echo $mandir`"
 echo "ELF interp prefix $interp_prefix"
 fi
 echo "Source path       $source_path"
@@ -2308,11 +2312,11 @@ fi
 echo "ROMS=$roms" >> $config_host_mak
 
 echo "prefix=$prefix" >> $config_host_mak
-echo "bindir=\${prefix}$binsuffix" >> $config_host_mak
-echo "mandir=\${prefix}$mansuffix" >> $config_host_mak
-echo "datadir=\${prefix}$datasuffix" >> $config_host_mak
+echo "bindir=$bindir" >> $config_host_mak
+echo "mandir=$mandir" >> $config_host_mak
+echo "datadir=$datadir" >> $config_host_mak
 echo "sysconfdir=$sysconfdir" >> $config_host_mak
-echo "docdir=\${prefix}$docsuffix" >> $config_host_mak
+echo "docdir=$docdir" >> $config_host_mak
 echo "MAKE=$make" >> $config_host_mak
 echo "INSTALL=$install" >> $config_host_mak
 echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
commit 7ee2822cbeb06dbf38f5b38b5d7fa7829d598350
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:22 2010 +0200

    rename CONFIG_QEMU_PREFIX
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 05cc3d9..aff9f13 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -43,7 +43,7 @@ unsigned long guest_base;
 int have_guest_base;
 #endif
 
-static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 extern char **environ;
 enum BSDType bsd_type;
diff --git a/configure b/configure
index f7b0a6d..6f282a3 100755
--- a/configure
+++ b/configure
@@ -2430,7 +2430,7 @@ echo "# Automatically generated by configure - do not modify" > $config_target_m
 bflt="no"
 target_nptl="no"
 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
-echo "CONFIG_QEMU_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
+echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
 gdb_xml_files=""
 
 TARGET_ARCH="$target_arch2"
diff --git a/linux-user/main.c b/linux-user/main.c
index ad292f1..403c8d3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -47,7 +47,7 @@ int have_guest_base;
 unsigned long reserved_va;
 #endif
 
-static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 
 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
commit 190e9c59c0d4f56c98e378d1024d46cc7166409b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:21 2010 +0200

    configure: introduce confdir and confsuffix
    
    confsuffix was write-only, flesh it out.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 553607a..f7b0a6d 100755
--- a/configure
+++ b/configure
@@ -1969,10 +1969,10 @@ if test "$mingw32" = "yes" ; then
   fi
   mansuffix=""
   datasuffix=""
-  confsuffix=""
   docsuffix=""
   binsuffix=""
   sysconfsuffix=""
+  confsuffix=""
 else
   if test -z "$prefix" ; then
       prefix="/usr/local"
@@ -1982,9 +1982,11 @@ else
   docsuffix="/share/doc/qemu"
   binsuffix="/bin"
   sysconfsuffix="/etc"
+  confsuffix="/qemu"
 fi
 
 : ${sysconfdir:="${prefix}$sysconfsuffix"}
+confdir=$sysconfdir$confsuffix
 
 echo "Install prefix    $prefix"
 echo "BIOS directory    $prefix$datasuffix"
@@ -2062,11 +2064,7 @@ printf " '%s'" "$0" "$@" >> $config_host_mak
 echo >> $config_host_mak
 
 echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
-if test "$mingw32" = "yes" ; then
-  echo "CONFIG_QEMU_CONFDIR=\"$sysconfdir\"" >> $config_host_mak
-else
-  echo "CONFIG_QEMU_CONFDIR=\"${sysconfdir}/qemu\"" >> $config_host_mak
-fi
+echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
 
 case "$cpu" in
   i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
commit e7b45cc4467f9bbae46acdc8d21ceb2a16d63b50
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:20 2010 +0200

    configure: introduce sysconfsuffix
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 31bd7ec..553607a 100755
--- a/configure
+++ b/configure
@@ -1972,9 +1972,7 @@ if test "$mingw32" = "yes" ; then
   confsuffix=""
   docsuffix=""
   binsuffix=""
-  if test -z "$sysconfdir" ; then
-      sysconfdir="${prefix}"
-  fi
+  sysconfsuffix=""
 else
   if test -z "$prefix" ; then
       prefix="/usr/local"
@@ -1983,11 +1981,11 @@ else
   datasuffix="/share/qemu"
   docsuffix="/share/doc/qemu"
   binsuffix="/bin"
-  if test -z "$sysconfdir" ; then
-      sysconfdir="${prefix}/etc"
-  fi
+  sysconfsuffix="/etc"
 fi
 
+: ${sysconfdir:="${prefix}$sysconfsuffix"}
+
 echo "Install prefix    $prefix"
 echo "BIOS directory    $prefix$datasuffix"
 echo "binary directory  $prefix$binsuffix"
commit 604f78e06e41526924890d83f9dab168268f4702
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:19 2010 +0200

    configure: delete duplicate create_config case stanza
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/create_config b/create_config
index 2f052ae..edcad25 100755
--- a/create_config
+++ b/create_config
@@ -13,11 +13,6 @@ case $line in
     pkgversion=${line#*=}
     echo "#define QEMU_PKGVERSION \"$pkgversion\""
     ;;
- ARCH=*) # configuration
-    arch=${line#*=}
-    arch_name=`echo $arch | tr '[:lower:]' '[:upper:]'`
-    echo "#define HOST_$arch_name 1"
-    ;;
  CONFIG_AUDIO_DRIVERS=*)
     drivers=${line#*=}
     echo "#define CONFIG_AUDIO_DRIVERS \\"
commit 0bfe8cc01259dff2b0d4d464d9154d0a2c25daca
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:18 2010 +0200

    configure: dyngen is long time gone
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 57eb27f..31bd7ec 100755
--- a/configure
+++ b/configure
@@ -748,7 +748,8 @@ echo "Advanced options (experts only):"
 echo "  --source-path=PATH       path of source code [$source_path]"
 echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
 echo "  --cc=CC                  use C compiler CC [$cc]"
-echo "  --host-cc=CC             use C compiler CC [$host_cc] for dyngen etc."
+echo "  --host-cc=CC             use C compiler CC [$host_cc] for code run at"
+echo "                           build time"
 echo "  --extra-cflags=CFLAGS    append extra C compiler flags QEMU_CFLAGS"
 echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
 echo "  --make=MAKE              use specified make [$make]"
commit f55fe2785c017a00b3aef547a68e2dd1a4843a16
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:17 2010 +0200

    configure: avoid using expr
    
    Just a personal preference against duplicating hieroglyphics.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 1d4f1e4..57eb27f 100755
--- a/configure
+++ b/configure
@@ -928,6 +928,13 @@ if test -z "$target_list" ; then
     echo "No targets enabled"
     exit 1
 fi
+# see if system emulation was really requested
+case " $target_list " in
+  *"-softmmu "*) softmmu=yes
+  ;;
+  *) softmmu=no
+  ;;
+esac
 
 feature_not_found() {
   feature=$1
@@ -2282,7 +2289,7 @@ bsd)
 esac
 
 tools=
-if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
@@ -2298,7 +2305,7 @@ echo "TOOLS=$tools" >> $config_host_mak
 roms=
 if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
         "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
-        `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+        "$softmmu" = yes ; then
   roms="optionrom"
 fi
 echo "ROMS=$roms" >> $config_host_mak
commit a447d4dc5607176a70361aed9361e1b63dc67ec9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed May 26 16:08:16 2010 +0200

    configure: bail out early on invalid -cpu option
    
    It would fail later anyway.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 8d3084a..1d4f1e4 100755
--- a/configure
+++ b/configure
@@ -232,7 +232,8 @@ case "$cpu" in
     cpu="sparc"
   ;;
   *)
-    cpu="unknown"
+    echo "Unsupported CPU = $cpu"
+    exit 1
   ;;
 esac
 
@@ -2068,10 +2069,6 @@ case "$cpu" in
   armv4b|armv4l)
     ARCH=arm
   ;;
-  *)
-    echo "Unsupported CPU = $cpu"
-    exit 1
-  ;;
 esac
 echo "ARCH=$ARCH" >> $config_host_mak
 if test "$debug_tcg" = "yes" ; then
commit 4021d2476c61ff101f97b6642d1fbb3c34844091
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 10 00:06:55 2010 +0200

    configure: remove some bashisms
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 72d8924..8d3084a 100755
--- a/configure
+++ b/configure
@@ -15,7 +15,7 @@ TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
 TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
 TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
 
-trap "rm -f $TMPC $TMPO $TMPE ; exit" 0 2 3 15
+trap "rm -f $TMPC $TMPO $TMPE ; exit" EXIT INT QUIT TERM
 
 compile_object() {
   $cc $QEMU_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null
@@ -1546,7 +1546,7 @@ EOF
             fi
     else
             if test "$vhost_net" = "yes" ; then
-                echo -e "NOTE: vhost-net feature requires KVM (--enable-kvm)."
+                echo "NOTE: vhost-net feature requires KVM (--enable-kvm)."
                 feature_not_found "vhost-net"
             fi
             vhost_net=no
commit 330875984432c26ef78bad85c4ee9816d3c41ca5
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Wed Jun 9 22:09:40 2010 +0200

    target-mips: Fix compilation
    
    TCGv t1 needs tcg_temp_free instead of tcg_temp_free_i32.
    
    Cc: Nathan Froyd <froydnj at codesourcery.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index ab8f974..d43d72d 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -9484,7 +9484,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
     }
     MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
     tcg_temp_free(t0);
-    tcg_temp_free_i32(t1);
+    tcg_temp_free(t1);
     tcg_temp_free_i32(t2);
 }
 
commit aecf13769852a4e14b51e8403860b18871826298
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:30:03 2010 -0700

    hw: honor low bit in mipssim machine
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index a747de5..293d99e 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -106,7 +106,10 @@ static void main_cpu_reset(void *opaque)
     CPUState *env = s->env;
 
     cpu_reset(env);
-    env->active_tc.PC = s->vector;
+    env->active_tc.PC = s->vector & ~(target_ulong)1;
+    if (s->vector & 1) {
+        env->hflags |= MIPS_HFLAG_M16;
+    }
 }
 
 static void
commit 0fddbbf2559579ab6274c50819001f4eb9896b2a
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:30:02 2010 -0700

    linux-user: honor low bit of entry PC for MIPS
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 0f23fc9..ad292f1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3271,7 +3271,10 @@ int main(int argc, char **argv, char **envp)
         for(i = 0; i < 32; i++) {
             env->active_tc.gpr[i] = regs->regs[i];
         }
-        env->active_tc.PC = regs->cp0_epc;
+        env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
+        if (regs->cp0_epc & 1) {
+            env->hflags |= MIPS_HFLAG_M16;
+        }
     }
 #elif defined(TARGET_SH4)
     {
commit bbfa8f72e99baa0514b2b39e671830cf9a3adc44
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:30:01 2010 -0700

    target-mips: add microMIPS exception handler support
    
    Unlike MIPS16, microMIPS lets you choose the ISA mode for your exception
    handlers.  The ISA mode is selectable via a user-writable CP0.Config3
    flag.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 7285636..c21b8e4 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -363,6 +363,7 @@ struct CPUMIPSState {
 #define CP0C2_SA   0
     int32_t CP0_Config3;
 #define CP0C3_M    31
+#define CP0C3_ISA_ON_EXC 16
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
 #define CP0C3_VEIC 6
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 8102f03..ea221ab 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -385,6 +385,18 @@ static target_ulong exception_resume_pc (CPUState *env)
 
     return bad_pc;
 }
+
+static void set_hflags_for_handler (CPUState *env)
+{
+    /* Exception handlers are entered in 32-bit mode.  */
+    env->hflags &= ~(MIPS_HFLAG_M16);
+    /* ...except that microMIPS lets you choose.  */
+    if (env->insn_flags & ASE_MICROMIPS) {
+        env->hflags |= (!!(env->CP0_Config3
+                           & (1 << CP0C3_ISA_ON_EXC))
+                        << MIPS_HFLAG_M16_SHIFT);
+    }
+}
 #endif
 
 void do_interrupt (CPUState *env)
@@ -440,8 +452,7 @@ void do_interrupt (CPUState *env)
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->active_tc.PC = (int32_t)0xBFC00480;
-        /* Exception handlers are entered in 32-bit mode.  */
-        env->hflags &= ~(MIPS_HFLAG_M16);
+        set_hflags_for_handler(env);
         break;
     case EXCP_RESET:
         cpu_reset(env);
@@ -461,8 +472,7 @@ void do_interrupt (CPUState *env)
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->active_tc.PC = (int32_t)0xBFC00000;
-        /* Exception handlers are entered in 32-bit mode.  */
-        env->hflags &= ~(MIPS_HFLAG_M16);
+        set_hflags_for_handler(env);
         break;
     case EXCP_EXT_INTERRUPT:
         cause = 0;
@@ -581,8 +591,7 @@ void do_interrupt (CPUState *env)
             env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
         }
         env->active_tc.PC += offset;
-        /* Exception handlers are entered in 32-bit mode.  */
-        env->hflags &= ~(MIPS_HFLAG_M16);
+        set_hflags_for_handler(env);
         env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
         break;
     default:
commit 3c824109da076d2a1df4b798f9df81b385131f92
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:29:59 2010 -0700

    target-mips: microMIPS ASE support
    
    Add instruction decoding for the microMIPS ASE.  All we do is decode and
    then forward to the existing gen_* routines.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/helper.h b/target-mips/helper.h
index ab47b1a..a6ba75d 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -160,6 +160,15 @@ DEF_HELPER_1(emt, tl, tl)
 DEF_HELPER_1(dvpe, tl, tl)
 DEF_HELPER_1(evpe, tl, tl)
 #endif /* !CONFIG_USER_ONLY */
+
+/* microMIPS functions */
+DEF_HELPER_3(lwm, void, tl, tl, i32);
+DEF_HELPER_3(swm, void, tl, tl, i32);
+#ifdef TARGET_MIPS64
+DEF_HELPER_3(ldm, void, tl, tl, i32);
+DEF_HELPER_3(sdm, void, tl, tl, i32);
+#endif
+
 DEF_HELPER_2(fork, void, tl, tl)
 DEF_HELPER_1(yield, tl, tl)
 
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index c57de02..a7f4697 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -38,6 +38,7 @@
 #define		ASE_DSPR2	0x00010000
 #define		ASE_MT		0x00020000
 #define		ASE_SMARTMIPS	0x00040000
+#define 	ASE_MICROMIPS	0x00080000
 
 /* Chip specific instructions. */
 #define		INSN_VR54XX	0x80000000
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 2bfdd50..d09d6ed 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -565,6 +565,142 @@ void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
 }
 #endif /* TARGET_MIPS64 */
 
+static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
+
+void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+    target_ulong base_reglist = reglist & 0xf;
+    target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef ldfun
+#define ldfun ldl_raw
+#else
+    uint32_t (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldl_kernel; break;
+    case 1: ldfun = ldl_super; break;
+    default:
+    case 2: ldfun = ldl_user; break;
+    }
+#endif
+
+    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+        target_ulong i;
+
+        for (i = 0; i < base_reglist; i++) {
+            env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
+            addr += 4;
+        }
+    }
+
+    if (do_r31) {
+        env->active_tc.gpr[31] = (target_long) ldfun(addr);
+    }
+}
+
+void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+    target_ulong base_reglist = reglist & 0xf;
+    target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef stfun
+#define stfun stl_raw
+#else
+    void (*stfun)(target_ulong, uint32_t);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stl_kernel; break;
+    case 1: stfun = stl_super; break;
+     default:
+    case 2: stfun = stl_user; break;
+    }
+#endif
+
+    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+        target_ulong i;
+
+        for (i = 0; i < base_reglist; i++) {
+            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
+            addr += 4;
+        }
+    }
+
+    if (do_r31) {
+        stfun(addr, env->active_tc.gpr[31]);
+    }
+}
+
+#if defined(TARGET_MIPS64)
+void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+    target_ulong base_reglist = reglist & 0xf;
+    target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef ldfun
+#define ldfun ldq_raw
+#else
+    uint64_t (*ldfun)(target_ulong);
+
+    switch (mem_idx)
+    {
+    case 0: ldfun = ldq_kernel; break;
+    case 1: ldfun = ldq_super; break;
+    default:
+    case 2: ldfun = ldq_user; break;
+    }
+#endif
+
+    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+        target_ulong i;
+
+        for (i = 0; i < base_reglist; i++) {
+            env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
+            addr += 8;
+        }
+    }
+
+    if (do_r31) {
+        env->active_tc.gpr[31] = ldfun(addr);
+    }
+}
+
+void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+    target_ulong base_reglist = reglist & 0xf;
+    target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef stfun
+#define stfun stq_raw
+#else
+    void (*stfun)(target_ulong, uint64_t);
+
+    switch (mem_idx)
+    {
+    case 0: stfun = stq_kernel; break;
+    case 1: stfun = stq_super; break;
+     default:
+    case 2: stfun = stq_user; break;
+    }
+#endif
+
+    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+        target_ulong i;
+
+        for (i = 0; i < base_reglist; i++) {
+            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
+            addr += 8;
+        }
+    }
+
+    if (do_r31) {
+        stfun(addr, env->active_tc.gpr[31]);
+    }
+}
+#endif
+
 #ifndef CONFIG_USER_ONLY
 /* CP0 helpers */
 target_ulong helper_mfc0_mvpcontrol (void)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 78783a8..ab8f974 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -4,7 +4,7 @@
  *  Copyright (c) 2004-2005 Jocelyn Mayer
  *  Copyright (c) 2006 Marius Groeger (FPU operations)
  *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
- *  Copyright (c) 2009 CodeSourcery (MIPS16 support)
+ *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -243,8 +243,10 @@ enum {
     OPC_BGEZ     = (0x01 << 16) | OPC_REGIMM,
     OPC_BGEZL    = (0x03 << 16) | OPC_REGIMM,
     OPC_BLTZAL   = (0x10 << 16) | OPC_REGIMM,
+    OPC_BLTZALS  = OPC_BLTZAL | 0x5, /* microMIPS */
     OPC_BLTZALL  = (0x12 << 16) | OPC_REGIMM,
     OPC_BGEZAL   = (0x11 << 16) | OPC_REGIMM,
+    OPC_BGEZALS  = OPC_BGEZAL | 0x5, /* microMIPS */
     OPC_BGEZALL  = (0x13 << 16) | OPC_REGIMM,
     OPC_TGEI     = (0x08 << 16) | OPC_REGIMM,
     OPC_TGEIU    = (0x09 << 16) | OPC_REGIMM,
@@ -2449,6 +2451,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
         break;
     case OPC_BGEZ:
     case OPC_BGEZAL:
+    case OPC_BGEZALS:
     case OPC_BGEZALL:
     case OPC_BGEZL:
     case OPC_BGTZ:
@@ -2457,6 +2460,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
     case OPC_BLEZL:
     case OPC_BLTZ:
     case OPC_BLTZAL:
+    case OPC_BLTZALS:
     case OPC_BLTZALL:
     case OPC_BLTZL:
         /* Compare to zero */
@@ -2506,8 +2510,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("balways");
             break;
+        case OPC_BGEZALS:
         case OPC_BGEZAL:  /* 0 >= 0          */
         case OPC_BGEZALL: /* 0 >= 0 likely   */
+            ctx->hflags |= (opc == OPC_BGEZALS
+                            ? MIPS_HFLAG_BDS16
+                            : MIPS_HFLAG_BDS32);
             /* Always take and link */
             blink = 31;
             ctx->hflags |= MIPS_HFLAG_B;
@@ -2519,10 +2527,18 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             /* Treat as NOP. */
             MIPS_DEBUG("bnever (NOP)");
             goto out;
+        case OPC_BLTZALS:
         case OPC_BLTZAL:  /* 0 < 0           */
-            tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
+            ctx->hflags |= (opc == OPC_BLTZALS
+                            ? MIPS_HFLAG_BDS16
+                            : MIPS_HFLAG_BDS32);
+            /* Handle as an unconditional branch to get correct delay
+               slot checking.  */
+            blink = 31;
+            btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
+            ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("bnever and link");
-            goto out;
+            break;
         case OPC_BLTZALL: /* 0 < 0 likely */
             tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
             /* Skip the instruction in the delay slot */
@@ -2604,7 +2620,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
             MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
             goto likely;
+        case OPC_BGEZALS:
         case OPC_BGEZAL:
+            ctx->hflags |= (opc == OPC_BGEZALS
+                            ? MIPS_HFLAG_BDS16
+                            : MIPS_HFLAG_BDS32);
             tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
             MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
             blink = 31;
@@ -2638,7 +2658,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
             MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
             goto likely;
+        case OPC_BLTZALS:
         case OPC_BLTZAL:
+            ctx->hflags |= (opc == OPC_BLTZALS
+                            ? MIPS_HFLAG_BDS16
+                            : MIPS_HFLAG_BDS32);
             tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
             blink = 31;
             MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
@@ -7785,7 +7809,7 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx,
         case MIPS_HFLAG_BR:
             /* unconditional branch to register */
             MIPS_DEBUG("branch to register");
-            if (env->insn_flags & ASE_MIPS16) {
+            if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
                 TCGv t0 = tcg_temp_new();
                 TCGv_i32 t1 = tcg_temp_new_i32();
 
@@ -8906,6 +8930,2358 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
     return n_bytes;
 }
 
+/* microMIPS extension to MIPS32 */
+
+/* microMIPS32 major opcodes */
+
+enum {
+    POOL32A = 0x00,
+    POOL16A = 0x01,
+    LBU16 = 0x02,
+    MOVE16 = 0x03,
+    ADDI32 = 0x04,
+    LBU32 = 0x05,
+    SB32 = 0x06,
+    LB32 = 0x07,
+
+    POOL32B = 0x08,
+    POOL16B = 0x09,
+    LHU16 = 0x0a,
+    ANDI16 = 0x0b,
+    ADDIU32 = 0x0c,
+    LHU32 = 0x0d,
+    SH32 = 0x0e,
+    LH32 = 0x0f,
+
+    POOL32I = 0x10,
+    POOL16C = 0x11,
+    LWSP16 = 0x12,
+    POOL16D = 0x13,
+    ORI32 = 0x14,
+    POOL32F = 0x15,
+    POOL32S = 0x16,
+    DADDIU32 = 0x17,
+
+    POOL32C = 0x18,
+    LWGP16 = 0x19,
+    LW16 = 0x1a,
+    POOL16E = 0x1b,
+    XORI32 = 0x1c,
+    JALS32 = 0x1d,
+    ADDIUPC = 0x1e,
+    POOL48A = 0x1f,
+
+    /* 0x20 is reserved */
+    RES_20 = 0x20,
+    POOL16F = 0x21,
+    SB16 = 0x22,
+    BEQZ16 = 0x23,
+    SLTI32 = 0x24,
+    BEQ32 = 0x25,
+    SWC132 = 0x26,
+    LWC132 = 0x27,
+
+    /* 0x28 and 0x29 are reserved */
+    RES_28 = 0x28,
+    RES_29 = 0x29,
+    SH16 = 0x2a,
+    BNEZ16 = 0x2b,
+    SLTIU32 = 0x2c,
+    BNE32 = 0x2d,
+    SDC132 = 0x2e,
+    LDC132 = 0x2f,
+
+    /* 0x30 and 0x31 are reserved */
+    RES_30 = 0x30,
+    RES_31 = 0x31,
+    SWSP16 = 0x32,
+    B16 = 0x33,
+    ANDI32 = 0x34,
+    J32 = 0x35,
+    SD32 = 0x36,
+    LD32 = 0x37,
+
+    /* 0x38 and 0x39 are reserved */
+    RES_38 = 0x38,
+    RES_39 = 0x39,
+    SW16 = 0x3a,
+    LI16 = 0x3b,
+    JALX32 = 0x3c,
+    JAL32 = 0x3d,
+    SW32 = 0x3e,
+    LW32 = 0x3f
+};
+
+/* POOL32A encoding of minor opcode field */
+
+enum {
+    /* These opcodes are distinguished only by bits 9..6; those bits are
+     * what are recorded below. */
+    SLL32 = 0x0,
+    SRL32 = 0x1,
+    SRA = 0x2,
+    ROTR = 0x3,
+
+    SLLV = 0x0,
+    SRLV = 0x1,
+    SRAV = 0x2,
+    ROTRV = 0x3,
+    ADD = 0x4,
+    ADDU32 = 0x5,
+    SUB = 0x6,
+    SUBU32 = 0x7,
+    MUL = 0x8,
+    AND = 0x9,
+    OR32 = 0xa,
+    NOR = 0xb,
+    XOR32 = 0xc,
+    SLT = 0xd,
+    SLTU = 0xe,
+
+    MOVN = 0x0,
+    MOVZ = 0x1,
+    LWXS = 0x4,
+
+    /* The following can be distinguished by their lower 6 bits. */
+    INS = 0x0c,
+    EXT = 0x2c,
+    POOL32AXF = 0x3c
+};
+
+/* POOL32AXF encoding of minor opcode field extension */
+
+enum {
+    /* bits 11..6 */
+    TEQ = 0x00,
+    TGE = 0x08,
+    TGEU = 0x10,
+    TLT = 0x20,
+    TLTU = 0x28,
+    TNE = 0x30,
+
+    MFC0 = 0x03,
+    MTC0 = 0x0b,
+
+    /* bits 13..12 for 0x01 */
+    MFHI_ACC = 0x0,
+    MFLO_ACC = 0x1,
+    MTHI_ACC = 0x2,
+    MTLO_ACC = 0x3,
+
+    /* bits 13..12 for 0x2a */
+    MADD_ACC = 0x0,
+    MADDU_ACC = 0x1,
+    MSUB_ACC = 0x2,
+    MSUBU_ACC = 0x3,
+
+    /* bits 13..12 for 0x32 */
+    MULT_ACC = 0x0,
+    MULTU_ACC = 0x0,
+
+    /* bits 15..12 for 0x2c */
+    SEB = 0x2,
+    SEH = 0x3,
+    CLO = 0x4,
+    CLZ = 0x5,
+    RDHWR = 0x6,
+    WSBH = 0x7,
+    MULT = 0x8,
+    MULTU = 0x9,
+    DIV = 0xa,
+    DIVU = 0xb,
+    MADD = 0xc,
+    MADDU = 0xd,
+    MSUB = 0xe,
+    MSUBU = 0xf,
+
+    /* bits 15..12 for 0x34 */
+    MFC2 = 0x4,
+    MTC2 = 0x5,
+    MFHC2 = 0x8,
+    MTHC2 = 0x9,
+    CFC2 = 0xc,
+    CTC2 = 0xd,
+
+    /* bits 15..12 for 0x3c */
+    JALR = 0x0,
+    JR = 0x0,                   /* alias */
+    JALR_HB = 0x1,
+    JALRS = 0x4,
+    JALRS_HB = 0x5,
+
+    /* bits 15..12 for 0x05 */
+    RDPGPR = 0xe,
+    WRPGPR = 0xf,
+
+    /* bits 15..12 for 0x0d */
+    TLBP = 0x0,
+    TLBR = 0x1,
+    TLBWI = 0x2,
+    TLBWR = 0x3,
+    WAIT = 0x9,
+    IRET = 0xd,
+    DERET = 0xe,
+    ERET = 0xf,
+
+    /* bits 15..12 for 0x15 */
+    DMT = 0x0,
+    DVPE = 0x1,
+    EMT = 0x2,
+    EVPE = 0x3,
+
+    /* bits 15..12 for 0x1d */
+    DI = 0x4,
+    EI = 0x5,
+
+    /* bits 15..12 for 0x2d */
+    SYNC = 0x6,
+    SYSCALL = 0x8,
+    SDBBP = 0xd,
+
+    /* bits 15..12 for 0x35 */
+    MFHI32 = 0x0,
+    MFLO32 = 0x1,
+    MTHI32 = 0x2,
+    MTLO32 = 0x3,
+};
+
+/* POOL32B encoding of minor opcode field (bits 15..12) */
+
+enum {
+    LWC2 = 0x0,
+    LWP = 0x1,
+    LDP = 0x4,
+    LWM32 = 0x5,
+    CACHE = 0x6,
+    LDM = 0x7,
+    SWC2 = 0x8,
+    SWP = 0x9,
+    SDP = 0xc,
+    SWM32 = 0xd,
+    SDM = 0xf
+};
+
+/* POOL32C encoding of minor opcode field (bits 15..12) */
+
+enum {
+    LWL = 0x0,
+    SWL = 0x8,
+    LWR = 0x1,
+    SWR = 0x9,
+    PREF = 0x2,
+    /* 0xa is reserved */
+    LL = 0x3,
+    SC = 0xb,
+    LDL = 0x4,
+    SDL = 0xc,
+    LDR = 0x5,
+    SDR = 0xd,
+    /* 0x6 is reserved */
+    LWU = 0xe,
+    LLD = 0x7,
+    SCD = 0xf
+};
+
+/* POOL32F encoding of minor opcode field (bits 5..0) */
+
+enum {
+    /* These are the bit 7..6 values */
+    ADD_FMT = 0x0,
+    MOVN_FMT = 0x0,
+
+    SUB_FMT = 0x1,
+    MOVZ_FMT = 0x1,
+
+    MUL_FMT = 0x2,
+
+    DIV_FMT = 0x3,
+
+    /* These are the bit 8..6 values */
+    RSQRT2_FMT = 0x0,
+    MOVF_FMT = 0x0,
+
+    LWXC1 = 0x1,
+    MOVT_FMT = 0x1,
+
+    PLL_PS = 0x2,
+    SWXC1 = 0x2,
+
+    PLU_PS = 0x3,
+    LDXC1 = 0x3,
+
+    PUL_PS = 0x4,
+    SDXC1 = 0x4,
+    RECIP2_FMT = 0x4,
+
+    PUU_PS = 0x5,
+    LUXC1 = 0x5,
+
+    CVT_PS_S = 0x6,
+    SUXC1 = 0x6,
+    ADDR_PS = 0x6,
+    PREFX = 0x6,
+
+    MULR_PS = 0x7,
+
+    MADD_S = 0x01,
+    MADD_D = 0x09,
+    MADD_PS = 0x11,
+    ALNV_PS = 0x19,
+    MSUB_S = 0x21,
+    MSUB_D = 0x29,
+    MSUB_PS = 0x31,
+
+    NMADD_S = 0x02,
+    NMADD_D = 0x0a,
+    NMADD_PS = 0x12,
+    NMSUB_S = 0x22,
+    NMSUB_D = 0x2a,
+    NMSUB_PS = 0x32,
+
+    POOL32FXF = 0x3b,
+
+    CABS_COND_FMT = 0x1c,              /* MIPS3D */
+    C_COND_FMT = 0x3c
+};
+
+/* POOL32Fxf encoding of minor opcode extension field */
+
+enum {
+    CVT_L = 0x04,
+    RSQRT_FMT = 0x08,
+    FLOOR_L = 0x0c,
+    CVT_PW_PS = 0x1c,
+    CVT_W = 0x24,
+    SQRT_FMT = 0x28,
+    FLOOR_W = 0x2c,
+    CVT_PS_PW = 0x3c,
+    CFC1 = 0x40,
+    RECIP_FMT = 0x48,
+    CEIL_L = 0x4c,
+    CTC1 = 0x60,
+    CEIL_W = 0x6c,
+    MFC1 = 0x80,
+    CVT_S_PL = 0x84,
+    TRUNC_L = 0x8c,
+    MTC1 = 0xa0,
+    CVT_S_PU = 0xa4,
+    TRUNC_W = 0xac,
+    MFHC1 = 0xc0,
+    ROUND_L = 0xcc,
+    MTHC1 = 0xe0,
+    ROUND_W = 0xec,
+
+    MOV_FMT = 0x01,
+    MOVF = 0x05,
+    ABS_FMT = 0x0d,
+    RSQRT1_FMT = 0x1d,
+    MOVT = 0x25,
+    NEG_FMT = 0x2d,
+    CVT_D = 0x4d,
+    RECIP1_FMT = 0x5d,
+    CVT_S = 0x6d
+};
+
+/* POOL32I encoding of minor opcode field (bits 25..21) */
+
+enum {
+    BLTZ = 0x00,
+    BLTZAL = 0x01,
+    BGEZ = 0x02,
+    BGEZAL = 0x03,
+    BLEZ = 0x04,
+    BNEZC = 0x05,
+    BGTZ = 0x06,
+    BEQZC = 0x07,
+    TLTI = 0x08,
+    TGEI = 0x09,
+    TLTIU = 0x0a,
+    TGEIU = 0x0b,
+    TNEI = 0x0c,
+    LUI = 0x0d,
+    TEQI = 0x0e,
+    SYNCI = 0x10,
+    BLTZALS = 0x11,
+    BGEZALS = 0x13,
+    BC2F = 0x14,
+    BC2T = 0x15,
+    BPOSGE64 = 0x1a,
+    BPOSGE32 = 0x1b,
+    /* These overlap and are distinguished by bit16 of the instruction */
+    BC1F = 0x1c,
+    BC1T = 0x1d,
+    BC1ANY2F = 0x1c,
+    BC1ANY2T = 0x1d,
+    BC1ANY4F = 0x1e,
+    BC1ANY4T = 0x1f
+};
+
+/* POOL16A encoding of minor opcode field */
+
+enum {
+    ADDU16 = 0x0,
+    SUBU16 = 0x1
+};
+
+/* POOL16B encoding of minor opcode field */
+
+enum {
+    SLL16 = 0x0,
+    SRL16 = 0x1
+};
+
+/* POOL16C encoding of minor opcode field */
+
+enum {
+    NOT16 = 0x00,
+    XOR16 = 0x04,
+    AND16 = 0x08,
+    OR16 = 0x0c,
+    LWM16 = 0x10,
+    SWM16 = 0x14,
+    JR16 = 0x18,
+    JRC16 = 0x1a,
+    JALR16 = 0x1c,
+    JALR16S = 0x1e,
+    MFHI16 = 0x20,
+    MFLO16 = 0x24,
+    BREAK16 = 0x28,
+    SDBBP16 = 0x2c,
+    JRADDIUSP = 0x30
+};
+
+/* POOL16D encoding of minor opcode field */
+
+enum {
+    ADDIUS5 = 0x0,
+    ADDIUSP = 0x1
+};
+
+/* POOL16E encoding of minor opcode field */
+
+enum {
+    ADDIUR2 = 0x0,
+    ADDIUR1SP = 0x1
+};
+
+static int mmreg (int r)
+{
+    static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+
+    return map[r];
+}
+
+/* Used for 16-bit store instructions.  */
+static int mmreg2 (int r)
+{
+    static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
+
+    return map[r];
+}
+
+#define uMIPS_RD(op) ((op >> 7) & 0x7)
+#define uMIPS_RS(op) ((op >> 4) & 0x7)
+#define uMIPS_RS2(op) uMIPS_RS(op)
+#define uMIPS_RS1(op) ((op >> 1) & 0x7)
+#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
+#define uMIPS_RS5(op) (op & 0x1f)
+
+/* Signed immediate */
+#define SIMM(op, start, width)                                          \
+    ((int32_t)(((op >> start) & ((~0U) >> (32-width)))                 \
+               << (32-width))                                           \
+     >> (32-width))
+/* Zero-extended immediate */
+#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
+
+static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
+{
+    int rd = mmreg(uMIPS_RD(ctx->opcode));
+
+    gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
+}
+
+static void gen_addiur2 (CPUState *env, DisasContext *ctx)
+{
+    static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
+    int rd = mmreg(uMIPS_RD(ctx->opcode));
+    int rs = mmreg(uMIPS_RS(ctx->opcode));
+
+    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
+}
+
+static void gen_addiusp (CPUState *env, DisasContext *ctx)
+{
+    int encoded = ZIMM(ctx->opcode, 1, 9);
+    int decoded;
+
+    if (encoded <= 1) {
+        decoded = 256 + encoded;
+    } else if (encoded <= 255) {
+        decoded = encoded;
+    } else if (encoded <= 509) {
+        decoded = encoded - 512;
+    } else {
+        decoded = encoded - 768;
+    }
+
+    gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
+}
+
+static void gen_addius5 (CPUState *env, DisasContext *ctx)
+{
+    int imm = SIMM(ctx->opcode, 1, 4);
+    int rd = (ctx->opcode >> 5) & 0x1f;
+
+    gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
+}
+
+static void gen_andi16 (CPUState *env, DisasContext *ctx)
+{
+    static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
+                                 31, 32, 63, 64, 255, 32768, 65535 };
+    int rd = mmreg(uMIPS_RD(ctx->opcode));
+    int rs = mmreg(uMIPS_RS(ctx->opcode));
+    int encoded = ZIMM(ctx->opcode, 0, 4);
+
+    gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
+}
+
+static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
+                               int base, int16_t offset)
+{
+    TCGv t0, t1;
+    TCGv_i32 t2;
+
+    if (ctx->hflags & MIPS_HFLAG_BMASK) {
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+
+    t0 = tcg_temp_new();
+
+    gen_base_offset_addr(ctx, t0, base, offset);
+
+    t1 = tcg_const_tl(reglist);
+    t2 = tcg_const_i32(ctx->mem_idx);
+
+    save_cpu_state(ctx, 1);
+    switch (opc) {
+    case LWM32:
+        gen_helper_lwm(t0, t1, t2);
+        break;
+    case SWM32:
+        gen_helper_swm(t0, t1, t2);
+        break;
+#ifdef TARGET_MIPS64
+    case LDM:
+        gen_helper_ldm(t0, t1, t2);
+        break;
+    case SDM:
+        gen_helper_sdm(t0, t1, t2);
+        break;
+#endif
+    }
+    MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
+    tcg_temp_free(t0);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+}
+
+
+static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
+{
+    int rd = mmreg((ctx->opcode >> 3) & 0x7);
+    int rs = mmreg(ctx->opcode & 0x7);
+    int opc;
+
+    switch (((ctx->opcode) >> 4) & 0x3f) {
+    case NOT16 + 0:
+    case NOT16 + 1:
+    case NOT16 + 2:
+    case NOT16 + 3:
+        gen_logic(env, OPC_NOR, rd, rs, 0);
+        break;
+    case XOR16 + 0:
+    case XOR16 + 1:
+    case XOR16 + 2:
+    case XOR16 + 3:
+        gen_logic(env, OPC_XOR, rd, rd, rs);
+        break;
+    case AND16 + 0:
+    case AND16 + 1:
+    case AND16 + 2:
+    case AND16 + 3:
+        gen_logic(env, OPC_AND, rd, rd, rs);
+        break;
+    case OR16 + 0:
+    case OR16 + 1:
+    case OR16 + 2:
+    case OR16 + 3:
+        gen_logic(env, OPC_OR, rd, rd, rs);
+        break;
+    case LWM16 + 0:
+    case LWM16 + 1:
+    case LWM16 + 2:
+    case LWM16 + 3:
+        {
+            static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
+            int offset = ZIMM(ctx->opcode, 0, 4);
+
+            gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
+                              29, offset << 2);
+        }
+        break;
+    case SWM16 + 0:
+    case SWM16 + 1:
+    case SWM16 + 2:
+    case SWM16 + 3:
+        {
+            static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
+            int offset = ZIMM(ctx->opcode, 0, 4);
+
+            gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
+                              29, offset << 2);
+        }
+        break;
+    case JR16 + 0:
+    case JR16 + 1:
+        {
+            int reg = ctx->opcode & 0x1f;
+
+            gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
+        }
+        *is_branch = 1;
+        break;
+    case JRC16 + 0:
+    case JRC16 + 1:
+        {
+            int reg = ctx->opcode & 0x1f;
+
+            gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
+            /* Let normal delay slot handling in our caller take us
+               to the branch target.  */
+        }
+        break;
+    case JALR16 + 0:
+    case JALR16 + 1:
+        opc = OPC_JALR;
+        goto do_jalr;
+    case JALR16S + 0:
+    case JALR16S + 1:
+        opc = OPC_JALRS;
+    do_jalr:
+        {
+            int reg = ctx->opcode & 0x1f;
+
+            gen_compute_branch(ctx, opc, 2, reg, 31, 0);
+        }
+        *is_branch = 1;
+        break;
+    case MFHI16 + 0:
+    case MFHI16 + 1:
+        gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
+        break;
+    case MFLO16 + 0:
+    case MFLO16 + 1:
+        gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
+        break;
+    case BREAK16:
+        generate_exception(ctx, EXCP_BREAK);
+        break;
+    case SDBBP16:
+        /* XXX: not clear which exception should be raised
+         *      when in debug mode...
+         */
+        check_insn(env, ctx, ISA_MIPS32);
+        if (!(ctx->hflags & MIPS_HFLAG_DM)) {
+            generate_exception(ctx, EXCP_DBp);
+        } else {
+            generate_exception(ctx, EXCP_DBp);
+        }
+        break;
+    case JRADDIUSP + 0:
+    case JRADDIUSP + 1:
+        {
+            int imm = ZIMM(ctx->opcode, 0, 5);
+
+            gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
+            gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
+            /* Let normal delay slot handling in our caller take us
+               to the branch target.  */
+        }
+        break;
+    default:
+        generate_exception(ctx, EXCP_RI);
+        break;
+    }
+}
+
+static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
+{
+    TCGv t0 = tcg_temp_new();
+    TCGv t1 = tcg_temp_new();
+
+    gen_load_gpr(t0, base);
+
+    if (index != 0) {
+        gen_load_gpr(t1, index);
+        tcg_gen_shli_tl(t1, t1, 2);
+        gen_op_addr_add(ctx, t0, t1, t0);
+    }
+
+    save_cpu_state(ctx, 0);
+    op_ldst_lw(t1, t0, ctx);
+    gen_store_gpr(t1, rd);
+
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
+                           int base, int16_t offset)
+{
+    const char *opn = "ldst_pair";
+    TCGv t0, t1;
+
+    if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+
+    t0 = tcg_temp_new();
+    t1 = tcg_temp_new();
+
+    gen_base_offset_addr(ctx, t0, base, offset);
+
+    switch (opc) {
+    case LWP:
+        save_cpu_state(ctx, 0);
+        op_ldst_lw(t1, t0, ctx);
+        gen_store_gpr(t1, rd);
+        tcg_gen_movi_tl(t1, 4);
+        gen_op_addr_add(ctx, t0, t0, t1);
+        op_ldst_lw(t1, t0, ctx);
+        gen_store_gpr(t1, rd+1);
+        opn = "lwp";
+        break;
+    case SWP:
+        save_cpu_state(ctx, 1);
+        gen_load_gpr(t1, rd);
+        op_ldst_sw(t1, t0, ctx);
+        tcg_gen_movi_tl(t1, 4);
+        gen_op_addr_add(ctx, t0, t0, t1);
+        gen_load_gpr(t1, rd+1);
+        op_ldst_sw(t1, t0, ctx);
+        opn = "swp";
+        break;
+#ifdef TARGET_MIPS64
+    case LDP:
+        save_cpu_state(ctx, 0);
+        op_ldst_ld(t1, t0, ctx);
+        gen_store_gpr(t1, rd);
+        tcg_gen_movi_tl(t1, 8);
+        gen_op_addr_add(ctx, t0, t0, t1);
+        op_ldst_ld(t1, t0, ctx);
+        gen_store_gpr(t1, rd+1);
+        opn = "ldp";
+        break;
+    case SDP:
+        save_cpu_state(ctx, 1);
+        gen_load_gpr(t1, rd);
+        op_ldst_sd(t1, t0, ctx);
+        tcg_gen_movi_tl(t1, 8);
+        gen_op_addr_add(ctx, t0, t0, t1);
+        gen_load_gpr(t1, rd+1);
+        op_ldst_sd(t1, t0, ctx);
+        opn = "sdp";
+        break;
+#endif
+    }
+    MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
+    tcg_temp_free(t0);
+    tcg_temp_free(t1);
+}
+
+static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
+                           int *is_branch)
+{
+    int extension = (ctx->opcode >> 6) & 0x3f;
+    int minor = (ctx->opcode >> 12) & 0xf;
+    uint32_t mips32_op;
+
+    switch (extension) {
+    case TEQ:
+        mips32_op = OPC_TEQ;
+        goto do_trap;
+    case TGE:
+        mips32_op = OPC_TGE;
+        goto do_trap;
+    case TGEU:
+        mips32_op = OPC_TGEU;
+        goto do_trap;
+    case TLT:
+        mips32_op = OPC_TLT;
+        goto do_trap;
+    case TLTU:
+        mips32_op = OPC_TLTU;
+        goto do_trap;
+    case TNE:
+        mips32_op = OPC_TNE;
+    do_trap:
+        gen_trap(ctx, mips32_op, rs, rt, -1);
+        break;
+#ifndef CONFIG_USER_ONLY
+    case MFC0:
+    case MFC0 + 32:
+        if (rt == 0) {
+            /* Treat as NOP. */
+            break;
+        }
+        gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
+        break;
+    case MTC0:
+    case MTC0 + 32:
+        {
+            TCGv t0 = tcg_temp_new();
+
+            gen_load_gpr(t0, rt);
+            gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
+            tcg_temp_free(t0);
+        }
+        break;
+#endif
+    case 0x2c:
+        switch (minor) {
+        case SEB:
+            gen_bshfl(ctx, OPC_SEB, rs, rt);
+            break;
+        case SEH:
+            gen_bshfl(ctx, OPC_SEH, rs, rt);
+            break;
+        case CLO:
+            mips32_op = OPC_CLO;
+            goto do_cl;
+        case CLZ:
+            mips32_op = OPC_CLZ;
+        do_cl:
+            check_insn(env, ctx, ISA_MIPS32);
+            gen_cl(ctx, mips32_op, rt, rs);
+            break;
+        case RDHWR:
+            gen_rdhwr(env, ctx, rt, rs);
+            break;
+        case WSBH:
+            gen_bshfl(ctx, OPC_WSBH, rs, rt);
+            break;
+        case MULT:
+            mips32_op = OPC_MULT;
+            goto do_muldiv;
+        case MULTU:
+            mips32_op = OPC_MULTU;
+            goto do_muldiv;
+        case DIV:
+            mips32_op = OPC_DIV;
+            goto do_muldiv;
+        case DIVU:
+            mips32_op = OPC_DIVU;
+            goto do_muldiv;
+        case MADD:
+            mips32_op = OPC_MADD;
+            goto do_muldiv;
+        case MADDU:
+            mips32_op = OPC_MADDU;
+            goto do_muldiv;
+        case MSUB:
+            mips32_op = OPC_MSUB;
+            goto do_muldiv;
+        case MSUBU:
+            mips32_op = OPC_MSUBU;
+        do_muldiv:
+            check_insn(env, ctx, ISA_MIPS32);
+            gen_muldiv(ctx, mips32_op, rs, rt);
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    case 0x34:
+        switch (minor) {
+        case MFC2:
+        case MTC2:
+        case MFHC2:
+        case MTHC2:
+        case CFC2:
+        case CTC2:
+            generate_exception_err(ctx, EXCP_CpU, 2);
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    case 0x3c:
+        switch (minor) {
+        case JALR:
+        case JALR_HB:
+            gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
+            *is_branch = 1;
+            break;
+        case JALRS:
+        case JALRS_HB:
+            gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
+            *is_branch = 1;
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    case 0x05:
+        switch (minor) {
+        case RDPGPR:
+            check_insn(env, ctx, ISA_MIPS32R2);
+            gen_load_srsgpr(rt, rs);
+            break;
+        case WRPGPR:
+            check_insn(env, ctx, ISA_MIPS32R2);
+            gen_store_srsgpr(rt, rs);
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+#ifndef CONFIG_USER_ONLY
+    case 0x0d:
+        switch (minor) {
+        case TLBP:
+            mips32_op = OPC_TLBP;
+            goto do_cp0;
+        case TLBR:
+            mips32_op = OPC_TLBR;
+            goto do_cp0;
+        case TLBWI:
+            mips32_op = OPC_TLBWI;
+            goto do_cp0;
+        case TLBWR:
+            mips32_op = OPC_TLBWR;
+            goto do_cp0;
+        case WAIT:
+            mips32_op = OPC_WAIT;
+            goto do_cp0;
+        case DERET:
+            mips32_op = OPC_DERET;
+            goto do_cp0;
+        case ERET:
+            mips32_op = OPC_ERET;
+        do_cp0:
+            gen_cp0(env, ctx, mips32_op, rt, rs);
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    case 0x1d:
+        switch (minor) {
+        case DI:
+            {
+                TCGv t0 = tcg_temp_new();
+
+                save_cpu_state(ctx, 1);
+                gen_helper_di(t0);
+                gen_store_gpr(t0, rs);
+                /* Stop translation as we may have switched the execution mode */
+                ctx->bstate = BS_STOP;
+                tcg_temp_free(t0);
+            }
+            break;
+        case EI:
+            {
+                TCGv t0 = tcg_temp_new();
+
+                save_cpu_state(ctx, 1);
+                gen_helper_ei(t0);
+                gen_store_gpr(t0, rs);
+                /* Stop translation as we may have switched the execution mode */
+                ctx->bstate = BS_STOP;
+                tcg_temp_free(t0);
+            }
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+#endif
+    case 0x2d:
+        switch (minor) {
+        case SYNC:
+            /* NOP */
+            break;
+        case SYSCALL:
+            generate_exception(ctx, EXCP_SYSCALL);
+            ctx->bstate = BS_STOP;
+            break;
+        case SDBBP:
+            check_insn(env, ctx, ISA_MIPS32);
+            if (!(ctx->hflags & MIPS_HFLAG_DM)) {
+                generate_exception(ctx, EXCP_DBp);
+            } else {
+                generate_exception(ctx, EXCP_DBp);
+            }
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    case 0x35:
+        switch (minor) {
+        case MFHI32:
+            gen_HILO(ctx, OPC_MFHI, rs);
+            break;
+        case MFLO32:
+            gen_HILO(ctx, OPC_MFLO, rs);
+            break;
+        case MTHI32:
+            gen_HILO(ctx, OPC_MTHI, rs);
+            break;
+        case MTLO32:
+            gen_HILO(ctx, OPC_MTLO, rs);
+            break;
+        default:
+            goto pool32axf_invalid;
+        }
+        break;
+    default:
+    pool32axf_invalid:
+        MIPS_INVAL("pool32axf");
+        generate_exception(ctx, EXCP_RI);
+        break;
+    }
+}
+
+/* Values for microMIPS fmt field.  Variable-width, depending on which
+   formats the instruction supports.  */
+
+enum {
+    FMT_SD_S = 0,
+    FMT_SD_D = 1,
+
+    FMT_SDPS_S = 0,
+    FMT_SDPS_D = 1,
+    FMT_SDPS_PS = 2,
+
+    FMT_SWL_S = 0,
+    FMT_SWL_W = 1,
+    FMT_SWL_L = 2,
+
+    FMT_DWL_D = 0,
+    FMT_DWL_W = 1,
+    FMT_DWL_L = 2
+};
+
+static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
+{
+    int extension = (ctx->opcode >> 6) & 0x3ff;
+    uint32_t mips32_op;
+
+#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
+#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
+#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
+
+    switch (extension) {
+    case FLOAT_1BIT_FMT(CFC1, 0):
+        mips32_op = OPC_CFC1;
+        goto do_cp1;
+    case FLOAT_1BIT_FMT(CTC1, 0):
+        mips32_op = OPC_CTC1;
+        goto do_cp1;
+    case FLOAT_1BIT_FMT(MFC1, 0):
+        mips32_op = OPC_MFC1;
+        goto do_cp1;
+    case FLOAT_1BIT_FMT(MTC1, 0):
+        mips32_op = OPC_MTC1;
+        goto do_cp1;
+    case FLOAT_1BIT_FMT(MFHC1, 0):
+        mips32_op = OPC_MFHC1;
+        goto do_cp1;
+    case FLOAT_1BIT_FMT(MTHC1, 0):
+        mips32_op = OPC_MTHC1;
+    do_cp1:
+        gen_cp1(ctx, mips32_op, rt, rs);
+        break;
+
+        /* Reciprocal square root */
+    case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
+        mips32_op = OPC_RSQRT_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
+        mips32_op = OPC_RSQRT_D;
+        goto do_unaryfp;
+
+        /* Square root */
+    case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
+        mips32_op = OPC_SQRT_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
+        mips32_op = OPC_SQRT_D;
+        goto do_unaryfp;
+
+        /* Reciprocal */
+    case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
+        mips32_op = OPC_RECIP_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
+        mips32_op = OPC_RECIP_D;
+        goto do_unaryfp;
+
+        /* Floor */
+    case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
+        mips32_op = OPC_FLOOR_L_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
+        mips32_op = OPC_FLOOR_L_D;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
+        mips32_op = OPC_FLOOR_W_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
+        mips32_op = OPC_FLOOR_W_D;
+        goto do_unaryfp;
+
+        /* Ceiling */
+    case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
+        mips32_op = OPC_CEIL_L_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
+        mips32_op = OPC_CEIL_L_D;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
+        mips32_op = OPC_CEIL_W_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
+        mips32_op = OPC_CEIL_W_D;
+        goto do_unaryfp;
+
+        /* Truncation */
+    case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
+        mips32_op = OPC_TRUNC_L_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
+        mips32_op = OPC_TRUNC_L_D;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
+        mips32_op = OPC_TRUNC_W_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
+        mips32_op = OPC_TRUNC_W_D;
+        goto do_unaryfp;
+
+        /* Round */
+    case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
+        mips32_op = OPC_ROUND_L_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
+        mips32_op = OPC_ROUND_L_D;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
+        mips32_op = OPC_ROUND_W_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
+        mips32_op = OPC_ROUND_W_D;
+        goto do_unaryfp;
+
+        /* Integer to floating-point conversion */
+    case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
+        mips32_op = OPC_CVT_L_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
+        mips32_op = OPC_CVT_L_D;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
+        mips32_op = OPC_CVT_W_S;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
+        mips32_op = OPC_CVT_W_D;
+        goto do_unaryfp;
+
+        /* Paired-foo conversions */
+    case FLOAT_1BIT_FMT(CVT_S_PL, 0):
+        mips32_op = OPC_CVT_S_PL;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_S_PU, 0):
+        mips32_op = OPC_CVT_S_PU;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
+        mips32_op = OPC_CVT_PW_PS;
+        goto do_unaryfp;
+    case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
+        mips32_op = OPC_CVT_PS_PW;
+        goto do_unaryfp;
+
+        /* Floating-point moves */
+    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
+        mips32_op = OPC_MOV_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
+        mips32_op = OPC_MOV_D;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
+        mips32_op = OPC_MOV_PS;
+        goto do_unaryfp;
+
+        /* Absolute value */
+    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
+        mips32_op = OPC_ABS_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
+        mips32_op = OPC_ABS_D;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
+        mips32_op = OPC_ABS_PS;
+        goto do_unaryfp;
+
+        /* Negation */
+    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
+        mips32_op = OPC_NEG_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
+        mips32_op = OPC_NEG_D;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
+        mips32_op = OPC_NEG_PS;
+        goto do_unaryfp;
+
+        /* Reciprocal square root step */
+    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
+        mips32_op = OPC_RSQRT1_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
+        mips32_op = OPC_RSQRT1_D;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
+        mips32_op = OPC_RSQRT1_PS;
+        goto do_unaryfp;
+
+        /* Reciprocal step */
+    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
+        mips32_op = OPC_RECIP1_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
+        mips32_op = OPC_RECIP1_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
+        mips32_op = OPC_RECIP1_PS;
+        goto do_unaryfp;
+
+        /* Conversions from double */
+    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
+        mips32_op = OPC_CVT_D_S;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
+        mips32_op = OPC_CVT_D_W;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
+        mips32_op = OPC_CVT_D_L;
+        goto do_unaryfp;
+
+        /* Conversions from single */
+    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
+        mips32_op = OPC_CVT_S_D;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
+        mips32_op = OPC_CVT_S_W;
+        goto do_unaryfp;
+    case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
+        mips32_op = OPC_CVT_S_L;
+    do_unaryfp:
+        gen_farith(ctx, mips32_op, -1, rs, rt, 0);
+        break;
+
+        /* Conditional moves on floating-point codes */
+    case COND_FLOAT_MOV(MOVT, 0):
+    case COND_FLOAT_MOV(MOVT, 1):
+    case COND_FLOAT_MOV(MOVT, 2):
+    case COND_FLOAT_MOV(MOVT, 3):
+    case COND_FLOAT_MOV(MOVT, 4):
+    case COND_FLOAT_MOV(MOVT, 5):
+    case COND_FLOAT_MOV(MOVT, 6):
+    case COND_FLOAT_MOV(MOVT, 7):
+        gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
+        break;
+    case COND_FLOAT_MOV(MOVF, 0):
+    case COND_FLOAT_MOV(MOVF, 1):
+    case COND_FLOAT_MOV(MOVF, 2):
+    case COND_FLOAT_MOV(MOVF, 3):
+    case COND_FLOAT_MOV(MOVF, 4):
+    case COND_FLOAT_MOV(MOVF, 5):
+    case COND_FLOAT_MOV(MOVF, 6):
+    case COND_FLOAT_MOV(MOVF, 7):
+        gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
+        break;
+    default:
+        MIPS_INVAL("pool32fxf");
+        generate_exception(ctx, EXCP_RI);
+        break;
+    }
+}
+
+static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
+                                    uint16_t insn_hw1, int *is_branch)
+{
+    int32_t offset;
+    uint16_t insn;
+    int rt, rs, rd, rr;
+    int16_t imm;
+    uint32_t op, minor, mips32_op;
+    uint32_t cond, fmt, cc;
+
+    insn = lduw_code(ctx->pc + 2);
+    ctx->opcode = (ctx->opcode << 16) | insn;
+
+    rt = (ctx->opcode >> 21) & 0x1f;
+    rs = (ctx->opcode >> 16) & 0x1f;
+    rd = (ctx->opcode >> 11) & 0x1f;
+    rr = (ctx->opcode >> 6) & 0x1f;
+    imm = (int16_t) ctx->opcode;
+
+    op = (ctx->opcode >> 26) & 0x3f;
+    switch (op) {
+    case POOL32A:
+        minor = ctx->opcode & 0x3f;
+        switch (minor) {
+        case 0x00:
+            minor = (ctx->opcode >> 6) & 0xf;
+            switch (minor) {
+            case SLL32:
+                mips32_op = OPC_SLL;
+                goto do_shifti;
+            case SRA:
+                mips32_op = OPC_SRA;
+                goto do_shifti;
+            case SRL32:
+                mips32_op = OPC_SRL;
+                goto do_shifti;
+            case ROTR:
+                mips32_op = OPC_ROTR;
+            do_shifti:
+                gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
+                break;
+            default:
+                goto pool32a_invalid;
+            }
+            break;
+        case 0x10:
+            minor = (ctx->opcode >> 6) & 0xf;
+            switch (minor) {
+                /* Arithmetic */
+            case ADD:
+                mips32_op = OPC_ADD;
+                goto do_arith;
+            case ADDU32:
+                mips32_op = OPC_ADDU;
+                goto do_arith;
+            case SUB:
+                mips32_op = OPC_SUB;
+                goto do_arith;
+            case SUBU32:
+                mips32_op = OPC_SUBU;
+                goto do_arith;
+            case MUL:
+                mips32_op = OPC_MUL;
+            do_arith:
+                gen_arith(env, ctx, mips32_op, rd, rs, rt);
+                break;
+                /* Shifts */
+            case SLLV:
+                mips32_op = OPC_SLLV;
+                goto do_shift;
+            case SRLV:
+                mips32_op = OPC_SRLV;
+                goto do_shift;
+            case SRAV:
+                mips32_op = OPC_SRAV;
+                goto do_shift;
+            case ROTRV:
+                mips32_op = OPC_ROTRV;
+            do_shift:
+                gen_shift(env, ctx, mips32_op, rd, rs, rt);
+                break;
+                /* Logical operations */
+            case AND:
+                mips32_op = OPC_AND;
+                goto do_logic;
+            case OR32:
+                mips32_op = OPC_OR;
+                goto do_logic;
+            case NOR:
+                mips32_op = OPC_NOR;
+                goto do_logic;
+            case XOR32:
+                mips32_op = OPC_XOR;
+            do_logic:
+                gen_logic(env, mips32_op, rd, rs, rt);
+                break;
+                /* Set less than */
+            case SLT:
+                mips32_op = OPC_SLT;
+                goto do_slt;
+            case SLTU:
+                mips32_op = OPC_SLTU;
+            do_slt:
+                gen_slt(env, mips32_op, rd, rs, rt);
+                break;
+            default:
+                goto pool32a_invalid;
+            }
+            break;
+        case 0x18:
+            minor = (ctx->opcode >> 6) & 0xf;
+            switch (minor) {
+                /* Conditional moves */
+            case MOVN:
+                mips32_op = OPC_MOVN;
+                goto do_cmov;
+            case MOVZ:
+                mips32_op = OPC_MOVZ;
+            do_cmov:
+                gen_cond_move(env, mips32_op, rd, rs, rt);
+                break;
+            case LWXS:
+                gen_ldxs(ctx, rs, rt, rd);
+                break;
+            default:
+                goto pool32a_invalid;
+            }
+            break;
+        case INS:
+            gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
+            return;
+        case EXT:
+            gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
+            return;
+        case POOL32AXF:
+            gen_pool32axf(env, ctx, rt, rs, is_branch);
+            break;
+        case 0x07:
+            generate_exception(ctx, EXCP_BREAK);
+            break;
+        default:
+        pool32a_invalid:
+                MIPS_INVAL("pool32a");
+                generate_exception(ctx, EXCP_RI);
+                break;
+        }
+        break;
+    case POOL32B:
+        minor = (ctx->opcode >> 12) & 0xf;
+        switch (minor) {
+        case CACHE:
+            /* Treat as no-op. */
+            break;
+        case LWC2:
+        case SWC2:
+            /* COP2: Not implemented. */
+            generate_exception_err(ctx, EXCP_CpU, 2);
+            break;
+        case LWP:
+        case SWP:
+#ifdef TARGET_MIPS64
+        case LDP:
+        case SDP:
+#endif
+            gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+        case LWM32:
+        case SWM32:
+#ifdef TARGET_MIPS64
+        case LDM:
+        case SDM:
+#endif
+            gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+        default:
+            MIPS_INVAL("pool32b");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case POOL32F:
+        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+            minor = ctx->opcode & 0x3f;
+            check_cp1_enabled(ctx);
+            switch (minor) {
+            case ALNV_PS:
+                mips32_op = OPC_ALNV_PS;
+                goto do_madd;
+            case MADD_S:
+                mips32_op = OPC_MADD_S;
+                goto do_madd;
+            case MADD_D:
+                mips32_op = OPC_MADD_D;
+                goto do_madd;
+            case MADD_PS:
+                mips32_op = OPC_MADD_PS;
+                goto do_madd;
+            case MSUB_S:
+                mips32_op = OPC_MSUB_S;
+                goto do_madd;
+            case MSUB_D:
+                mips32_op = OPC_MSUB_D;
+                goto do_madd;
+            case MSUB_PS:
+                mips32_op = OPC_MSUB_PS;
+                goto do_madd;
+            case NMADD_S:
+                mips32_op = OPC_NMADD_S;
+                goto do_madd;
+            case NMADD_D:
+                mips32_op = OPC_NMADD_D;
+                goto do_madd;
+            case NMADD_PS:
+                mips32_op = OPC_NMADD_PS;
+                goto do_madd;
+            case NMSUB_S:
+                mips32_op = OPC_NMSUB_S;
+                goto do_madd;
+            case NMSUB_D:
+                mips32_op = OPC_NMSUB_D;
+                goto do_madd;
+            case NMSUB_PS:
+                mips32_op = OPC_NMSUB_PS;
+            do_madd:
+                gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
+                break;
+            case CABS_COND_FMT:
+                cond = (ctx->opcode >> 6) & 0xf;
+                cc = (ctx->opcode >> 13) & 0x7;
+                fmt = (ctx->opcode >> 10) & 0x3;
+                switch (fmt) {
+                case 0x0:
+                    gen_cmpabs_s(ctx, cond, rt, rs, cc);
+                    break;
+                case 0x1:
+                    gen_cmpabs_d(ctx, cond, rt, rs, cc);
+                    break;
+                case 0x2:
+                    gen_cmpabs_ps(ctx, cond, rt, rs, cc);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case C_COND_FMT:
+                cond = (ctx->opcode >> 6) & 0xf;
+                cc = (ctx->opcode >> 13) & 0x7;
+                fmt = (ctx->opcode >> 10) & 0x3;
+                switch (fmt) {
+                case 0x0:
+                    gen_cmp_s(ctx, cond, rt, rs, cc);
+                    break;
+                case 0x1:
+                    gen_cmp_d(ctx, cond, rt, rs, cc);
+                    break;
+                case 0x2:
+                    gen_cmp_ps(ctx, cond, rt, rs, cc);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case POOL32FXF:
+                gen_pool32fxf(env, ctx, rt, rs);
+                break;
+            case 0x00:
+                /* PLL foo */
+                switch ((ctx->opcode >> 6) & 0x7) {
+                case PLL_PS:
+                    mips32_op = OPC_PLL_PS;
+                    goto do_ps;
+                case PLU_PS:
+                    mips32_op = OPC_PLU_PS;
+                    goto do_ps;
+                case PUL_PS:
+                    mips32_op = OPC_PUL_PS;
+                    goto do_ps;
+                case PUU_PS:
+                    mips32_op = OPC_PUU_PS;
+                    goto do_ps;
+                case CVT_PS_S:
+                    mips32_op = OPC_CVT_PS_S;
+                do_ps:
+                    gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case 0x08:
+                /* [LS][WDU]XC1 */
+                switch ((ctx->opcode >> 6) & 0x7) {
+                case LWXC1:
+                    mips32_op = OPC_LWXC1;
+                    goto do_ldst_cp1;
+                case SWXC1:
+                    mips32_op = OPC_SWXC1;
+                    goto do_ldst_cp1;
+                case LDXC1:
+                    mips32_op = OPC_LDXC1;
+                    goto do_ldst_cp1;
+                case SDXC1:
+                    mips32_op = OPC_SDXC1;
+                    goto do_ldst_cp1;
+                case LUXC1:
+                    mips32_op = OPC_LUXC1;
+                    goto do_ldst_cp1;
+                case SUXC1:
+                    mips32_op = OPC_SUXC1;
+                do_ldst_cp1:
+                    gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case 0x18:
+                /* 3D insns */
+                fmt = (ctx->opcode >> 9) & 0x3;
+                switch ((ctx->opcode >> 6) & 0x7) {
+                case RSQRT2_FMT:
+                    switch (fmt) {
+                    case FMT_SDPS_S:
+                        mips32_op = OPC_RSQRT2_S;
+                        goto do_3d;
+                    case FMT_SDPS_D:
+                        mips32_op = OPC_RSQRT2_D;
+                        goto do_3d;
+                    case FMT_SDPS_PS:
+                        mips32_op = OPC_RSQRT2_PS;
+                        goto do_3d;
+                    default:
+                        goto pool32f_invalid;
+                    }
+                    break;
+                case RECIP2_FMT:
+                    switch (fmt) {
+                    case FMT_SDPS_S:
+                        mips32_op = OPC_RECIP2_S;
+                        goto do_3d;
+                    case FMT_SDPS_D:
+                        mips32_op = OPC_RECIP2_D;
+                        goto do_3d;
+                    case FMT_SDPS_PS:
+                        mips32_op = OPC_RECIP2_PS;
+                        goto do_3d;
+                    default:
+                        goto pool32f_invalid;
+                    }
+                    break;
+                case ADDR_PS:
+                    mips32_op = OPC_ADDR_PS;
+                    goto do_3d;
+                case MULR_PS:
+                    mips32_op = OPC_MULR_PS;
+                do_3d:
+                    gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case 0x20:
+                /* MOV[FT].fmt and PREFX */
+                cc = (ctx->opcode >> 13) & 0x7;
+                fmt = (ctx->opcode >> 9) & 0x3;
+                switch ((ctx->opcode >> 6) & 0x7) {
+                case MOVF_FMT:
+                    switch (fmt) {
+                    case FMT_SDPS_S:
+                        gen_movcf_s(rs, rt, cc, 0);
+                        break;
+                    case FMT_SDPS_D:
+                        gen_movcf_d(ctx, rs, rt, cc, 0);
+                        break;
+                    case FMT_SDPS_PS:
+                        gen_movcf_ps(rs, rt, cc, 0);
+                        break;
+                    default:
+                        goto pool32f_invalid;
+                    }
+                    break;
+                case MOVT_FMT:
+                    switch (fmt) {
+                    case FMT_SDPS_S:
+                        gen_movcf_s(rs, rt, cc, 1);
+                        break;
+                    case FMT_SDPS_D:
+                        gen_movcf_d(ctx, rs, rt, cc, 1);
+                        break;
+                    case FMT_SDPS_PS:
+                        gen_movcf_ps(rs, rt, cc, 1);
+                        break;
+                    default:
+                        goto pool32f_invalid;
+                    }
+                    break;
+                case PREFX:
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+#define FINSN_3ARG_SDPS(prfx)                           \
+                switch ((ctx->opcode >> 8) & 0x3) {     \
+                case FMT_SDPS_S:                        \
+                    mips32_op = OPC_##prfx##_S;         \
+                    goto do_fpop;                       \
+                case FMT_SDPS_D:                        \
+                    mips32_op = OPC_##prfx##_D;         \
+                    goto do_fpop;                       \
+                case FMT_SDPS_PS:                       \
+                    mips32_op = OPC_##prfx##_PS;        \
+                    goto do_fpop;                       \
+                default:                                \
+                    goto pool32f_invalid;               \
+                }
+            case 0x30:
+                /* regular FP ops */
+                switch ((ctx->opcode >> 6) & 0x3) {
+                case ADD_FMT:
+                    FINSN_3ARG_SDPS(ADD);
+                    break;
+                case SUB_FMT:
+                    FINSN_3ARG_SDPS(SUB);
+                    break;
+                case MUL_FMT:
+                    FINSN_3ARG_SDPS(MUL);
+                    break;
+                case DIV_FMT:
+                    fmt = (ctx->opcode >> 8) & 0x3;
+                    if (fmt == 1) {
+                        mips32_op = OPC_DIV_D;
+                    } else if (fmt == 0) {
+                        mips32_op = OPC_DIV_S;
+                    } else {
+                        goto pool32f_invalid;
+                    }
+                    goto do_fpop;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            case 0x38:
+                /* cmovs */
+                switch ((ctx->opcode >> 6) & 0x3) {
+                case MOVN_FMT:
+                    FINSN_3ARG_SDPS(MOVN);
+                    break;
+                case MOVZ_FMT:
+                    FINSN_3ARG_SDPS(MOVZ);
+                    break;
+                default:
+                    goto pool32f_invalid;
+                }
+                break;
+            do_fpop:
+                gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+                break;
+            default:
+            pool32f_invalid:
+                MIPS_INVAL("pool32f");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+        } else {
+            generate_exception_err(ctx, EXCP_CpU, 1);
+        }
+        break;
+    case POOL32I:
+        minor = (ctx->opcode >> 21) & 0x1f;
+        switch (minor) {
+        case BLTZ:
+            mips32_op = OPC_BLTZ;
+            goto do_branch;
+        case BLTZAL:
+            mips32_op = OPC_BLTZAL;
+            goto do_branch;
+        case BLTZALS:
+            mips32_op = OPC_BLTZALS;
+            goto do_branch;
+        case BGEZ:
+            mips32_op = OPC_BGEZ;
+            goto do_branch;
+        case BGEZAL:
+            mips32_op = OPC_BGEZAL;
+            goto do_branch;
+        case BGEZALS:
+            mips32_op = OPC_BGEZALS;
+            goto do_branch;
+        case BLEZ:
+            mips32_op = OPC_BLEZ;
+            goto do_branch;
+        case BGTZ:
+            mips32_op = OPC_BGTZ;
+        do_branch:
+            gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
+            *is_branch = 1;
+            break;
+
+            /* Traps */
+        case TLTI:
+            mips32_op = OPC_TLTI;
+            goto do_trapi;
+        case TGEI:
+            mips32_op = OPC_TGEI;
+            goto do_trapi;
+        case TLTIU:
+            mips32_op = OPC_TLTIU;
+            goto do_trapi;
+        case TGEIU:
+            mips32_op = OPC_TGEIU;
+            goto do_trapi;
+        case TNEI:
+            mips32_op = OPC_TNEI;
+            goto do_trapi;
+        case TEQI:
+            mips32_op = OPC_TEQI;
+        do_trapi:
+            gen_trap(ctx, mips32_op, rs, -1, imm);
+            break;
+
+        case BNEZC:
+        case BEQZC:
+            gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
+                               4, rs, 0, imm << 1);
+            /* Compact branches don't have a delay slot, so just let
+               the normal delay slot handling take us to the branch
+               target. */
+            break;
+        case LUI:
+            gen_logic_imm(env, OPC_LUI, rs, -1, imm);
+            break;
+        case SYNCI:
+            break;
+        case BC2F:
+        case BC2T:
+            /* COP2: Not implemented. */
+            generate_exception_err(ctx, EXCP_CpU, 2);
+            break;
+        case BC1F:
+            mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
+            goto do_cp1branch;
+        case BC1T:
+            mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
+            goto do_cp1branch;
+        case BC1ANY4F:
+            mips32_op = OPC_BC1FANY4;
+            goto do_cp1mips3d;
+        case BC1ANY4T:
+            mips32_op = OPC_BC1TANY4;
+        do_cp1mips3d:
+            check_cop1x(ctx);
+            check_insn(env, ctx, ASE_MIPS3D);
+            /* Fall through */
+        do_cp1branch:
+            gen_compute_branch1(env, ctx, mips32_op,
+                                (ctx->opcode >> 18) & 0x7, imm << 1);
+            *is_branch = 1;
+            break;
+        case BPOSGE64:
+        case BPOSGE32:
+            /* MIPS DSP: not implemented */
+            /* Fall through */
+        default:
+            MIPS_INVAL("pool32i");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case POOL32C:
+        minor = (ctx->opcode >> 12) & 0xf;
+        switch (minor) {
+        case LWL:
+            mips32_op = OPC_LWL;
+            goto do_ldst_lr;
+        case SWL:
+            mips32_op = OPC_SWL;
+            goto do_ldst_lr;
+        case LWR:
+            mips32_op = OPC_LWR;
+            goto do_ldst_lr;
+        case SWR:
+            mips32_op = OPC_SWR;
+            goto do_ldst_lr;
+#if defined(TARGET_MIPS64)
+        case LDL:
+            mips32_op = OPC_LDL;
+            goto do_ldst_lr;
+        case SDL:
+            mips32_op = OPC_SDL;
+            goto do_ldst_lr;
+        case LDR:
+            mips32_op = OPC_LDR;
+            goto do_ldst_lr;
+        case SDR:
+            mips32_op = OPC_SDR;
+            goto do_ldst_lr;
+        case LWU:
+            mips32_op = OPC_LWU;
+            goto do_ldst_lr;
+        case LLD:
+            mips32_op = OPC_LLD;
+            goto do_ldst_lr;
+#endif
+        case LL:
+            mips32_op = OPC_LL;
+        do_ldst_lr:
+            gen_ldst(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+        case SC:
+            gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+#if defined(TARGET_MIPS64)
+        case SCD:
+            gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
+            break;
+#endif
+        case PREF:
+            /* Treat as no-op */
+            break;
+        default:
+            MIPS_INVAL("pool32c");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
+        break;
+    case ADDI32:
+        mips32_op = OPC_ADDI;
+        goto do_addi;
+    case ADDIU32:
+        mips32_op = OPC_ADDIU;
+    do_addi:
+        gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
+        break;
+
+        /* Logical operations */
+    case ORI32:
+        mips32_op = OPC_ORI;
+        goto do_logici;
+    case XORI32:
+        mips32_op = OPC_XORI;
+        goto do_logici;
+    case ANDI32:
+        mips32_op = OPC_ANDI;
+    do_logici:
+        gen_logic_imm(env, mips32_op, rt, rs, imm);
+        break;
+
+        /* Set less than immediate */
+    case SLTI32:
+        mips32_op = OPC_SLTI;
+        goto do_slti;
+    case SLTIU32:
+        mips32_op = OPC_SLTIU;
+    do_slti:
+        gen_slt_imm(env, mips32_op, rt, rs, imm);
+        break;
+    case JALX32:
+        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
+        gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
+        *is_branch = 1;
+        break;
+    case JALS32:
+        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
+        gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
+        *is_branch = 1;
+        break;
+    case BEQ32:
+        gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
+        *is_branch = 1;
+        break;
+    case BNE32:
+        gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
+        *is_branch = 1;
+        break;
+    case J32:
+        gen_compute_branch(ctx, OPC_J, 4, rt, rs,
+                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
+        *is_branch = 1;
+        break;
+    case JAL32:
+        gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
+                           (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
+        *is_branch = 1;
+        break;
+        /* Floating point (COP1) */
+    case LWC132:
+        mips32_op = OPC_LWC1;
+        goto do_cop1;
+    case LDC132:
+        mips32_op = OPC_LDC1;
+        goto do_cop1;
+    case SWC132:
+        mips32_op = OPC_SWC1;
+        goto do_cop1;
+    case SDC132:
+        mips32_op = OPC_SDC1;
+    do_cop1:
+        gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
+        break;
+    case ADDIUPC:
+        {
+            int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
+            int offset = SIMM(ctx->opcode, 0, 23) << 2;
+
+            gen_addiupc(ctx, reg, offset, 0, 0);
+        }
+        break;
+        /* Loads and stores */
+    case LB32:
+        mips32_op = OPC_LB;
+        goto do_ldst;
+    case LBU32:
+        mips32_op = OPC_LBU;
+        goto do_ldst;
+    case LH32:
+        mips32_op = OPC_LH;
+        goto do_ldst;
+    case LHU32:
+        mips32_op = OPC_LHU;
+        goto do_ldst;
+    case LW32:
+        mips32_op = OPC_LW;
+        goto do_ldst;
+#ifdef TARGET_MIPS64
+    case LD32:
+        mips32_op = OPC_LD;
+        goto do_ldst;
+    case SD32:
+        mips32_op = OPC_SD;
+        goto do_ldst;
+#endif
+    case SB32:
+        mips32_op = OPC_SB;
+        goto do_ldst;
+    case SH32:
+        mips32_op = OPC_SH;
+        goto do_ldst;
+    case SW32:
+        mips32_op = OPC_SW;
+    do_ldst:
+        gen_ldst(ctx, mips32_op, rt, rs, imm);
+        break;
+    default:
+        generate_exception(ctx, EXCP_RI);
+        break;
+    }
+}
+
+static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+{
+    uint32_t op;
+
+    /* make sure instructions are on a halfword boundary */
+    if (ctx->pc & 0x1) {
+        env->CP0_BadVAddr = ctx->pc;
+        generate_exception(ctx, EXCP_AdEL);
+        ctx->bstate = BS_STOP;
+        return 2;
+    }
+
+    op = (ctx->opcode >> 10) & 0x3f;
+    /* Enforce properly-sized instructions in a delay slot */
+    if (ctx->hflags & MIPS_HFLAG_BMASK) {
+        int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
+
+        switch (op) {
+        case POOL32A:
+        case POOL32B:
+        case POOL32I:
+        case POOL32C:
+        case ADDI32:
+        case ADDIU32:
+        case ORI32:
+        case XORI32:
+        case SLTI32:
+        case SLTIU32:
+        case ANDI32:
+        case JALX32:
+        case LBU32:
+        case LHU32:
+        case POOL32F:
+        case JALS32:
+        case BEQ32:
+        case BNE32:
+        case J32:
+        case JAL32:
+        case SB32:
+        case SH32:
+        case POOL32S:
+        case ADDIUPC:
+        case SWC132:
+        case SDC132:
+        case SD32:
+        case SW32:
+        case LB32:
+        case LH32:
+        case DADDIU32:
+        case POOL48A:           /* ??? */
+        case LWC132:
+        case LDC132:
+        case LD32:
+        case LW32:
+            if (bits & MIPS_HFLAG_BDS16) {
+                generate_exception(ctx, EXCP_RI);
+                /* Just stop translation; the user is confused.  */
+                ctx->bstate = BS_STOP;
+                return 2;
+            }
+            break;
+        case POOL16A:
+        case POOL16B:
+        case POOL16C:
+        case LWGP16:
+        case POOL16F:
+        case LBU16:
+        case LHU16:
+        case LWSP16:
+        case LW16:
+        case SB16:
+        case SH16:
+        case SWSP16:
+        case SW16:
+        case MOVE16:
+        case ANDI16:
+        case POOL16D:
+        case POOL16E:
+        case BEQZ16:
+        case BNEZ16:
+        case B16:
+        case LI16:
+            if (bits & MIPS_HFLAG_BDS32) {
+                generate_exception(ctx, EXCP_RI);
+                /* Just stop translation; the user is confused.  */
+                ctx->bstate = BS_STOP;
+                return 2;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    switch (op) {
+    case POOL16A:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
+            int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
+            uint32_t opc = 0;
+
+            switch (ctx->opcode & 0x1) {
+            case ADDU16:
+                opc = OPC_ADDU;
+                break;
+            case SUBU16:
+                opc = OPC_SUBU;
+                break;
+            }
+
+            gen_arith(env, ctx, opc, rd, rs1, rs2);
+        }
+        break;
+    case POOL16B:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rs = mmreg(uMIPS_RS(ctx->opcode));
+            int amount = (ctx->opcode >> 1) & 0x7;
+            uint32_t opc = 0;
+            amount = amount == 0 ? 8 : amount;
+
+            switch (ctx->opcode & 0x1) {
+            case SLL16:
+                opc = OPC_SLL;
+                break;
+            case SRL16:
+                opc = OPC_SRL;
+                break;
+            }
+
+            gen_shift_imm(env, ctx, opc, rd, rs, amount);
+        }
+        break;
+    case POOL16C:
+        gen_pool16c_insn(env, ctx, is_branch);
+        break;
+    case LWGP16:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rb = 28;            /* GP */
+            int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
+
+            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+        }
+        break;
+    case POOL16F:
+        if (ctx->opcode & 1) {
+            generate_exception(ctx, EXCP_RI);
+        } else {
+            /* MOVEP */
+            int enc_dest = uMIPS_RD(ctx->opcode);
+            int enc_rt = uMIPS_RS2(ctx->opcode);
+            int enc_rs = uMIPS_RS1(ctx->opcode);
+            int rd, rs, re, rt;
+            static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
+            static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
+            static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
+
+            rd = rd_enc[enc_dest];
+            re = re_enc[enc_dest];
+            rs = rs_rt_enc[enc_rs];
+            rt = rs_rt_enc[enc_rt];
+
+            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
+            gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
+        }
+        break;
+    case LBU16:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4);
+            offset = (offset == 0xf ? -1 : offset);
+
+            gen_ldst(ctx, OPC_LBU, rd, rb, offset);
+        }
+        break;
+    case LHU16:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
+
+            gen_ldst(ctx, OPC_LHU, rd, rb, offset);
+        }
+        break;
+    case LWSP16:
+        {
+            int rd = (ctx->opcode >> 5) & 0x1f;
+            int rb = 29;            /* SP */
+            int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
+
+            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+        }
+        break;
+    case LW16:
+        {
+            int rd = mmreg(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
+
+            gen_ldst(ctx, OPC_LW, rd, rb, offset);
+        }
+        break;
+    case SB16:
+        {
+            int rd = mmreg2(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4);
+
+            gen_ldst(ctx, OPC_SB, rd, rb, offset);
+        }
+        break;
+    case SH16:
+        {
+            int rd = mmreg2(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
+
+            gen_ldst(ctx, OPC_SH, rd, rb, offset);
+        }
+        break;
+    case SWSP16:
+        {
+            int rd = (ctx->opcode >> 5) & 0x1f;
+            int rb = 29;            /* SP */
+            int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
+
+            gen_ldst(ctx, OPC_SW, rd, rb, offset);
+        }
+        break;
+    case SW16:
+        {
+            int rd = mmreg2(uMIPS_RD(ctx->opcode));
+            int rb = mmreg(uMIPS_RS(ctx->opcode));
+            int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
+
+            gen_ldst(ctx, OPC_SW, rd, rb, offset);
+        }
+        break;
+    case MOVE16:
+        {
+            int rd = uMIPS_RD5(ctx->opcode);
+            int rs = uMIPS_RS5(ctx->opcode);
+
+            gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
+        }
+        break;
+    case ANDI16:
+        gen_andi16(env, ctx);
+        break;
+    case POOL16D:
+        switch (ctx->opcode & 0x1) {
+        case ADDIUS5:
+            gen_addius5(env, ctx);
+            break;
+        case ADDIUSP:
+            gen_addiusp(env, ctx);
+            break;
+        }
+        break;
+    case POOL16E:
+        switch (ctx->opcode & 0x1) {
+        case ADDIUR2:
+            gen_addiur2(env, ctx);
+            break;
+        case ADDIUR1SP:
+            gen_addiur1sp(env, ctx);
+            break;
+        }
+        break;
+    case B16:
+        gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
+                           SIMM(ctx->opcode, 0, 10) << 1);
+        *is_branch = 1;
+        break;
+    case BNEZ16:
+    case BEQZ16:
+        gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
+                           mmreg(uMIPS_RD(ctx->opcode)),
+                           0, SIMM(ctx->opcode, 0, 7) << 1);
+        *is_branch = 1;
+        break;
+    case LI16:
+        {
+            int reg = mmreg(uMIPS_RD(ctx->opcode));
+            int imm = ZIMM(ctx->opcode, 0, 7);
+
+            imm = (imm == 0x7f ? -1 : imm);
+            tcg_gen_movi_tl(cpu_gpr[reg], imm);
+        }
+        break;
+    case RES_20:
+    case RES_28:
+    case RES_29:
+    case RES_30:
+    case RES_31:
+    case RES_38:
+    case RES_39:
+        generate_exception(ctx, EXCP_RI);
+        break;
+    default:
+        decode_micromips32_opc (env, ctx, op, is_branch);
+        return 4;
+    }
+
+    return 2;
+}
+
 /* SmartMIPS extension to MIPS32 */
 
 #if defined(TARGET_MIPS64)
@@ -9548,7 +11924,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
         break;
 #endif
     case OPC_JALX:
-        check_insn(env, ctx, ASE_MIPS16);
+        check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
         gen_compute_branch(ctx, op, 4, rs, rt, offset);
         *is_branch = 1;
@@ -9636,11 +12012,15 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
             ctx.opcode = ldl_code(ctx.pc);
             insn_bytes = 4;
             decode_opc(env, &ctx, &is_branch);
+        } else if (env->insn_flags & ASE_MICROMIPS) {
+            ctx.opcode = lduw_code(ctx.pc);
+            insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
         } else if (env->insn_flags & ASE_MIPS16) {
             ctx.opcode = lduw_code(ctx.pc);
             insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
         } else {
             generate_exception(&ctx, EXCP_RI);
+            ctx.bstate = BS_STOP;
             break;
         }
         if (!is_branch) {
commit 620e48f66350991918dd78e9a686a9b159fec111
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:29:58 2010 -0700

    target-mips: mips16 cleanups
    
    Change code handling mips16-specific branches to use ISA-neutral special
    opcodes.  Since there are several places where the delay slot
    requirements for microMIPS branches differ from mips16 branches, using
    opcodes is easier than checking hflags, then checking mips16
    vs. microMIPS.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index c3182c5..78783a8 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -68,6 +68,7 @@ enum {
     /* Jump and branches */
     OPC_J        = (0x02 << 26),
     OPC_JAL      = (0x03 << 26),
+    OPC_JALS     = OPC_JAL | 0x5,
     OPC_BEQ      = (0x04 << 26),  /* Unconditional if rs = rt = 0 (B) */
     OPC_BEQL     = (0x14 << 26),
     OPC_BNE      = (0x05 << 26),
@@ -77,6 +78,7 @@ enum {
     OPC_BGTZ     = (0x07 << 26),
     OPC_BGTZL    = (0x17 << 26),
     OPC_JALX     = (0x1D << 26),  /* MIPS 16 only */
+    OPC_JALXS    = OPC_JALX | 0x5,
     /* Load and stores */
     OPC_LDL      = (0x1A << 26),
     OPC_LDR      = (0x1B << 26),
@@ -177,6 +179,7 @@ enum {
     OPC_JR       = 0x08 | OPC_SPECIAL, /* Also JR.HB */
     OPC_JALR     = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
     OPC_JALRC    = OPC_JALR | (0x5 << 6),
+    OPC_JALRS    = 0x10 | OPC_SPECIAL | (0x5 << 6),
     /* Traps */
     OPC_TGE      = 0x30 | OPC_SPECIAL,
     OPC_TGEU     = 0x31 | OPC_SPECIAL,
@@ -2466,12 +2469,15 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
     case OPC_J:
     case OPC_JAL:
     case OPC_JALX:
+    case OPC_JALS:
+    case OPC_JALXS:
         /* Jump to immediate */
         btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
         break;
     case OPC_JR:
     case OPC_JALR:
     case OPC_JALRC:
+    case OPC_JALRS:
         /* Jump to register */
         if (offset != 0 && offset != 16) {
             /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
@@ -2534,29 +2540,33 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
             ctx->hflags |= MIPS_HFLAG_B;
             MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
             break;
+        case OPC_JALXS:
         case OPC_JALX:
             ctx->hflags |= MIPS_HFLAG_BX;
             /* Fallthrough */
+        case OPC_JALS:
         case OPC_JAL:
             blink = 31;
             ctx->hflags |= MIPS_HFLAG_B;
-            ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
+            ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
                             ? MIPS_HFLAG_BDS16
                             : MIPS_HFLAG_BDS32);
             MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
             break;
         case OPC_JR:
             ctx->hflags |= MIPS_HFLAG_BR;
-            if (ctx->hflags & MIPS_HFLAG_M16)
-                ctx->hflags |= MIPS_HFLAG_BDS16;
+            if (insn_bytes == 4)
+                ctx->hflags |= MIPS_HFLAG_BDS32;
             MIPS_DEBUG("jr %s", regnames[rs]);
             break;
+        case OPC_JALRS:
         case OPC_JALR:
         case OPC_JALRC:
             blink = rt;
             ctx->hflags |= MIPS_HFLAG_BR;
-            if (ctx->hflags & MIPS_HFLAG_M16)
-                ctx->hflags |= MIPS_HFLAG_BDS16;
+            ctx->hflags |= (opc == OPC_JALRS
+                            ? MIPS_HFLAG_BDS16
+                            : MIPS_HFLAG_BDS32);
             MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
             break;
         default:
@@ -8487,7 +8497,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
         offset = (((ctx->opcode & 0x1f) << 21)
                   | ((ctx->opcode >> 5) & 0x1f) << 16
                   | offset) << 2;
-        op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
+        op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
         gen_compute_branch(ctx, op, 4, rx, ry, offset);
         n_bytes = 4;
         *is_branch = 1;
@@ -8726,7 +8736,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
                 int ra = (ctx->opcode >> 5) & 0x1;
 
                 if (link) {
-                    op = nd ? OPC_JALRC : OPC_JALR;
+                    op = nd ? OPC_JALRC : OPC_JALRS;
                 } else {
                     op = OPC_JR;
                 }
commit 8153667c718e359368f306e1b2c144596dec5f80
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:29:57 2010 -0700

    target-mips: refactor c{, abs}.cond.fmt insns
    
    Move all knowledge about coprocessor-checking and register numbering
    into the gen_cmp* helper functions.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 380312f..c3182c5 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -676,39 +676,6 @@ static inline int get_fp_bit (int cc)
         return 23;
 }
 
-#define FOP_CONDS(type, fmt, bits)                                            \
-static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a,         \
-                                               TCGv_i##bits b, int cc)        \
-{                                                                             \
-    switch (n) {                                                              \
-    case  0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc);    break;\
-    case  1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc);   break;\
-    case  2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc);   break;\
-    case  3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc);  break;\
-    case  4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc);  break;\
-    case  5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc);  break;\
-    case  6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc);  break;\
-    case  7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc);  break;\
-    case  8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc);   break;\
-    case  9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
-    case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc);  break;\
-    case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc);  break;\
-    case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc);   break;\
-    case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc);  break;\
-    case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc);   break;\
-    case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc);  break;\
-    default: abort();                                                         \
-    }                                                                         \
-}
-
-FOP_CONDS(, d, 64)
-FOP_CONDS(abs, d, 64)
-FOP_CONDS(, s, 32)
-FOP_CONDS(abs, s, 32)
-FOP_CONDS(, ps, 64)
-FOP_CONDS(abs, ps, 64)
-#undef FOP_CONDS
-
 /* Tests */
 static inline void gen_save_pc(target_ulong pc)
 {
@@ -849,6 +816,69 @@ static inline void check_mips_64(DisasContext *ctx)
         generate_exception(ctx, EXCP_RI);
 }
 
+/* Define small wrappers for gen_load_fpr* so that we have a uniform
+   calling interface for 32 and 64-bit FPRs.  No sense in changing
+   all callers for gen_load_fpr32 when we need the CTX parameter for
+   this one use.  */
+#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
+#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
+#define FOP_CONDS(type, abs, fmt, ifmt, bits)                                 \
+static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n,      \
+                                               int ft, int fs, int cc)        \
+{                                                                             \
+    TCGv_i##bits fp0 = tcg_temp_new_i##bits ();                               \
+    TCGv_i##bits fp1 = tcg_temp_new_i##bits ();                               \
+    switch (ifmt) {                                                           \
+    case FMT_PS:                                                              \
+        check_cp1_64bitmode(ctx);                                             \
+        break;                                                                \
+    case FMT_D:                                                               \
+        if (abs) {                                                            \
+            check_cop1x(ctx);                                                 \
+        }                                                                     \
+        check_cp1_registers(ctx, fs | ft);                                    \
+        break;                                                                \
+    case FMT_S:                                                               \
+        if (abs) {                                                            \
+            check_cop1x(ctx);                                                 \
+        }                                                                     \
+        break;                                                                \
+    }                                                                         \
+    gen_ldcmp_fpr##bits (ctx, fp0, fs);                                       \
+    gen_ldcmp_fpr##bits (ctx, fp1, ft);                                       \
+    switch (n) {                                                              \
+    case  0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc);    break;\
+    case  1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc);   break;\
+    case  2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc);   break;\
+    case  3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc);  break;\
+    case  4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc);  break;\
+    case  5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc);  break;\
+    case  6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc);  break;\
+    case  7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc);  break;\
+    case  8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc);   break;\
+    case  9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
+    case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc);  break;\
+    case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc);  break;\
+    case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc);   break;\
+    case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc);  break;\
+    case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc);   break;\
+    case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc);  break;\
+    default: abort();                                                         \
+    }                                                                         \
+    tcg_temp_free_i##bits (fp0);                                              \
+    tcg_temp_free_i##bits (fp1);                                              \
+}
+
+FOP_CONDS(, 0, d, FMT_D, 64)
+FOP_CONDS(abs, 1, d, FMT_D, 64)
+FOP_CONDS(, 0, s, FMT_S, 32)
+FOP_CONDS(abs, 1, s, FMT_S, 32)
+FOP_CONDS(, 0, ps, FMT_PS, 64)
+FOP_CONDS(abs, 1, ps, FMT_PS, 64)
+#undef FOP_CONDS
+#undef gen_ldcmp_fpr32
+#undef gen_ldcmp_fpr64
+
 /* load/store instructions. */
 #define OP_LD(insn,fname)                                                 \
 static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
@@ -6480,22 +6510,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
     case OPC_CMP_NGE_S:
     case OPC_CMP_LE_S:
     case OPC_CMP_NGT_S:
-        {
-            TCGv_i32 fp0 = tcg_temp_new_i32();
-            TCGv_i32 fp1 = tcg_temp_new_i32();
-
-            gen_load_fpr32(fp0, fs);
-            gen_load_fpr32(fp1, ft);
-            if (ctx->opcode & (1 << 6)) {
-                check_cop1x(ctx);
-                gen_cmpabs_s(func-48, fp0, fp1, cc);
-                opn = condnames_abs[func-48];
-            } else {
-                gen_cmp_s(func-48, fp0, fp1, cc);
-                opn = condnames[func-48];
-            }
-            tcg_temp_free_i32(fp0);
-            tcg_temp_free_i32(fp1);
+        if (ctx->opcode & (1 << 6)) {
+            gen_cmpabs_s(ctx, func-48, ft, fs, cc);
+            opn = condnames_abs[func-48];
+        } else {
+            gen_cmp_s(ctx, func-48, ft, fs, cc);
+            opn = condnames[func-48];
         }
         break;
     case OPC_ADD_D:
@@ -6843,24 +6863,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
     case OPC_CMP_NGE_D:
     case OPC_CMP_LE_D:
     case OPC_CMP_NGT_D:
-        {
-            TCGv_i64 fp0 = tcg_temp_new_i64();
-            TCGv_i64 fp1 = tcg_temp_new_i64();
-
-            gen_load_fpr64(ctx, fp0, fs);
-            gen_load_fpr64(ctx, fp1, ft);
-            if (ctx->opcode & (1 << 6)) {
-                check_cop1x(ctx);
-                check_cp1_registers(ctx, fs | ft);
-                gen_cmpabs_d(func-48, fp0, fp1, cc);
-                opn = condnames_abs[func-48];
-            } else {
-                check_cp1_registers(ctx, fs | ft);
-                gen_cmp_d(func-48, fp0, fp1, cc);
-                opn = condnames[func-48];
-            }
-            tcg_temp_free_i64(fp0);
-            tcg_temp_free_i64(fp1);
+        if (ctx->opcode & (1 << 6)) {
+            gen_cmpabs_d(ctx, func-48, ft, fs, cc);
+            opn = condnames_abs[func-48];
+        } else {
+            gen_cmp_d(ctx, func-48, ft, fs, cc);
+            opn = condnames[func-48];
         }
         break;
     case OPC_CVT_S_D:
@@ -7280,22 +7288,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
     case OPC_CMP_NGE_PS:
     case OPC_CMP_LE_PS:
     case OPC_CMP_NGT_PS:
-        check_cp1_64bitmode(ctx);
-        {
-            TCGv_i64 fp0 = tcg_temp_new_i64();
-            TCGv_i64 fp1 = tcg_temp_new_i64();
-
-            gen_load_fpr64(ctx, fp0, fs);
-            gen_load_fpr64(ctx, fp1, ft);
-            if (ctx->opcode & (1 << 6)) {
-                gen_cmpabs_ps(func-48, fp0, fp1, cc);
-                opn = condnames_abs[func-48];
-            } else {
-                gen_cmp_ps(func-48, fp0, fp1, cc);
-                opn = condnames[func-48];
-            }
-            tcg_temp_free_i64(fp0);
-            tcg_temp_free_i64(fp1);
+        if (ctx->opcode & (1 << 6)) {
+            gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
+            opn = condnames_abs[func-48];
+        } else {
+            gen_cmp_ps(ctx, func-48, ft, fs, cc);
+            opn = condnames[func-48];
         }
         break;
     default:
commit e459440a896166b65875767f081d9add8db6c9ea
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Jun 9 15:13:17 2010 +0200

    target-mips: move FP FMT comments closer to the definitions
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4e54940..380312f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -357,13 +357,13 @@ enum {
 /* Values for the fmt field in FP instructions */
 enum {
     /* 0 - 15 are reserved */
-    FMT_S = 16,
-    FMT_D = 17,
-    FMT_E = 18,
-    FMT_Q = 19,
-    FMT_W = 20,
-    FMT_L = 21,
-    FMT_PS = 22,
+    FMT_S = 16,          /* single fp */
+    FMT_D = 17,          /* double fp */
+    FMT_E = 18,          /* extended fp */
+    FMT_Q = 19,          /* quad fp */
+    FMT_W = 20,          /* 32-bit fixed */
+    FMT_L = 21,          /* 64-bit fixed */
+    FMT_PS = 22,         /* paired single fp */
     /* 23 - 31 are reserved */
 };
 
@@ -379,13 +379,13 @@ enum {
     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
-    OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,  /* 16: fmt=single fp */
-    OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,  /* 17: fmt=double fp */
-    OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,  /* 18: fmt=extended fp */
-    OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,  /* 19: fmt=quad fp */
-    OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,  /* 20: fmt=32bit fixed */
-    OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,  /* 21: fmt=64bit fixed */
-    OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1, /* 22: fmt=paired single fp */
+    OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
+    OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
+    OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
+    OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
+    OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
+    OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
+    OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
 };
 
 #define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
commit bf4120adaabb540fe66742b4d26cac69713af0c1
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Tue Jun 8 13:29:56 2010 -0700

    target-mips: define constants for magic numbers
    
    Add FMT_* constants for the floating-point format field in opcodes and
    tweak a few places to use them.  Add enums for various invocations of
    FOP and tweak gen_farith and its lone caller accordingly.
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2075d09..4e54940 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -354,6 +354,19 @@ enum {
 /* Coprocessor 1 (rs field) */
 #define MASK_CP1(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
+/* Values for the fmt field in FP instructions */
+enum {
+    /* 0 - 15 are reserved */
+    FMT_S = 16,
+    FMT_D = 17,
+    FMT_E = 18,
+    FMT_Q = 19,
+    FMT_W = 20,
+    FMT_L = 21,
+    FMT_PS = 22,
+    /* 23 - 31 are reserved */
+};
+
 enum {
     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
@@ -366,13 +379,13 @@ enum {
     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
-    OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
-    OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
-    OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
-    OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
-    OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
-    OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
-    OPC_PS_FMT   = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
+    OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,  /* 16: fmt=single fp */
+    OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,  /* 17: fmt=double fp */
+    OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,  /* 18: fmt=extended fp */
+    OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,  /* 19: fmt=quad fp */
+    OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,  /* 20: fmt=32bit fixed */
+    OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,  /* 21: fmt=64bit fixed */
+    OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1, /* 22: fmt=paired single fp */
 };
 
 #define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
@@ -5714,6 +5727,146 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
 
 #define FOP(func, fmt) (((fmt) << 21) | (func))
 
+enum fopcode {
+    OPC_ADD_S = FOP(0, FMT_S),
+    OPC_SUB_S = FOP(1, FMT_S),
+    OPC_MUL_S = FOP(2, FMT_S),
+    OPC_DIV_S = FOP(3, FMT_S),
+    OPC_SQRT_S = FOP(4, FMT_S),
+    OPC_ABS_S = FOP(5, FMT_S),
+    OPC_MOV_S = FOP(6, FMT_S),
+    OPC_NEG_S = FOP(7, FMT_S),
+    OPC_ROUND_L_S = FOP(8, FMT_S),
+    OPC_TRUNC_L_S = FOP(9, FMT_S),
+    OPC_CEIL_L_S = FOP(10, FMT_S),
+    OPC_FLOOR_L_S = FOP(11, FMT_S),
+    OPC_ROUND_W_S = FOP(12, FMT_S),
+    OPC_TRUNC_W_S = FOP(13, FMT_S),
+    OPC_CEIL_W_S = FOP(14, FMT_S),
+    OPC_FLOOR_W_S = FOP(15, FMT_S),
+    OPC_MOVCF_S = FOP(17, FMT_S),
+    OPC_MOVZ_S = FOP(18, FMT_S),
+    OPC_MOVN_S = FOP(19, FMT_S),
+    OPC_RECIP_S = FOP(21, FMT_S),
+    OPC_RSQRT_S = FOP(22, FMT_S),
+    OPC_RECIP2_S = FOP(28, FMT_S),
+    OPC_RECIP1_S = FOP(29, FMT_S),
+    OPC_RSQRT1_S = FOP(30, FMT_S),
+    OPC_RSQRT2_S = FOP(31, FMT_S),
+    OPC_CVT_D_S = FOP(33, FMT_S),
+    OPC_CVT_W_S = FOP(36, FMT_S),
+    OPC_CVT_L_S = FOP(37, FMT_S),
+    OPC_CVT_PS_S = FOP(38, FMT_S),
+    OPC_CMP_F_S = FOP (48, FMT_S),
+    OPC_CMP_UN_S = FOP (49, FMT_S),
+    OPC_CMP_EQ_S = FOP (50, FMT_S),
+    OPC_CMP_UEQ_S = FOP (51, FMT_S),
+    OPC_CMP_OLT_S = FOP (52, FMT_S),
+    OPC_CMP_ULT_S = FOP (53, FMT_S),
+    OPC_CMP_OLE_S = FOP (54, FMT_S),
+    OPC_CMP_ULE_S = FOP (55, FMT_S),
+    OPC_CMP_SF_S = FOP (56, FMT_S),
+    OPC_CMP_NGLE_S = FOP (57, FMT_S),
+    OPC_CMP_SEQ_S = FOP (58, FMT_S),
+    OPC_CMP_NGL_S = FOP (59, FMT_S),
+    OPC_CMP_LT_S = FOP (60, FMT_S),
+    OPC_CMP_NGE_S = FOP (61, FMT_S),
+    OPC_CMP_LE_S = FOP (62, FMT_S),
+    OPC_CMP_NGT_S = FOP (63, FMT_S),
+
+    OPC_ADD_D = FOP(0, FMT_D),
+    OPC_SUB_D = FOP(1, FMT_D),
+    OPC_MUL_D = FOP(2, FMT_D),
+    OPC_DIV_D = FOP(3, FMT_D),
+    OPC_SQRT_D = FOP(4, FMT_D),
+    OPC_ABS_D = FOP(5, FMT_D),
+    OPC_MOV_D = FOP(6, FMT_D),
+    OPC_NEG_D = FOP(7, FMT_D),
+    OPC_ROUND_L_D = FOP(8, FMT_D),
+    OPC_TRUNC_L_D = FOP(9, FMT_D),
+    OPC_CEIL_L_D = FOP(10, FMT_D),
+    OPC_FLOOR_L_D = FOP(11, FMT_D),
+    OPC_ROUND_W_D = FOP(12, FMT_D),
+    OPC_TRUNC_W_D = FOP(13, FMT_D),
+    OPC_CEIL_W_D = FOP(14, FMT_D),
+    OPC_FLOOR_W_D = FOP(15, FMT_D),
+    OPC_MOVCF_D = FOP(17, FMT_D),
+    OPC_MOVZ_D = FOP(18, FMT_D),
+    OPC_MOVN_D = FOP(19, FMT_D),
+    OPC_RECIP_D = FOP(21, FMT_D),
+    OPC_RSQRT_D = FOP(22, FMT_D),
+    OPC_RECIP2_D = FOP(28, FMT_D),
+    OPC_RECIP1_D = FOP(29, FMT_D),
+    OPC_RSQRT1_D = FOP(30, FMT_D),
+    OPC_RSQRT2_D = FOP(31, FMT_D),
+    OPC_CVT_S_D = FOP(32, FMT_D),
+    OPC_CVT_W_D = FOP(36, FMT_D),
+    OPC_CVT_L_D = FOP(37, FMT_D),
+    OPC_CMP_F_D = FOP (48, FMT_D),
+    OPC_CMP_UN_D = FOP (49, FMT_D),
+    OPC_CMP_EQ_D = FOP (50, FMT_D),
+    OPC_CMP_UEQ_D = FOP (51, FMT_D),
+    OPC_CMP_OLT_D = FOP (52, FMT_D),
+    OPC_CMP_ULT_D = FOP (53, FMT_D),
+    OPC_CMP_OLE_D = FOP (54, FMT_D),
+    OPC_CMP_ULE_D = FOP (55, FMT_D),
+    OPC_CMP_SF_D = FOP (56, FMT_D),
+    OPC_CMP_NGLE_D = FOP (57, FMT_D),
+    OPC_CMP_SEQ_D = FOP (58, FMT_D),
+    OPC_CMP_NGL_D = FOP (59, FMT_D),
+    OPC_CMP_LT_D = FOP (60, FMT_D),
+    OPC_CMP_NGE_D = FOP (61, FMT_D),
+    OPC_CMP_LE_D = FOP (62, FMT_D),
+    OPC_CMP_NGT_D = FOP (63, FMT_D),
+
+    OPC_CVT_S_W = FOP(32, FMT_W),
+    OPC_CVT_D_W = FOP(33, FMT_W),
+    OPC_CVT_S_L = FOP(32, FMT_L),
+    OPC_CVT_D_L = FOP(33, FMT_L),
+    OPC_CVT_PS_PW = FOP(38, FMT_W),
+
+    OPC_ADD_PS = FOP(0, FMT_PS),
+    OPC_SUB_PS = FOP(1, FMT_PS),
+    OPC_MUL_PS = FOP(2, FMT_PS),
+    OPC_DIV_PS = FOP(3, FMT_PS),
+    OPC_ABS_PS = FOP(5, FMT_PS),
+    OPC_MOV_PS = FOP(6, FMT_PS),
+    OPC_NEG_PS = FOP(7, FMT_PS),
+    OPC_MOVCF_PS = FOP(17, FMT_PS),
+    OPC_MOVZ_PS = FOP(18, FMT_PS),
+    OPC_MOVN_PS = FOP(19, FMT_PS),
+    OPC_ADDR_PS = FOP(24, FMT_PS),
+    OPC_MULR_PS = FOP(26, FMT_PS),
+    OPC_RECIP2_PS = FOP(28, FMT_PS),
+    OPC_RECIP1_PS = FOP(29, FMT_PS),
+    OPC_RSQRT1_PS = FOP(30, FMT_PS),
+    OPC_RSQRT2_PS = FOP(31, FMT_PS),
+
+    OPC_CVT_S_PU = FOP(32, FMT_PS),
+    OPC_CVT_PW_PS = FOP(36, FMT_PS),
+    OPC_CVT_S_PL = FOP(40, FMT_PS),
+    OPC_PLL_PS = FOP(44, FMT_PS),
+    OPC_PLU_PS = FOP(45, FMT_PS),
+    OPC_PUL_PS = FOP(46, FMT_PS),
+    OPC_PUU_PS = FOP(47, FMT_PS),
+    OPC_CMP_F_PS = FOP (48, FMT_PS),
+    OPC_CMP_UN_PS = FOP (49, FMT_PS),
+    OPC_CMP_EQ_PS = FOP (50, FMT_PS),
+    OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
+    OPC_CMP_OLT_PS = FOP (52, FMT_PS),
+    OPC_CMP_ULT_PS = FOP (53, FMT_PS),
+    OPC_CMP_OLE_PS = FOP (54, FMT_PS),
+    OPC_CMP_ULE_PS = FOP (55, FMT_PS),
+    OPC_CMP_SF_PS = FOP (56, FMT_PS),
+    OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
+    OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
+    OPC_CMP_NGL_PS = FOP (59, FMT_PS),
+    OPC_CMP_LT_PS = FOP (60, FMT_PS),
+    OPC_CMP_NGE_PS = FOP (61, FMT_PS),
+    OPC_CMP_LE_PS = FOP (62, FMT_PS),
+    OPC_CMP_NGT_PS = FOP (63, FMT_PS),
+};
+
 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
 {
     const char *opn = "cp1 move";
@@ -5894,7 +6047,7 @@ static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
 }
 
 
-static void gen_farith (DisasContext *ctx, uint32_t op1,
+static void gen_farith (DisasContext *ctx, enum fopcode op1,
                         int ft, int fs, int fd, int cc)
 {
     const char *opn = "farith";
@@ -5937,8 +6090,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
     enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
     uint32_t func = ctx->opcode & 0x3f;
 
-    switch (ctx->opcode & FOP(0x3f, 0x1f)) {
-    case FOP(0, 16):
+    switch (op1) {
+    case OPC_ADD_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5953,7 +6106,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "add.s";
         optype = BINOP;
         break;
-    case FOP(1, 16):
+    case OPC_SUB_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5968,7 +6121,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "sub.s";
         optype = BINOP;
         break;
-    case FOP(2, 16):
+    case OPC_MUL_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5983,7 +6136,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "mul.s";
         optype = BINOP;
         break;
-    case FOP(3, 16):
+    case OPC_DIV_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5998,7 +6151,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "div.s";
         optype = BINOP;
         break;
-    case FOP(4, 16):
+    case OPC_SQRT_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6009,7 +6162,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "sqrt.s";
         break;
-    case FOP(5, 16):
+    case OPC_ABS_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6020,7 +6173,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "abs.s";
         break;
-    case FOP(6, 16):
+    case OPC_MOV_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6030,7 +6183,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "mov.s";
         break;
-    case FOP(7, 16):
+    case OPC_NEG_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6041,7 +6194,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "neg.s";
         break;
-    case FOP(8, 16):
+    case OPC_ROUND_L_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6055,7 +6208,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "round.l.s";
         break;
-    case FOP(9, 16):
+    case OPC_TRUNC_L_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6069,7 +6222,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "trunc.l.s";
         break;
-    case FOP(10, 16):
+    case OPC_CEIL_L_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6083,7 +6236,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "ceil.l.s";
         break;
-    case FOP(11, 16):
+    case OPC_FLOOR_L_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6097,7 +6250,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "floor.l.s";
         break;
-    case FOP(12, 16):
+    case OPC_ROUND_W_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6108,7 +6261,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "round.w.s";
         break;
-    case FOP(13, 16):
+    case OPC_TRUNC_W_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6119,7 +6272,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "trunc.w.s";
         break;
-    case FOP(14, 16):
+    case OPC_CEIL_W_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6130,7 +6283,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "ceil.w.s";
         break;
-    case FOP(15, 16):
+    case OPC_FLOOR_W_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6141,11 +6294,11 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "floor.w.s";
         break;
-    case FOP(17, 16):
+    case OPC_MOVCF_S:
         gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
         opn = "movcf.s";
         break;
-    case FOP(18, 16):
+    case OPC_MOVZ_S:
         {
             int l1 = gen_new_label();
             TCGv_i32 fp0;
@@ -6161,7 +6314,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movz.s";
         break;
-    case FOP(19, 16):
+    case OPC_MOVN_S:
         {
             int l1 = gen_new_label();
             TCGv_i32 fp0;
@@ -6177,7 +6330,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movn.s";
         break;
-    case FOP(21, 16):
+    case OPC_RECIP_S:
         check_cop1x(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6189,7 +6342,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip.s";
         break;
-    case FOP(22, 16):
+    case OPC_RSQRT_S:
         check_cop1x(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6201,7 +6354,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt.s";
         break;
-    case FOP(28, 16):
+    case OPC_RECIP2_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6216,7 +6369,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip2.s";
         break;
-    case FOP(29, 16):
+    case OPC_RECIP1_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6228,7 +6381,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip1.s";
         break;
-    case FOP(30, 16):
+    case OPC_RSQRT1_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6240,7 +6393,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt1.s";
         break;
-    case FOP(31, 16):
+    case OPC_RSQRT2_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6255,7 +6408,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt2.s";
         break;
-    case FOP(33, 16):
+    case OPC_CVT_D_S:
         check_cp1_registers(ctx, fd);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6269,7 +6422,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.d.s";
         break;
-    case FOP(36, 16):
+    case OPC_CVT_W_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6280,7 +6433,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.w.s";
         break;
-    case FOP(37, 16):
+    case OPC_CVT_L_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6294,7 +6447,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.l.s";
         break;
-    case FOP(38, 16):
+    case OPC_CVT_PS_S:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp64 = tcg_temp_new_i64();
@@ -6311,22 +6464,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.ps.s";
         break;
-    case FOP(48, 16):
-    case FOP(49, 16):
-    case FOP(50, 16):
-    case FOP(51, 16):
-    case FOP(52, 16):
-    case FOP(53, 16):
-    case FOP(54, 16):
-    case FOP(55, 16):
-    case FOP(56, 16):
-    case FOP(57, 16):
-    case FOP(58, 16):
-    case FOP(59, 16):
-    case FOP(60, 16):
-    case FOP(61, 16):
-    case FOP(62, 16):
-    case FOP(63, 16):
+    case OPC_CMP_F_S:
+    case OPC_CMP_UN_S:
+    case OPC_CMP_EQ_S:
+    case OPC_CMP_UEQ_S:
+    case OPC_CMP_OLT_S:
+    case OPC_CMP_ULT_S:
+    case OPC_CMP_OLE_S:
+    case OPC_CMP_ULE_S:
+    case OPC_CMP_SF_S:
+    case OPC_CMP_NGLE_S:
+    case OPC_CMP_SEQ_S:
+    case OPC_CMP_NGL_S:
+    case OPC_CMP_LT_S:
+    case OPC_CMP_NGE_S:
+    case OPC_CMP_LE_S:
+    case OPC_CMP_NGT_S:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -6345,7 +6498,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
             tcg_temp_free_i32(fp1);
         }
         break;
-    case FOP(0, 17):
+    case OPC_ADD_D:
         check_cp1_registers(ctx, fs | ft | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6361,7 +6514,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "add.d";
         optype = BINOP;
         break;
-    case FOP(1, 17):
+    case OPC_SUB_D:
         check_cp1_registers(ctx, fs | ft | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6377,7 +6530,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "sub.d";
         optype = BINOP;
         break;
-    case FOP(2, 17):
+    case OPC_MUL_D:
         check_cp1_registers(ctx, fs | ft | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6393,7 +6546,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "mul.d";
         optype = BINOP;
         break;
-    case FOP(3, 17):
+    case OPC_DIV_D:
         check_cp1_registers(ctx, fs | ft | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6409,7 +6562,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         opn = "div.d";
         optype = BINOP;
         break;
-    case FOP(4, 17):
+    case OPC_SQRT_D:
         check_cp1_registers(ctx, fs | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6421,7 +6574,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "sqrt.d";
         break;
-    case FOP(5, 17):
+    case OPC_ABS_D:
         check_cp1_registers(ctx, fs | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6433,7 +6586,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "abs.d";
         break;
-    case FOP(6, 17):
+    case OPC_MOV_D:
         check_cp1_registers(ctx, fs | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6444,7 +6597,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "mov.d";
         break;
-    case FOP(7, 17):
+    case OPC_NEG_D:
         check_cp1_registers(ctx, fs | fd);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6456,7 +6609,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "neg.d";
         break;
-    case FOP(8, 17):
+    case OPC_ROUND_L_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6468,7 +6621,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "round.l.d";
         break;
-    case FOP(9, 17):
+    case OPC_TRUNC_L_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6480,7 +6633,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "trunc.l.d";
         break;
-    case FOP(10, 17):
+    case OPC_CEIL_L_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6492,7 +6645,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "ceil.l.d";
         break;
-    case FOP(11, 17):
+    case OPC_FLOOR_L_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6504,7 +6657,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "floor.l.d";
         break;
-    case FOP(12, 17):
+    case OPC_ROUND_W_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6518,7 +6671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "round.w.d";
         break;
-    case FOP(13, 17):
+    case OPC_TRUNC_W_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6532,7 +6685,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "trunc.w.d";
         break;
-    case FOP(14, 17):
+    case OPC_CEIL_W_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6546,7 +6699,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "ceil.w.d";
         break;
-    case FOP(15, 17):
+    case OPC_FLOOR_W_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6560,11 +6713,11 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "floor.w.d";
         break;
-    case FOP(17, 17):
+    case OPC_MOVCF_D:
         gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
         opn = "movcf.d";
         break;
-    case FOP(18, 17):
+    case OPC_MOVZ_D:
         {
             int l1 = gen_new_label();
             TCGv_i64 fp0;
@@ -6580,7 +6733,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movz.d";
         break;
-    case FOP(19, 17):
+    case OPC_MOVN_D:
         {
             int l1 = gen_new_label();
             TCGv_i64 fp0;
@@ -6596,7 +6749,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movn.d";
         break;
-    case FOP(21, 17):
+    case OPC_RECIP_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6608,7 +6761,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip.d";
         break;
-    case FOP(22, 17):
+    case OPC_RSQRT_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6620,7 +6773,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt.d";
         break;
-    case FOP(28, 17):
+    case OPC_RECIP2_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6635,7 +6788,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip2.d";
         break;
-    case FOP(29, 17):
+    case OPC_RECIP1_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6647,7 +6800,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip1.d";
         break;
-    case FOP(30, 17):
+    case OPC_RSQRT1_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6659,7 +6812,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt1.d";
         break;
-    case FOP(31, 17):
+    case OPC_RSQRT2_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6674,22 +6827,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt2.d";
         break;
-    case FOP(48, 17):
-    case FOP(49, 17):
-    case FOP(50, 17):
-    case FOP(51, 17):
-    case FOP(52, 17):
-    case FOP(53, 17):
-    case FOP(54, 17):
-    case FOP(55, 17):
-    case FOP(56, 17):
-    case FOP(57, 17):
-    case FOP(58, 17):
-    case FOP(59, 17):
-    case FOP(60, 17):
-    case FOP(61, 17):
-    case FOP(62, 17):
-    case FOP(63, 17):
+    case OPC_CMP_F_D:
+    case OPC_CMP_UN_D:
+    case OPC_CMP_EQ_D:
+    case OPC_CMP_UEQ_D:
+    case OPC_CMP_OLT_D:
+    case OPC_CMP_ULT_D:
+    case OPC_CMP_OLE_D:
+    case OPC_CMP_ULE_D:
+    case OPC_CMP_SF_D:
+    case OPC_CMP_NGLE_D:
+    case OPC_CMP_SEQ_D:
+    case OPC_CMP_NGL_D:
+    case OPC_CMP_LT_D:
+    case OPC_CMP_NGE_D:
+    case OPC_CMP_LE_D:
+    case OPC_CMP_NGT_D:
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -6710,7 +6863,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
             tcg_temp_free_i64(fp1);
         }
         break;
-    case FOP(32, 17):
+    case OPC_CVT_S_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6724,7 +6877,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.s.d";
         break;
-    case FOP(36, 17):
+    case OPC_CVT_W_D:
         check_cp1_registers(ctx, fs);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6738,7 +6891,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.w.d";
         break;
-    case FOP(37, 17):
+    case OPC_CVT_L_D:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6750,7 +6903,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.l.d";
         break;
-    case FOP(32, 20):
+    case OPC_CVT_S_W:
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
@@ -6761,7 +6914,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.s.w";
         break;
-    case FOP(33, 20):
+    case OPC_CVT_D_W:
         check_cp1_registers(ctx, fd);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6775,7 +6928,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.d.w";
         break;
-    case FOP(32, 21):
+    case OPC_CVT_S_L:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6789,7 +6942,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.s.l";
         break;
-    case FOP(33, 21):
+    case OPC_CVT_D_L:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6801,7 +6954,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.d.l";
         break;
-    case FOP(38, 20):
+    case OPC_CVT_PS_PW:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6813,7 +6966,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.ps.pw";
         break;
-    case FOP(0, 22):
+    case OPC_ADD_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6828,7 +6981,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "add.ps";
         break;
-    case FOP(1, 22):
+    case OPC_SUB_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6843,7 +6996,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "sub.ps";
         break;
-    case FOP(2, 22):
+    case OPC_MUL_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6858,7 +7011,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "mul.ps";
         break;
-    case FOP(5, 22):
+    case OPC_ABS_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6870,7 +7023,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "abs.ps";
         break;
-    case FOP(6, 22):
+    case OPC_MOV_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6881,7 +7034,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "mov.ps";
         break;
-    case FOP(7, 22):
+    case OPC_NEG_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6893,12 +7046,12 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "neg.ps";
         break;
-    case FOP(17, 22):
+    case OPC_MOVCF_PS:
         check_cp1_64bitmode(ctx);
         gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
         opn = "movcf.ps";
         break;
-    case FOP(18, 22):
+    case OPC_MOVZ_PS:
         check_cp1_64bitmode(ctx);
         {
             int l1 = gen_new_label();
@@ -6914,7 +7067,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movz.ps";
         break;
-    case FOP(19, 22):
+    case OPC_MOVN_PS:
         check_cp1_64bitmode(ctx);
         {
             int l1 = gen_new_label();
@@ -6931,7 +7084,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "movn.ps";
         break;
-    case FOP(24, 22):
+    case OPC_ADDR_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6946,7 +7099,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "addr.ps";
         break;
-    case FOP(26, 22):
+    case OPC_MULR_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6961,7 +7114,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "mulr.ps";
         break;
-    case FOP(28, 22):
+    case OPC_RECIP2_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6976,7 +7129,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip2.ps";
         break;
-    case FOP(29, 22):
+    case OPC_RECIP1_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6988,7 +7141,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "recip1.ps";
         break;
-    case FOP(30, 22):
+    case OPC_RSQRT1_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7000,7 +7153,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt1.ps";
         break;
-    case FOP(31, 22):
+    case OPC_RSQRT2_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7015,7 +7168,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "rsqrt2.ps";
         break;
-    case FOP(32, 22):
+    case OPC_CVT_S_PU:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7027,7 +7180,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.s.pu";
         break;
-    case FOP(36, 22):
+    case OPC_CVT_PW_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7039,7 +7192,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.pw.ps";
         break;
-    case FOP(40, 22):
+    case OPC_CVT_S_PL:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7051,7 +7204,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "cvt.s.pl";
         break;
-    case FOP(44, 22):
+    case OPC_PLL_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7066,7 +7219,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "pll.ps";
         break;
-    case FOP(45, 22):
+    case OPC_PLU_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7081,7 +7234,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "plu.ps";
         break;
-    case FOP(46, 22):
+    case OPC_PUL_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7096,7 +7249,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "pul.ps";
         break;
-    case FOP(47, 22):
+    case OPC_PUU_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7111,22 +7264,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
         }
         opn = "puu.ps";
         break;
-    case FOP(48, 22):
-    case FOP(49, 22):
-    case FOP(50, 22):
-    case FOP(51, 22):
-    case FOP(52, 22):
-    case FOP(53, 22):
-    case FOP(54, 22):
-    case FOP(55, 22):
-    case FOP(56, 22):
-    case FOP(57, 22):
-    case FOP(58, 22):
-    case FOP(59, 22):
-    case FOP(60, 22):
-    case FOP(61, 22):
-    case FOP(62, 22):
-    case FOP(63, 22):
+    case OPC_CMP_F_PS:
+    case OPC_CMP_UN_PS:
+    case OPC_CMP_EQ_PS:
+    case OPC_CMP_UEQ_PS:
+    case OPC_CMP_OLT_PS:
+    case OPC_CMP_ULT_PS:
+    case OPC_CMP_OLE_PS:
+    case OPC_CMP_ULE_PS:
+    case OPC_CMP_SF_PS:
+    case OPC_CMP_NGLE_PS:
+    case OPC_CMP_SEQ_PS:
+    case OPC_CMP_NGL_PS:
+    case OPC_CMP_LT_PS:
+    case OPC_CMP_NGE_PS:
+    case OPC_CMP_LE_PS:
+    case OPC_CMP_NGT_PS:
         check_cp1_64bitmode(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -9298,7 +9451,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             case OPC_W_FMT:
             case OPC_L_FMT:
             case OPC_PS_FMT:
-                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
+                gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
                            (imm >> 8) & 0x7);
                 break;
             default:
commit c61aaf7a388c4ad95d8b546fdb9267dc01183317
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 3 19:40:04 2010 +0200

    tcg: get rid of DEF2 in tcg-opc.h
    
    Now that tcg-opc.h is only used in TCG code, get rid of DEF2 in
    tcg-opc.h.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 5531da7..2a98fed 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -21,283 +21,284 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#ifndef DEF2
-#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs)
-#endif
+
+/*
+ * DEF(name, oargs, iargs, cargs, flags)
+ */
 
 /* predefined ops */
-DEF2(end, 0, 0, 0, 0) /* must be kept first */
-DEF2(nop, 0, 0, 0, 0)
-DEF2(nop1, 0, 0, 1, 0)
-DEF2(nop2, 0, 0, 2, 0)
-DEF2(nop3, 0, 0, 3, 0)
-DEF2(nopn, 0, 0, 1, 0) /* variable number of parameters */
+DEF(end, 0, 0, 0, 0) /* must be kept first */
+DEF(nop, 0, 0, 0, 0)
+DEF(nop1, 0, 0, 1, 0)
+DEF(nop2, 0, 0, 2, 0)
+DEF(nop3, 0, 0, 3, 0)
+DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
 
-DEF2(discard, 1, 0, 0, 0)
+DEF(discard, 1, 0, 0, 0)
 
-DEF2(set_label, 0, 0, 1, 0)
-DEF2(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
-DEF2(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(set_label, 0, 0, 1, 0)
+DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
+DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
 
-DEF2(mov_i32, 1, 1, 0, 0)
-DEF2(movi_i32, 1, 0, 1, 0)
-DEF2(setcond_i32, 1, 2, 1, 0)
+DEF(mov_i32, 1, 1, 0, 0)
+DEF(movi_i32, 1, 0, 1, 0)
+DEF(setcond_i32, 1, 2, 1, 0)
 /* load/store */
-DEF2(ld8u_i32, 1, 1, 1, 0)
-DEF2(ld8s_i32, 1, 1, 1, 0)
-DEF2(ld16u_i32, 1, 1, 1, 0)
-DEF2(ld16s_i32, 1, 1, 1, 0)
-DEF2(ld_i32, 1, 1, 1, 0)
-DEF2(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(ld8u_i32, 1, 1, 1, 0)
+DEF(ld8s_i32, 1, 1, 1, 0)
+DEF(ld16u_i32, 1, 1, 1, 0)
+DEF(ld16s_i32, 1, 1, 1, 0)
+DEF(ld_i32, 1, 1, 1, 0)
+DEF(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
 /* arith */
-DEF2(add_i32, 1, 2, 0, 0)
-DEF2(sub_i32, 1, 2, 0, 0)
-DEF2(mul_i32, 1, 2, 0, 0)
+DEF(add_i32, 1, 2, 0, 0)
+DEF(sub_i32, 1, 2, 0, 0)
+DEF(mul_i32, 1, 2, 0, 0)
 #ifdef TCG_TARGET_HAS_div_i32
-DEF2(div_i32, 1, 2, 0, 0)
-DEF2(divu_i32, 1, 2, 0, 0)
-DEF2(rem_i32, 1, 2, 0, 0)
-DEF2(remu_i32, 1, 2, 0, 0)
+DEF(div_i32, 1, 2, 0, 0)
+DEF(divu_i32, 1, 2, 0, 0)
+DEF(rem_i32, 1, 2, 0, 0)
+DEF(remu_i32, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_div2_i32
-DEF2(div2_i32, 2, 3, 0, 0)
-DEF2(divu2_i32, 2, 3, 0, 0)
+DEF(div2_i32, 2, 3, 0, 0)
+DEF(divu2_i32, 2, 3, 0, 0)
 #endif
-DEF2(and_i32, 1, 2, 0, 0)
-DEF2(or_i32, 1, 2, 0, 0)
-DEF2(xor_i32, 1, 2, 0, 0)
+DEF(and_i32, 1, 2, 0, 0)
+DEF(or_i32, 1, 2, 0, 0)
+DEF(xor_i32, 1, 2, 0, 0)
 /* shifts/rotates */
-DEF2(shl_i32, 1, 2, 0, 0)
-DEF2(shr_i32, 1, 2, 0, 0)
-DEF2(sar_i32, 1, 2, 0, 0)
+DEF(shl_i32, 1, 2, 0, 0)
+DEF(shr_i32, 1, 2, 0, 0)
+DEF(sar_i32, 1, 2, 0, 0)
 #ifdef TCG_TARGET_HAS_rot_i32
-DEF2(rotl_i32, 1, 2, 0, 0)
-DEF2(rotr_i32, 1, 2, 0, 0)
+DEF(rotl_i32, 1, 2, 0, 0)
+DEF(rotr_i32, 1, 2, 0, 0)
 #endif
 
-DEF2(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
 #if TCG_TARGET_REG_BITS == 32
-DEF2(add2_i32, 2, 4, 0, 0)
-DEF2(sub2_i32, 2, 4, 0, 0)
-DEF2(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(mulu2_i32, 2, 2, 0, 0)
-DEF2(setcond2_i32, 1, 4, 1, 0)
+DEF(add2_i32, 2, 4, 0, 0)
+DEF(sub2_i32, 2, 4, 0, 0)
+DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(mulu2_i32, 2, 2, 0, 0)
+DEF(setcond2_i32, 1, 4, 1, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext8s_i32
-DEF2(ext8s_i32, 1, 1, 0, 0)
+DEF(ext8s_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext16s_i32
-DEF2(ext16s_i32, 1, 1, 0, 0)
+DEF(ext16s_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext8u_i32
-DEF2(ext8u_i32, 1, 1, 0, 0)
+DEF(ext8u_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext16u_i32
-DEF2(ext16u_i32, 1, 1, 0, 0)
+DEF(ext16u_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_bswap16_i32
-DEF2(bswap16_i32, 1, 1, 0, 0)
+DEF(bswap16_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_bswap32_i32
-DEF2(bswap32_i32, 1, 1, 0, 0)
+DEF(bswap32_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_not_i32
-DEF2(not_i32, 1, 1, 0, 0)
+DEF(not_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_neg_i32
-DEF2(neg_i32, 1, 1, 0, 0)
+DEF(neg_i32, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_andc_i32
-DEF2(andc_i32, 1, 2, 0, 0)
+DEF(andc_i32, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_orc_i32
-DEF2(orc_i32, 1, 2, 0, 0)
+DEF(orc_i32, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_eqv_i32
-DEF2(eqv_i32, 1, 2, 0, 0)
+DEF(eqv_i32, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_nand_i32
-DEF2(nand_i32, 1, 2, 0, 0)
+DEF(nand_i32, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_nor_i32
-DEF2(nor_i32, 1, 2, 0, 0)
+DEF(nor_i32, 1, 2, 0, 0)
 #endif
 
 #if TCG_TARGET_REG_BITS == 64
-DEF2(mov_i64, 1, 1, 0, 0)
-DEF2(movi_i64, 1, 0, 1, 0)
-DEF2(setcond_i64, 1, 2, 1, 0)
+DEF(mov_i64, 1, 1, 0, 0)
+DEF(movi_i64, 1, 0, 1, 0)
+DEF(setcond_i64, 1, 2, 1, 0)
 /* load/store */
-DEF2(ld8u_i64, 1, 1, 1, 0)
-DEF2(ld8s_i64, 1, 1, 1, 0)
-DEF2(ld16u_i64, 1, 1, 1, 0)
-DEF2(ld16s_i64, 1, 1, 1, 0)
-DEF2(ld32u_i64, 1, 1, 1, 0)
-DEF2(ld32s_i64, 1, 1, 1, 0)
-DEF2(ld_i64, 1, 1, 1, 0)
-DEF2(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(ld8u_i64, 1, 1, 1, 0)
+DEF(ld8s_i64, 1, 1, 1, 0)
+DEF(ld16u_i64, 1, 1, 1, 0)
+DEF(ld16s_i64, 1, 1, 1, 0)
+DEF(ld32u_i64, 1, 1, 1, 0)
+DEF(ld32s_i64, 1, 1, 1, 0)
+DEF(ld_i64, 1, 1, 1, 0)
+DEF(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
 /* arith */
-DEF2(add_i64, 1, 2, 0, 0)
-DEF2(sub_i64, 1, 2, 0, 0)
-DEF2(mul_i64, 1, 2, 0, 0)
+DEF(add_i64, 1, 2, 0, 0)
+DEF(sub_i64, 1, 2, 0, 0)
+DEF(mul_i64, 1, 2, 0, 0)
 #ifdef TCG_TARGET_HAS_div_i64
-DEF2(div_i64, 1, 2, 0, 0)
-DEF2(divu_i64, 1, 2, 0, 0)
-DEF2(rem_i64, 1, 2, 0, 0)
-DEF2(remu_i64, 1, 2, 0, 0)
+DEF(div_i64, 1, 2, 0, 0)
+DEF(divu_i64, 1, 2, 0, 0)
+DEF(rem_i64, 1, 2, 0, 0)
+DEF(remu_i64, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_div2_i64
-DEF2(div2_i64, 2, 3, 0, 0)
-DEF2(divu2_i64, 2, 3, 0, 0)
+DEF(div2_i64, 2, 3, 0, 0)
+DEF(divu2_i64, 2, 3, 0, 0)
 #endif
-DEF2(and_i64, 1, 2, 0, 0)
-DEF2(or_i64, 1, 2, 0, 0)
-DEF2(xor_i64, 1, 2, 0, 0)
+DEF(and_i64, 1, 2, 0, 0)
+DEF(or_i64, 1, 2, 0, 0)
+DEF(xor_i64, 1, 2, 0, 0)
 /* shifts/rotates */
-DEF2(shl_i64, 1, 2, 0, 0)
-DEF2(shr_i64, 1, 2, 0, 0)
-DEF2(sar_i64, 1, 2, 0, 0)
+DEF(shl_i64, 1, 2, 0, 0)
+DEF(shr_i64, 1, 2, 0, 0)
+DEF(sar_i64, 1, 2, 0, 0)
 #ifdef TCG_TARGET_HAS_rot_i64
-DEF2(rotl_i64, 1, 2, 0, 0)
-DEF2(rotr_i64, 1, 2, 0, 0)
+DEF(rotl_i64, 1, 2, 0, 0)
+DEF(rotr_i64, 1, 2, 0, 0)
 #endif
 
-DEF2(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
 #ifdef TCG_TARGET_HAS_ext8s_i64
-DEF2(ext8s_i64, 1, 1, 0, 0)
+DEF(ext8s_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext16s_i64
-DEF2(ext16s_i64, 1, 1, 0, 0)
+DEF(ext16s_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext32s_i64
-DEF2(ext32s_i64, 1, 1, 0, 0)
+DEF(ext32s_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext8u_i64
-DEF2(ext8u_i64, 1, 1, 0, 0)
+DEF(ext8u_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext16u_i64
-DEF2(ext16u_i64, 1, 1, 0, 0)
+DEF(ext16u_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_ext32u_i64
-DEF2(ext32u_i64, 1, 1, 0, 0)
+DEF(ext32u_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_bswap16_i64
-DEF2(bswap16_i64, 1, 1, 0, 0)
+DEF(bswap16_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_bswap32_i64
-DEF2(bswap32_i64, 1, 1, 0, 0)
+DEF(bswap32_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_bswap64_i64
-DEF2(bswap64_i64, 1, 1, 0, 0)
+DEF(bswap64_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_not_i64
-DEF2(not_i64, 1, 1, 0, 0)
+DEF(not_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_neg_i64
-DEF2(neg_i64, 1, 1, 0, 0)
+DEF(neg_i64, 1, 1, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_andc_i64
-DEF2(andc_i64, 1, 2, 0, 0)
+DEF(andc_i64, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_orc_i64
-DEF2(orc_i64, 1, 2, 0, 0)
+DEF(orc_i64, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_eqv_i64
-DEF2(eqv_i64, 1, 2, 0, 0)
+DEF(eqv_i64, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_nand_i64
-DEF2(nand_i64, 1, 2, 0, 0)
+DEF(nand_i64, 1, 2, 0, 0)
 #endif
 #ifdef TCG_TARGET_HAS_nor_i64
-DEF2(nor_i64, 1, 2, 0, 0)
+DEF(nor_i64, 1, 2, 0, 0)
 #endif
 #endif
 
 /* QEMU specific */
 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF2(debug_insn_start, 0, 0, 2, 0)
+DEF(debug_insn_start, 0, 0, 2, 0)
 #else
-DEF2(debug_insn_start, 0, 0, 1, 0)
+DEF(debug_insn_start, 0, 0, 1, 0)
 #endif
-DEF2(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
 /* Note: even if TARGET_LONG_BITS is not defined, the INDEX_op
    constants must be defined */
 #if TCG_TARGET_REG_BITS == 32
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 #if TARGET_LONG_BITS == 32
-DEF2(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #else
-DEF2(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 #endif
 
 #else /* TCG_TARGET_REG_BITS == 32 */
 
-DEF2(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 
-DEF2(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
 
 #endif /* TCG_TARGET_REG_BITS != 32 */
 
-#undef DEF2
+#undef DEF
diff --git a/tcg/tcg.c b/tcg/tcg.c
index b1fe470..30b5106 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,11 +69,9 @@ static void patch_reloc(uint8_t *code_ptr, int type,
                         tcg_target_long value, tcg_target_long addend);
 
 static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, n) { #s, 0, 0, n, n, 0 },
-#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
+#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
 #include "tcg-opc.h"
 #undef DEF
-#undef DEF2
 };
 
 static TCGRegSet tcg_target_available_regs[2];
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 7fe7ab0..972df72 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -48,7 +48,7 @@ typedef uint64_t TCGRegSet;
 #endif
 
 typedef enum TCGOpcode {
-#define DEF(s, n) INDEX_op_ ## s,
+#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
 #include "tcg-opc.h"
 #undef DEF
     NB_OPS,
commit 239fda311a6f7784bc4f732795722c909b835651
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 3 19:29:31 2010 +0200

    tcg: get rid of copy_size in TCGOpDef
    
    copy_size is a left-over from the dyngen era, remove it.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/exec-all.h b/exec-all.h
index 4565dd0..a775582 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -80,7 +80,6 @@ void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
 void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
                  unsigned long searched_pc, int pc_pos, void *puc);
 
-unsigned long code_gen_max_block_size(void);
 void cpu_gen_init(void);
 int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
                  int *gen_code_size_ptr);
diff --git a/exec.c b/exec.c
index bb3dcad..aedfda4 100644
--- a/exec.c
+++ b/exec.c
@@ -557,7 +557,7 @@ static void code_gen_alloc(unsigned long tb_size)
 #endif /* !USE_STATIC_CODE_GEN_BUFFER */
     map_exec(code_gen_prologue, sizeof(code_gen_prologue));
     code_gen_buffer_max_size = code_gen_buffer_size - 
-        code_gen_max_block_size();
+        (TCG_MAX_OP_SIZE * OPC_MAX_SIZE);
     code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
     tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
 }
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 674c73a..5531da7 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #ifndef DEF2
-#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs, 0)
+#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs)
 #endif
 
 /* predefined ops */
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 3368d93..b1fe470 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,7 +69,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
                         tcg_target_long value, tcg_target_long addend);
 
 static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
+#define DEF(s, n) { #s, 0, 0, n, n, 0 },
 #define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
 #include "tcg-opc.h"
 #undef DEF
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9134700..7fe7ab0 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -48,7 +48,7 @@ typedef uint64_t TCGRegSet;
 #endif
 
 typedef enum TCGOpcode {
-#define DEF(s, n, copy_size) INDEX_op_ ## s,
+#define DEF(s, n) INDEX_op_ ## s,
 #include "tcg-opc.h"
 #undef DEF
     NB_OPS,
@@ -422,7 +422,6 @@ typedef struct TCGOpDef {
     const char *name;
     uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
     uint8_t flags;
-    uint16_t copy_size;
     TCGArgConstraint *args_ct;
     int *sorted_args;
 #if defined(CONFIG_DEBUG_TCG)
diff --git a/translate-all.c b/translate-all.c
index 91cbbc4..efcfb9a 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -41,22 +41,6 @@ target_ulong gen_opc_pc[OPC_BUF_SIZE];
 uint16_t gen_opc_icount[OPC_BUF_SIZE];
 uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
 
-/* XXX: suppress that */
-unsigned long code_gen_max_block_size(void)
-{
-    static unsigned long max;
-
-    if (max == 0) {
-        max = TCG_MAX_OP_SIZE;
-#define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
-#include "tcg-opc.h"
-#undef DEF
-        max *= OPC_MAX_SIZE;
-    }
-
-    return max;
-}
-
 void cpu_gen_init(void)
 {
     tcg_context_init(&tcg_ctx); 
commit 590bf491a49670843ee902c47f7ab1de5e9acd06
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jun 2 01:56:50 2010 +0200

    Fix multiboot compilation
    
    Commit dd4239d6574ca41c94fc0d0f77ddc728510ffc57 broke multiboot. It replaced the
    instruction "rep insb (%dx), %es:(%edi)" by the binary output of
    "addr32 rep insb (%dx), %es:(%di)".
    
    Linuxboot calls the respective helper function in a code16 section. So the
    original instruction was automatically translated to its "addr32" equivalent.
    For multiboot, we're running in code32 so gcc didn't add the "addr32" which
    breaks the instruction.
    
    This patch splits that helper function in one which uses addr32 and one which
    does not, so everyone's happy.
    
    The good news is that nobody probably cared so far. The bundled multiboot.bin
    binary was built before the change and is thus correct.
    
    Please also put this patch into -stable.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/pc-bios/optionrom/linuxboot.S b/pc-bios/optionrom/linuxboot.S
index 8aebe51..c109363 100644
--- a/pc-bios/optionrom/linuxboot.S
+++ b/pc-bios/optionrom/linuxboot.S
@@ -106,10 +106,10 @@ copy_kernel:
 	/* We're now running in 16-bit CS, but 32-bit ES! */
 
 	/* Load kernel and initrd */
-	read_fw_blob(FW_CFG_KERNEL)
-	read_fw_blob(FW_CFG_INITRD)
-	read_fw_blob(FW_CFG_CMDLINE)
-	read_fw_blob(FW_CFG_SETUP)
+	read_fw_blob_addr32(FW_CFG_KERNEL)
+	read_fw_blob_addr32(FW_CFG_INITRD)
+	read_fw_blob_addr32(FW_CFG_CMDLINE)
+	read_fw_blob_addr32(FW_CFG_SETUP)
 
 	/* And now jump into Linux! */
 	mov		$0, %eax
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index 4dcb906..fbdd48a 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -50,13 +50,7 @@
 	bswap		%eax
 .endm
 
-/*
- * Read a blob from the fw_cfg device.
- * Requires _ADDR, _SIZE and _DATA values for the parameter.
- *
- * Clobbers:	%eax, %edx, %es, %ecx, %edi
- */
-#define read_fw_blob(var)				\
+#define read_fw_blob_pre(var)				\
 	read_fw		var ## _ADDR;			\
 	mov		%eax, %edi;			\
 	read_fw		var ## _SIZE;			\
@@ -65,10 +59,32 @@
 	mov		$BIOS_CFG_IOPORT_CFG, %edx;	\
 	outw		%ax, (%dx);			\
 	mov		$BIOS_CFG_IOPORT_DATA, %dx;	\
-	cld;						\
+	cld
+
+/*
+ * Read a blob from the fw_cfg device.
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers:	%eax, %edx, %es, %ecx, %edi
+ */
+#define read_fw_blob(var)				\
+	read_fw_blob_pre(var);				\
 	/* old as(1) doesn't like this insn so emit the bytes instead: \
 	rep insb	(%dx), %es:(%edi);		\
 	*/						\
+	.dc.b		0xf3,0x6c
+
+/*
+ * Read a blob from the fw_cfg device in forced addr32 mode.
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers:	%eax, %edx, %es, %ecx, %edi
+ */
+#define read_fw_blob_addr32(var)				\
+	read_fw_blob_pre(var);				\
+	/* old as(1) doesn't like this insn so emit the bytes instead: \
+	addr32 rep insb	(%dx), %es:(%edi);		\
+	*/						\
 	.dc.b		0x67,0xf3,0x6c
 
 #define OPTION_ROM_START					\
commit 50e32ea8f31035877decc10f1075aa0e619e09cb
Author: Amit Shah <amit.shah at redhat.com>
Date:   Tue Jun 8 21:13:58 2010 +0530

    net: Fix hotplug with pci_add
    
    The correct model type wasn't getting added when hotplugging nics with
    pci_add.
    
    Testcase: start VM with default nic type. In the qemu_monitor:
    
    (qemu) pci_add auto nic model=virtio
    
    This results in a nic hot-plug of the same nic type as the default.
    
    This was broken in 5294e2c774f120e10b44652ac143abda356f44eb
    
    Also changes the behaviour where no .init is defined for a
    net_client_type. Previously, 0 was returned, which indicated the init
    was successful and that 0 was the index into the nd_tables[] array.
    Return -1, indicating unsuccessful init, in such a case.
    
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/net.c b/net.c
index 378edfc..22f5cf1 100644
--- a/net.c
+++ b/net.c
@@ -1106,6 +1106,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     for (i = 0; net_client_types[i].type != NULL; i++) {
         if (!strcmp(net_client_types[i].type, type)) {
             VLANState *vlan = NULL;
+            int ret;
 
             if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
                 return -1;
@@ -1118,14 +1119,16 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
                 vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
             }
 
+            ret = -1;
             if (net_client_types[i].init) {
-                if (net_client_types[i].init(opts, mon, name, vlan) < 0) {
+                ret = net_client_types[i].init(opts, mon, name, vlan);
+                if (ret < 0) {
                     /* TODO push error reporting into init() methods */
                     qerror_report(QERR_DEVICE_INIT_FAILED, type);
                     return -1;
                 }
             }
-            return 0;
+            return ret;
         }
     }
 
commit e4d58b41f9fb6d7ea8281fe42fd5e00db2fd1455
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Jun 2 17:26:56 2010 -0700

    tcg: Make some tcg-target.c routines static.
    
    Both tcg_target_init and tcg_target_qemu_prologue
    are unused outside of tcg.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index b3169a9..a3af5b2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1746,7 +1746,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
     { -1 },
 };
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* fail safe */
@@ -1809,7 +1809,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
     tcg_out_movi32(s, COND_AL, ret, arg);
 }
 
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     /* There is no need to save r7, it is used to store the address
        of the env structure and is not modified by GCC. */
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index a5f2162..7f4653e 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1600,7 +1600,7 @@ static int tcg_target_callee_save_regs[] = {
     TCG_REG_R18
 };
 
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int frame_size, i;
 
@@ -1652,7 +1652,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
                  TCG_REG_SP, -frame_size, INSN_LDWM);
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
 
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8745ad1..147ba17 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1430,7 +1430,7 @@ static int tcg_target_callee_save_regs[] = {
 };
 
 /* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int i, frame_size, push_size, stack_addend;
 
@@ -1458,7 +1458,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
     tcg_out_opc(s, OPC_RET);
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* fail safe */
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 0d275e9..a0f3877 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2266,7 +2266,7 @@ static const TCGTargetOpDef ia64_op_defs[] = {
 };
 
 /* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int frame_size;
 
@@ -2321,7 +2321,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
                                TCG_REG_B0));
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32],
                    0xffffffffffffffffull);
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8d9c12f..2af7a2e 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1466,7 +1466,7 @@ static int tcg_target_callee_save_regs[] = {
 };
 
 /* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int i, frame_size;
 
@@ -1498,7 +1498,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
     tcg_out_addi(s, TCG_REG_SP, frame_size);
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
     tcg_regset_set(tcg_target_call_clobber_regs,
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index ce078e4..2e5bb9f 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -900,7 +900,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-void tcg_target_qemu_prologue (TCGContext *s)
+static void tcg_target_qemu_prologue (TCGContext *s)
 {
     int i, frame_size;
 
@@ -1885,7 +1885,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { -1 },
 };
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 2d436a5..0483d6b 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -860,7 +860,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #endif
 }
 
-void tcg_target_qemu_prologue (TCGContext *s)
+static void tcg_target_qemu_prologue (TCGContext *s)
 {
     int i, frame_size;
 #ifndef __APPLE__
@@ -1663,7 +1663,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
     { -1 },
 };
 
-void tcg_target_init (TCGContext *s)
+static void tcg_target_init (TCGContext *s)
 {
     tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
     tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 06b6db3..6f08aa4 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -84,12 +84,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     tcg_abort();
 }
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     /* gets called with KVM */
 }
 
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     /* gets called with KVM */
 }
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 9f970cd..5f1353a 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -691,7 +691,7 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
 #endif
 
 /* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
               INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
@@ -1533,7 +1533,7 @@ static const TCGTargetOpDef sparc_op_defs[] = {
     { -1 },
 };
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
 #if TCG_TARGET_REG_BITS == 64
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 32f9e17..3368d93 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -63,6 +63,8 @@
 #error GUEST_BASE not supported on this host.
 #endif
 
+static void tcg_target_init(TCGContext *s);
+static void tcg_target_qemu_prologue(TCGContext *s);
 static void patch_reloc(uint8_t *code_ptr, int type, 
                         tcg_target_long value, tcg_target_long addend);
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index d6cb9e7..9134700 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -435,9 +435,6 @@ typedef struct TCGTargetOpDef {
     const char *args_ct_str[TCG_MAX_OP_ARGS];
 } TCGTargetOpDef;
 
-void tcg_target_init(TCGContext *s);
-void tcg_target_qemu_prologue(TCGContext *s);
-
 #define tcg_abort() \
 do {\
     fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
index 9844a57..490666e 100644
--- a/tcg/x86_64/tcg-target.c
+++ b/tcg/x86_64/tcg-target.c
@@ -1279,7 +1279,7 @@ static inline void tcg_out_pop(TCGContext *s, int reg)
 }
 
 /* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int i, frame_size, push_size, stack_addend;
 
@@ -1417,7 +1417,7 @@ static const TCGTargetOpDef x86_64_op_defs[] = {
     { -1 },
 };
 
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* fail safe */
commit 3b6dac34161bc0a342336072643c2f6d17e0ec45
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Jun 2 17:26:55 2010 -0700

    tcg: Add TYPE parameter to tcg_out_mov.
    
    Mirror tcg_out_movi in having a TYPE parameter.  This allows x86_64
    to perform the move at the proper width, which may elide a REX prefix.
    
    Introduce a TCG_TYPE_REG enumerator to represent the "native width"
    of the host register, and to distinguish the usage from "pointer data"
    as represented by the existing TCG_TYPE_PTR.
    
    Update all targets to match.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 8d23f47..b3169a9 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1798,7 +1798,7 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
     }
 }
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
 }
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 558c21f..a5f2162 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -338,7 +338,7 @@ static int tcg_target_const_match(tcg_target_long val,
 /* supplied by libgcc */
 extern void *__canonicalize_funcptr_for_compare(void *);
 
-static void tcg_out_mov(TCGContext *s, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     /* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t
        but hppa-dis.c is unaware of this definition */
@@ -498,7 +498,7 @@ static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
     }
     assert(bs1 == 32 || (1ul << bs1) > m);
 
-    tcg_out_mov(s, ret, arg);
+    tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
     tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
               | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
 }
@@ -528,7 +528,7 @@ static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
     if (ls1 == 32) {
         tcg_out_extr(s, ret, arg, 0, ls0, 0);
     } else {
-        tcg_out_mov(s, ret, arg);
+        tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
         tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
                   | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
     }
@@ -608,7 +608,7 @@ static void tcg_out_rotr(TCGContext *s, int ret, int arg, int creg)
 static void tcg_out_bswap16(TCGContext *s, int ret, int arg, int sign)
 {
     if (ret != arg) {
-        tcg_out_mov(s, ret, arg);             /* arg =  xxAB */
+        tcg_out_mov(s, TCG_TYPE_I32, ret, arg); /* arg =  xxAB */
     }
     tcg_out_dep(s, ret, ret, 16, 8);          /* ret =  xBAB */
     tcg_out_extr(s, ret, ret, 8, 16, sign);   /* ret =  ..BA */
@@ -638,7 +638,7 @@ static void tcg_out_call(TCGContext *s, void *func)
         tcg_out32(s, INSN_LDIL | INSN_R2(TCG_REG_R20) | reassemble_21(hi));
         tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R20)
                   | reassemble_17(lo >> 2));
-        tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RP, TCG_REG_R31);
     }
 }
 
@@ -685,7 +685,7 @@ static void tcg_out_add2(TCGContext *s, int destl, int desth,
     }
     tcg_out_arith(s, desth, ah, bh, INSN_ADDC);
 
-    tcg_out_mov(s, destl, tmp);
+    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
 }
 
 static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
@@ -706,7 +706,7 @@ static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
     }
     tcg_out_arith(s, desth, ah, bh, INSN_SUBB);
 
-    tcg_out_mov(s, destl, tmp);
+    tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
 }
 
 static void tcg_out_branch(TCGContext *s, int label_index, int nul)
@@ -869,7 +869,7 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
         break;
     }
 
-    tcg_out_mov(s, ret, scratch);
+    tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);
 }
 
 #if defined(CONFIG_SOFTMMU)
@@ -1048,9 +1048,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
 
     argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addrlo_reg);
+    tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addrhi_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
     }
     tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
 
@@ -1071,11 +1071,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
         break;
     case 2:
     case 2 | 4:
-        tcg_out_mov(s, datalo_reg, TCG_REG_RET0);
+        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET0);
         break;
     case 3:
-        tcg_out_mov(s, datahi_reg, TCG_REG_RET0);
-        tcg_out_mov(s, datalo_reg, TCG_REG_RET1);
+        tcg_out_mov(s, TCG_TYPE_I32, datahi_reg, TCG_REG_RET0);
+        tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET1);
         break;
     default:
         tcg_abort();
@@ -1167,9 +1167,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
     tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
 
     argreg = TCG_REG_R26;
-    tcg_out_mov(s, argreg--, addrlo_reg);
+    tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, argreg--, addrhi_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
     }
 
     switch(opc) {
@@ -1182,7 +1182,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         break;
     case 2:
-        tcg_out_mov(s, argreg--, datalo_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, argreg--, datalo_reg);
         tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         break;
     case 3:
@@ -1196,8 +1196,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
             argreg = TCG_REG_R20;
             tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
         }
-        tcg_out_mov(s, TCG_REG_R23, datahi_reg);
-        tcg_out_mov(s, TCG_REG_R24, datalo_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg);
         tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
                    TCG_TARGET_CALL_STACK_OFFSET - 4);
         break;
@@ -1637,7 +1637,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
 
     /* Jump to TB, and adjust R18 to be the return address.  */
     tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
-    tcg_out_mov(s, TCG_REG_R18, TCG_REG_R31);
+    tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
 
     /* Restore callee saved registers.  */
     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -frame_size - 20);
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 3600c35..8745ad1 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -348,7 +348,7 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
     tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
 }
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     if (arg != ret) {
         tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
@@ -733,8 +733,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
     const int r0 = TCG_REG_EAX;
     const int r1 = TCG_REG_EDX;
 
-    tcg_out_mov(s, r1, addrlo);
-    tcg_out_mov(s, r0, addrlo);
+    tcg_out_mov(s, TCG_TYPE_I32, r1, addrlo);
+    tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
 
     tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 
@@ -748,7 +748,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
     /* cmp 0(r1), r0 */
     tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
 
-    tcg_out_mov(s, r0, addrlo);
+    tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
 
     /* jne label1 */
     tcg_out8(s, OPC_JCC_short + JCC_JNE);
@@ -881,7 +881,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     /* EAX is already loaded.  */
     arg_idx = 1;
     if (TARGET_LONG_BITS == 64) {
-        tcg_out_mov(s, tcg_target_call_iarg_regs[arg_idx++],
+        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
                     args[addrlo_idx + 1]);
     }
     tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
@@ -903,16 +903,16 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         break;
     case 2:
     default:
-        tcg_out_mov(s, data_reg, TCG_REG_EAX);
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
         break;
     case 3:
         if (data_reg == TCG_REG_EDX) {
             /* xchg %edx, %eax */
             tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
-            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
+            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
         } else {
-            tcg_out_mov(s, data_reg, TCG_REG_EAX);
-            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
+            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
         }
         break;
     }
@@ -945,7 +945,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         break;
     case 1:
         if (bswap) {
-            tcg_out_mov(s, scratch, datalo);
+            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
             tcg_out_rolw_8(s, scratch);
             datalo = scratch;
         }
@@ -955,7 +955,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         break;
     case 2:
         if (bswap) {
-            tcg_out_mov(s, scratch, datalo);
+            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
             tcg_out_bswap32(s, scratch);
             datalo = scratch;
         }
@@ -963,10 +963,10 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
         break;
     case 3:
         if (bswap) {
-            tcg_out_mov(s, scratch, datahi);
+            tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
             tcg_out_bswap32(s, scratch);
             tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
-            tcg_out_mov(s, scratch, datalo);
+            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
             tcg_out_bswap32(s, scratch);
             tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
         } else {
@@ -1022,9 +1022,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     /* XXX: move that code at the end of the TB */
     if (TARGET_LONG_BITS == 32) {
-        tcg_out_mov(s, TCG_REG_EDX, data_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
         if (opc == 3) {
-            tcg_out_mov(s, TCG_REG_ECX, data_reg2);
+            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
             tcg_out_pushi(s, mem_index);
             stack_adjust = 4;
         } else {
@@ -1033,13 +1033,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         }
     } else {
         if (opc == 3) {
-            tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
             tcg_out_pushi(s, mem_index);
             tcg_out_push(s, data_reg2);
             tcg_out_push(s, data_reg);
             stack_adjust = 12;
         } else {
-            tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
             switch(opc) {
             case 0:
                 tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
@@ -1048,7 +1048,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                 tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
                 break;
             case 2:
-                tcg_out_mov(s, TCG_REG_ECX, data_reg);
+                tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
                 break;
             }
             tcg_out_pushi(s, mem_index);
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 905f48b..0d275e9 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -827,7 +827,8 @@ static inline void tcg_out_bundle(TCGContext *s, int template,
     s->code_ptr += 16;
 }
 
-static inline void tcg_out_mov(TCGContext *s, TCGArg ret, TCGArg arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+                               TCGArg ret, TCGArg arg)
 {
     tcg_out_bundle(s, mmI,
                    tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index f38eb28..8d9c12f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -377,7 +377,7 @@ static inline void tcg_out_nop(TCGContext *s)
     tcg_out32(s, 0);
 }
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
 }
@@ -849,9 +849,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     /* slow path */
     sp_args = TCG_REG_A0;
-    tcg_out_mov(s, sp_args++, addr_reg1);
+    tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
 # if TARGET_LONG_BITS == 64
-    tcg_out_mov(s, sp_args++, addr_reg2);
+    tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
 # endif
     tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
@@ -872,11 +872,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
         break;
     case 2:
-        tcg_out_mov(s, data_reg1, TCG_REG_V0);
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
         break;
     case 3:
-        tcg_out_mov(s, data_reg2, TCG_REG_V1);
-        tcg_out_mov(s, data_reg1, TCG_REG_V0);
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
         break;
     default:
         tcg_abort();
@@ -1035,9 +1035,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     /* slow path */
     sp_args = TCG_REG_A0;
-    tcg_out_mov(s, sp_args++, addr_reg1);
+    tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
 # if TARGET_LONG_BITS == 64
-    tcg_out_mov(s, sp_args++, addr_reg2);
+    tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
 # endif
     switch(opc) {
     case 0:
@@ -1047,12 +1047,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
         break;
     case 2:
-        tcg_out_mov(s, sp_args++, data_reg1);
+        tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
         break;
     case 3:
         sp_args = (sp_args + 1) & ~1;
-        tcg_out_mov(s, sp_args++, data_reg1);
-        tcg_out_mov(s, sp_args++, data_reg2);
+        tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
+        tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
         break;
     default:
         tcg_abort();
@@ -1165,7 +1165,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_mov_i32:
-        tcg_out_mov(s, args[0], args[1]);
+        tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
         break;
     case INDEX_op_movi_i32:
         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
@@ -1216,7 +1216,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
              tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
         }
         tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
-        tcg_out_mov(s, args[0], TCG_REG_AT);
+        tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
         break;
     case INDEX_op_sub_i32:
         if (const_args[2]) {
@@ -1238,7 +1238,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
              tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
         }
         tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
-        tcg_out_mov(s, args[0], TCG_REG_AT);
+        tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
         break;
     case INDEX_op_mul_i32:
         tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 2b85928..ce078e4 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -437,7 +437,7 @@ static const uint32_t tcg_to_bc[10] = {
     [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
 };
 
-static void tcg_out_mov(TCGContext *s, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_out32 (s, OR | SAB (arg, ret, arg));
 }
@@ -591,11 +591,11 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 
     /* slow path */
 #if TARGET_LONG_BITS == 32
-    tcg_out_mov (s, 3, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
     tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
 #else
-    tcg_out_mov (s, 3, addr_reg2);
-    tcg_out_mov (s, 4, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
+    tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
     tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
 #endif
 
@@ -611,23 +611,23 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     case 1:
     case 2:
         if (data_reg != 3)
-            tcg_out_mov (s, data_reg, 3);
+            tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3);
         break;
     case 3:
         if (data_reg == 3) {
             if (data_reg2 == 4) {
-                tcg_out_mov (s, 0, 4);
-                tcg_out_mov (s, 4, 3);
-                tcg_out_mov (s, 3, 0);
+                tcg_out_mov (s, TCG_TYPE_I32, 0, 4);
+                tcg_out_mov (s, TCG_TYPE_I32, 4, 3);
+                tcg_out_mov (s, TCG_TYPE_I32, 3, 0);
             }
             else {
-                tcg_out_mov (s, data_reg2, 3);
-                tcg_out_mov (s, 3, 4);
+                tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
+                tcg_out_mov (s, TCG_TYPE_I32, 3, 4);
             }
         }
         else {
-            if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
-            if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
+            if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4);
+            if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
         }
         break;
     }
@@ -705,7 +705,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
             if (r0 == data_reg2) {
                 tcg_out32 (s, LWZ | RT (0) | RA (r0));
                 tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
-                tcg_out_mov (s, data_reg2, 0);
+                tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 0);
             }
             else {
                 tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
@@ -787,11 +787,11 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 
     /* slow path */
 #if TARGET_LONG_BITS == 32
-    tcg_out_mov (s, 3, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
     ir = 4;
 #else
-    tcg_out_mov (s, 3, addr_reg2);
-    tcg_out_mov (s, 4, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
+    tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
     ir = 5;
 #else
@@ -817,14 +817,14 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
                        | ME (31)));
         break;
     case 2:
-        tcg_out_mov (s, ir, data_reg);
+        tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
         break;
     case 3:
 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
         ir = 5;
 #endif
-        tcg_out_mov (s, ir++, data_reg2);
-        tcg_out_mov (s, ir, data_reg);
+        tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2);
+        tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
         break;
     }
     ir++;
@@ -1526,7 +1526,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         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, args[0], 0);
+            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
         }
         else {
             tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
@@ -1584,7 +1584,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
     case INDEX_op_rotr_i32:
         if (const_args[2]) {
             if (!args[2]) {
-                tcg_out_mov (s, args[0], args[1]);
+                tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
             }
             else {
                 tcg_out32 (s, RLWINM
@@ -1612,7 +1612,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         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, args[0], 0);
+            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
         }
         else {
             tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
@@ -1623,7 +1623,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
         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, args[0], 0);
+            tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
         }
         else {
             tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
@@ -1782,7 +1782,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                 );
 
             if (!a0) {
-                tcg_out_mov (s, args[0], a0);
+                tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
             }
         }
         break;
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 0b6c61f..2d436a5 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -435,7 +435,7 @@ static const uint32_t tcg_to_bc[10] = {
     [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
 };
 
-static void tcg_out_mov (TCGContext *s, int ret, int arg)
+static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_out32 (s, OR | SAB (arg, ret, arg));
 }
@@ -644,7 +644,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     /* slow path */
-    tcg_out_mov (s, 3, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
     tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
 
     tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
@@ -664,7 +664,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
     case 2:
     case 3:
         if (data_reg != 3)
-            tcg_out_mov (s, data_reg, 3);
+            tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
         break;
     }
     label2_ptr = s->code_ptr;
@@ -746,7 +746,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
         else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
 #else
         if (bswap) {
-            tcg_out_movi32 (s, 0, 4);
+            tcg_out_movi32 (s, TCG_TYPE_I64, 0, 4);
             tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
             tcg_out32 (s, LWBRX | RT (      r1) | RA (r0));
             tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
@@ -790,7 +790,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
 #endif
 
     /* slow path */
-    tcg_out_mov (s, 3, addr_reg);
+    tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
     tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
     tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
 
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 265194a..06b6db3 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -94,7 +94,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
     /* gets called with KVM */
 }
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_abort();
 }
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index e460d44..9f970cd 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -304,7 +304,7 @@ static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
               | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
 }
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
     tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
 }
@@ -795,7 +795,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     tcg_out32(s, 0);
 
     /* mov (delay slot) */
-    tcg_out_mov(s, arg0, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
 
     /* mov */
     tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
@@ -845,7 +845,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     case 3:
     default:
         /* mov */
-        tcg_out_mov(s, data_reg, arg0);
+        tcg_out_mov(s, TCG_TYPE_REG, data_reg, arg0);
         break;
     }
 
@@ -1007,10 +1007,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     tcg_out32(s, 0);
 
     /* mov (delay slot) */
-    tcg_out_mov(s, arg0, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
 
     /* mov */
-    tcg_out_mov(s, arg1, data_reg);
+    tcg_out_mov(s, TCG_TYPE_REG, arg1, data_reg);
 
     /* mov */
     tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 880e7ce..32f9e17 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1547,7 +1547,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
                 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
             }
             if (ts->reg != reg) {
-                tcg_out_mov(s, reg, ts->reg);
+                tcg_out_mov(s, ots->type, reg, ts->reg);
             }
         }
     } else if (ts->val_type == TEMP_VAL_MEM) {
@@ -1652,7 +1652,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
             /* allocate a new register matching the constraint 
                and move the temporary register into it */
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_mov(s, reg, ts->reg);
+            tcg_out_mov(s, ts->type, reg, ts->reg);
         }
         new_args[i] = reg;
         const_args[i] = 0;
@@ -1734,7 +1734,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
         ts = &s->temps[args[i]];
         reg = new_args[i];
         if (ts->fixed_reg && ts->reg != reg) {
-            tcg_out_mov(s, ts->reg, reg);
+            tcg_out_mov(s, ts->type, ts->reg, reg);
         }
     }
 }
@@ -1820,7 +1820,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
             tcg_reg_free(s, reg);
             if (ts->val_type == TEMP_VAL_REG) {
                 if (ts->reg != reg) {
-                    tcg_out_mov(s, reg, ts->reg);
+                    tcg_out_mov(s, ts->type, reg, ts->reg);
                 }
             } else if (ts->val_type == TEMP_VAL_MEM) {
                 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
@@ -1849,7 +1849,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
         reg = ts->reg;
         if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
-            tcg_out_mov(s, reg, ts->reg);
+            tcg_out_mov(s, ts->type, reg, ts->reg);
         }
         func_arg = reg;
         tcg_regset_set_reg(allocated_regs, reg);
@@ -1908,7 +1908,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
         assert(s->reg_to_temp[reg] == -1);
         if (ts->fixed_reg) {
             if (ts->reg != reg) {
-                tcg_out_mov(s, ts->reg, reg);
+                tcg_out_mov(s, ts->type, ts->reg, reg);
             }
         } else {
             if (ts->val_type == TEMP_VAL_REG)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5853823..d6cb9e7 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -101,11 +101,18 @@ typedef enum TCGType {
     TCG_TYPE_I64,
     TCG_TYPE_COUNT, /* number of different types */
 
+    /* An alias for the size of the host register.  */
 #if TCG_TARGET_REG_BITS == 32
-    TCG_TYPE_PTR = TCG_TYPE_I32,
+    TCG_TYPE_REG = TCG_TYPE_I32,
 #else
-    TCG_TYPE_PTR = TCG_TYPE_I64,
+    TCG_TYPE_REG = TCG_TYPE_I64,
 #endif
+
+    /* An alias for the size of the native pointer.  We don't currently
+       support any hosts with 64-bit registers and 32-bit pointers.  */
+    TCG_TYPE_PTR = TCG_TYPE_REG,
+
+    /* An alias for the size of the target "long", aka register.  */
 #if TARGET_LONG_BITS == 64
     TCG_TYPE_TL = TCG_TYPE_I64,
 #else
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
index 3892f75..9844a57 100644
--- a/tcg/x86_64/tcg-target.c
+++ b/tcg/x86_64/tcg-target.c
@@ -354,9 +354,10 @@ static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm,
 }
 #endif
 
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
 {
-    tcg_out_modrm(s, 0x8b | P_REXW, ret, arg);
+    int rexw = (type == TCG_TYPE_I64 ? P_REXW : 0);
+    tcg_out_modrm(s, 0x8b | rexw, ret, arg);
 }
 
 static inline void tcg_out_movi(TCGContext *s, TCGType type, 
@@ -577,11 +578,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     rexw = P_REXW;
 #endif
 #if defined(CONFIG_SOFTMMU)
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
-
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
  
     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
@@ -599,8 +597,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     /* cmp 0(r1), r0 */
     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
     
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
     
     /* je label1 */
     tcg_out8(s, 0x70 + JCC_JE);
@@ -634,11 +631,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         break;
     case 2:
     default:
-        /* movl */
-        tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX);
+        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_RAX);
         break;
     case 3:
-        tcg_out_mov(s, data_reg, TCG_REG_RAX);
+        tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
         break;
     }
 
@@ -772,11 +768,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     rexw = P_REXW;
 #endif
 #if defined(CONFIG_SOFTMMU)
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
-
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
+    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
  
     tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
     tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
@@ -793,10 +786,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     /* cmp 0(r1), r0 */
     tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-    
-    /* mov */
-    tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
-    
+
+    tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
+
     /* je label1 */
     tcg_out8(s, 0x70 + JCC_JE);
     label1_ptr = s->code_ptr;
@@ -813,12 +805,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
         break;
     case 2:
-        /* movl */
-        tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg);
+        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RSI, data_reg);
         break;
     default:
     case 3:
-        tcg_out_mov(s, TCG_REG_RSI, data_reg);
+        tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_RSI, data_reg);
         break;
     }
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
@@ -863,7 +854,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         break;
     case 1:
         if (bswap) {
-            tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
+            tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
             tcg_out8(s, 0x66); /* rolw $8, %ecx */
             tcg_out_modrm(s, 0xc1, 0, r1);
             tcg_out8(s, 8);
@@ -875,7 +866,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         break;
     case 2:
         if (bswap) {
-            tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
+            tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
             /* bswap data_reg */
             tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
             data_reg = r1;
@@ -885,7 +876,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         break;
     case 3:
         if (bswap) {
-            tcg_out_mov(s, r1, data_reg);
+            tcg_out_mov(s, TCG_TYPE_I64, r1, data_reg);
             /* bswap data_reg */
             tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
             data_reg = r1;
commit 26ebe46848ecb2462cc53d4de20ac6590709643b
Author: Nathan Froyd <froydnj at codesourcery.com>
Date:   Mon May 24 09:19:35 2010 -0700

    target-mips: break out [ls][wd]c1 and rdhwr insn generation
    
    Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index c95ecb1..2075d09 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1220,6 +1220,17 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
     tcg_temp_free(t0);
 }
 
+static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
+                          uint32_t op, int rt, int rs, int16_t imm)
+{
+    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+        check_cp1_enabled(ctx);
+        gen_flt_ldst(ctx, op, rt, rs, imm);
+    } else {
+        generate_exception_err(ctx, EXCP_CpU, 1);
+    }
+}
+
 /* Arithmetic with immediate operand */
 static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
                            int rt, int rs, int16_t imm)
@@ -7528,6 +7539,52 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
                fregnames[fs], fregnames[ft]);
 }
 
+static void
+gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
+{
+    TCGv t0;
+
+    check_insn(env, ctx, ISA_MIPS32R2);
+    t0 = tcg_temp_new();
+
+    switch (rd) {
+    case 0:
+        save_cpu_state(ctx, 1);
+        gen_helper_rdhwr_cpunum(t0);
+        gen_store_gpr(t0, rt);
+        break;
+    case 1:
+        save_cpu_state(ctx, 1);
+        gen_helper_rdhwr_synci_step(t0);
+        gen_store_gpr(t0, rt);
+        break;
+    case 2:
+        save_cpu_state(ctx, 1);
+        gen_helper_rdhwr_cc(t0);
+        gen_store_gpr(t0, rt);
+        break;
+    case 3:
+        save_cpu_state(ctx, 1);
+        gen_helper_rdhwr_ccres(t0);
+        gen_store_gpr(t0, rt);
+        break;
+    case 29:
+#if defined(CONFIG_USER_ONLY)
+        tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+        gen_store_gpr(t0, rt);
+        break;
+#else
+        /* XXX: Some CPUs implement this in hardware.
+           Not supported yet. */
+#endif
+    default:            /* Invalid */
+        MIPS_INVAL("rdhwr");
+        generate_exception(ctx, EXCP_RI);
+        break;
+    }
+    tcg_temp_free(t0);
+}
+
 static void handle_delay_slot (CPUState *env, DisasContext *ctx,
                                int insn_bytes)
 {
@@ -8999,47 +9056,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
             gen_bshfl(ctx, op2, rt, rd);
             break;
         case OPC_RDHWR:
-            check_insn(env, ctx, ISA_MIPS32R2);
-            {
-                TCGv t0 = tcg_temp_new();
-
-                switch (rd) {
-                case 0:
-                    save_cpu_state(ctx, 1);
-                    gen_helper_rdhwr_cpunum(t0);
-                    gen_store_gpr(t0, rt);
-                    break;
-                case 1:
-                    save_cpu_state(ctx, 1);
-                    gen_helper_rdhwr_synci_step(t0);
-                    gen_store_gpr(t0, rt);
-                    break;
-                case 2:
-                    save_cpu_state(ctx, 1);
-                    gen_helper_rdhwr_cc(t0);
-                    gen_store_gpr(t0, rt);
-                    break;
-                case 3:
-                    save_cpu_state(ctx, 1);
-                    gen_helper_rdhwr_ccres(t0);
-                    gen_store_gpr(t0, rt);
-                    break;
-                case 29:
-#if defined(CONFIG_USER_ONLY)
-                    tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
-                    gen_store_gpr(t0, rt);
-                    break;
-#else
-                    /* XXX: Some CPUs implement this in hardware.
-                       Not supported yet. */
-#endif
-                default:            /* Invalid */
-                    MIPS_INVAL("rdhwr");
-                    generate_exception(ctx, EXCP_RI);
-                    break;
-                }
-                tcg_temp_free(t0);
-            }
+            gen_rdhwr(env, ctx, rt, rd);
             break;
         case OPC_FORK:
             check_insn(env, ctx, ASE_MT);
@@ -9242,12 +9259,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
     case OPC_LDC1:
     case OPC_SWC1:
     case OPC_SDC1:
-        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
-            check_cp1_enabled(ctx);
-            gen_flt_ldst(ctx, op, rt, rs, imm);
-        } else {
-            generate_exception_err(ctx, EXCP_CpU, 1);
-        }
+        gen_cop1_ldst(env, ctx, op, rt, rs, imm);
         break;
 
     case OPC_CP1:
commit d44cff22047651aefe8ea68f173e1dcbb56b07a7
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 10:04:46 2010 -0700

    Fix --enable-user-pie compilation.
    
    We forgot to propagate -fpie to the libdis-user directory.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/configure b/configure
index 653c8d2..72d8924 100755
--- a/configure
+++ b/configure
@@ -2355,6 +2355,9 @@ for d in libdis libdis-user; do
     ln -s $source_path/Makefile.dis $d/Makefile
     echo > $d/config.mak
 done
+if test "$static" = "no" -a "$user_pie" = "yes" ; then
+  echo "QEMU_CFLAGS+=-fpie" > libdis-user/config.mak
+fi
 
 for target in $target_list; do
 target_dir="$target"
commit 940cda94dc01e955b6008c47b782817a1ed3b201
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Sun Jun 6 18:53:10 2010 +0300

    virtio-net: truncating packet
    
    virtio net attempts to peek into virtio queue to
    determine that we have enough space for the complete
    packet to fit. However, it fails to account for space
    consumed by virtio net header when it does this,
    under stress this results in a failure
    with the message 'truncating packet'.
    
    redhat bz 591494.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 6a9d560..06ba481 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -532,16 +532,17 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
     if (!virtio_net_can_receive(&n->nic->nc))
         return -1;
 
-    if (!virtio_net_has_buffers(n, size))
+    /* hdr_len refers to the header we supply to the guest */
+    hdr_len = n->mergeable_rx_bufs ?
+        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
+
+
+    if (!virtio_net_has_buffers(n, size + hdr_len))
         return 0;
 
     if (!receive_filter(n, buf, size))
         return size;
 
-    /* hdr_len refers to the header we supply to the guest */
-    hdr_len = n->mergeable_rx_bufs ?
-        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
-
     offset = i = 0;
 
     while (offset < size) {
@@ -555,7 +556,9 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
             virtqueue_pop(n->rx_vq, &elem) == 0) {
             if (i == 0)
                 return -1;
-            fprintf(stderr, "virtio-net truncating packet\n");
+            fprintf(stderr, "virtio-net truncating packet: "
+                    "offset %zd, size %zd, hdr_len %zd\n",
+                    offset, size, hdr_len);
             exit(1);
         }
 
commit fd1dc858370d9a9ac7ea2512812c3a152ee6484b
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Mon Jun 7 11:54:27 2010 +0200

    microblaze: Make MSR_UM and MSR_VM part of the tb flags
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3316797..ff8c8c8 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -217,8 +217,7 @@ typedef struct CPUMBState {
 #define DRTB_FLAG	(1 << 18)
 #define D_FLAG		(1 << 19)  /* Bit in ESR.  */
 /* TB dependant CPUState.  */
-#define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG \
-                         | DRTE_FLAG | DRTB_FLAG | MSR_EE_FLAG)
+#define IFLAGS_TB_MASK  (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
     uint32_t iflags;
 
     struct {
@@ -323,8 +322,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 {
     *pc = env->sregs[SR_PC];
     *cs_base = 0;
-    env->iflags |= env->sregs[SR_MSR] & MSR_EE;
-    *flags = env->iflags & IFLAGS_TB_MASK;
+    *flags = (env->iflags & IFLAGS_TB_MASK) |
+                 (env->sregs[SR_MSR] & (MSR_UM | MSR_VM | MSR_EE));
 }
 
 #if !defined(CONFIG_USER_ONLY)
commit 7375c86f0b1b1ac6f71a8728c6416c99850b30d9
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Mon Jun 7 11:53:09 2010 +0200

    petlogix-3adsp: Tweak displacement of cmdline and fdt blob.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 93344b1..cdde991 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -185,12 +185,12 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
             boot_info.bootstrap_pc = ddr_base;
         }
 
-        boot_info.cmdline = ddr_base + kernel_size + 8192;
+        boot_info.cmdline = high + 4096;
         if (kernel_cmdline && strlen(kernel_cmdline)) {
             pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
         }
         /* Provide a device-tree.  */
-        boot_info.fdt = boot_info.cmdline + 256;
+        boot_info.fdt = boot_info.cmdline + 4096; 
         petalogix_load_device_tree(boot_info.fdt, ram_size,
                                    0, 0,
                                    kernel_cmdline);
commit 0ffbba357c557d9fa5caf9476878a4b9c155a614
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Jun 4 20:01:07 2010 +0000

    migration-exec: fix OpenBSD build warning
    
    Add include directives to get WIFEXITED() and WEXITSTATUS() macros defined.
    
    Fixes warnings:
      CC    migration-exec.o
    /src/qemu/migration-exec.c: In function `exec_close':
    /src/qemu/migration-exec.c:53: warning: implicit declaration of function `WIFEXITED'
    /src/qemu/migration-exec.c:54: warning: implicit declaration of function `WEXITSTATUS'
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/migration-exec.c b/migration-exec.c
index 93bde62..a8813b4 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -20,6 +20,8 @@
 #include "sysemu.h"
 #include "buffered_file.h"
 #include "block.h"
+#include <sys/types.h>
+#include <sys/wait.h>
 
 //#define DEBUG_MIGRATION_EXEC
 
commit 8c0e6340fb53cb3f94c0f43abb19eb485f30840e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jun 4 16:27:33 2010 +0200

    target-i386: fix decoding of negative 4-byte displacements
    
    Negative four byte displacements need to be sign-extended after
    c086b783eb7a578993d6d2ab62c4c2666800b63d.  Do so.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Acked-by: Richard Henderson  <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 38c6016..708b0a1 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2016,7 +2016,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
             break;
         default:
         case 2:
-            disp = ldl_code(s->pc);
+            disp = (int32_t)ldl_code(s->pc);
             s->pc += 4;
             break;
         }
commit 653dbec7c97cb51d19636423902719e5850da265
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Wed Jun 2 17:46:31 2010 -0300

    block: Fix serial number assignment
    
    We should use 'dinfo->serial' length, 'serial' is a pointer, so
    the serial number length is currently limited to the pointer size.
    
    This fixes https://bugs.launchpad.net/qemu/+bug/584143 and is also
    valid for stable.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index bd9783a..642ce75 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -422,7 +422,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     dinfo->on_write_error = on_write_error;
     dinfo->opts = opts;
     if (serial)
-        strncpy(dinfo->serial, serial, sizeof(serial));
+        strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 
     switch(type) {
commit 666daa68234b5b1758652633cab07d5ca6046a5b
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Jun 2 18:48:27 2010 +0200

    blockdev: Collect block device code in new blockdev.c
    
    Anything that moves hundreds of lines out of vl.c can't be all bad.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 9796dcb..54dec26 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -44,7 +44,7 @@ fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y))
 # system emulation, i.e. a single QEMU executable should support all
 # CPUs and machines.
 
-common-obj-y = $(block-obj-y)
+common-obj-y = $(block-obj-y) blockdev.o
 common-obj-y += $(net-obj-y)
 common-obj-y += $(qobject-obj-y)
 common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
diff --git a/blockdev.c b/blockdev.c
new file mode 100644
index 0000000..bd9783a
--- /dev/null
+++ b/blockdev.c
@@ -0,0 +1,600 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "block.h"
+#include "blockdev.h"
+#include "monitor.h"
+#include "qerror.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "sysemu.h"
+
+struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
+
+QemuOpts *drive_add(const char *file, const char *fmt, ...)
+{
+    va_list ap;
+    char optstr[1024];
+    QemuOpts *opts;
+
+    va_start(ap, fmt);
+    vsnprintf(optstr, sizeof(optstr), fmt, ap);
+    va_end(ap);
+
+    opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
+    if (!opts) {
+        return NULL;
+    }
+    if (file)
+        qemu_opt_set(opts, "file", file);
+    return opts;
+}
+
+DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
+{
+    DriveInfo *dinfo;
+
+    /* seek interface, bus and unit */
+
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->type == type &&
+	    dinfo->bus == bus &&
+	    dinfo->unit == unit)
+            return dinfo;
+    }
+
+    return NULL;
+}
+
+DriveInfo *drive_get_by_id(const char *id)
+{
+    DriveInfo *dinfo;
+
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if (strcmp(id, dinfo->id))
+            continue;
+        return dinfo;
+    }
+    return NULL;
+}
+
+int drive_get_max_bus(BlockInterfaceType type)
+{
+    int max_bus;
+    DriveInfo *dinfo;
+
+    max_bus = -1;
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if(dinfo->type == type &&
+           dinfo->bus > max_bus)
+            max_bus = dinfo->bus;
+    }
+    return max_bus;
+}
+
+const char *drive_get_serial(BlockDriverState *bdrv)
+{
+    DriveInfo *dinfo;
+
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->bdrv == bdrv)
+            return dinfo->serial;
+    }
+
+    return "\0";
+}
+
+BlockInterfaceErrorAction drive_get_on_error(
+    BlockDriverState *bdrv, int is_read)
+{
+    DriveInfo *dinfo;
+
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->bdrv == bdrv)
+            return is_read ? dinfo->on_read_error : dinfo->on_write_error;
+    }
+
+    return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
+}
+
+static void bdrv_format_print(void *opaque, const char *name)
+{
+    fprintf(stderr, " %s", name);
+}
+
+void drive_uninit(DriveInfo *dinfo)
+{
+    qemu_opts_del(dinfo->opts);
+    bdrv_delete(dinfo->bdrv);
+    QTAILQ_REMOVE(&drives, dinfo, next);
+    qemu_free(dinfo);
+}
+
+static int parse_block_error_action(const char *buf, int is_read)
+{
+    if (!strcmp(buf, "ignore")) {
+        return BLOCK_ERR_IGNORE;
+    } else if (!is_read && !strcmp(buf, "enospc")) {
+        return BLOCK_ERR_STOP_ENOSPC;
+    } else if (!strcmp(buf, "stop")) {
+        return BLOCK_ERR_STOP_ANY;
+    } else if (!strcmp(buf, "report")) {
+        return BLOCK_ERR_REPORT;
+    } else {
+        fprintf(stderr, "qemu: '%s' invalid %s error action\n",
+            buf, is_read ? "read" : "write");
+        return -1;
+    }
+}
+
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
+{
+    const char *buf;
+    const char *file = NULL;
+    char devname[128];
+    const char *serial;
+    const char *mediastr = "";
+    BlockInterfaceType type;
+    enum { MEDIA_DISK, MEDIA_CDROM } media;
+    int bus_id, unit_id;
+    int cyls, heads, secs, translation;
+    BlockDriver *drv = NULL;
+    int max_devs;
+    int index;
+    int ro = 0;
+    int bdrv_flags = 0;
+    int on_read_error, on_write_error;
+    const char *devaddr;
+    DriveInfo *dinfo;
+    int snapshot = 0;
+    int ret;
+
+    *fatal_error = 1;
+
+    translation = BIOS_ATA_TRANSLATION_AUTO;
+
+    if (default_to_scsi) {
+        type = IF_SCSI;
+        max_devs = MAX_SCSI_DEVS;
+        pstrcpy(devname, sizeof(devname), "scsi");
+    } else {
+        type = IF_IDE;
+        max_devs = MAX_IDE_DEVS;
+        pstrcpy(devname, sizeof(devname), "ide");
+    }
+    media = MEDIA_DISK;
+
+    /* extract parameters */
+    bus_id  = qemu_opt_get_number(opts, "bus", 0);
+    unit_id = qemu_opt_get_number(opts, "unit", -1);
+    index   = qemu_opt_get_number(opts, "index", -1);
+
+    cyls  = qemu_opt_get_number(opts, "cyls", 0);
+    heads = qemu_opt_get_number(opts, "heads", 0);
+    secs  = qemu_opt_get_number(opts, "secs", 0);
+
+    snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
+    ro = qemu_opt_get_bool(opts, "readonly", 0);
+
+    file = qemu_opt_get(opts, "file");
+    serial = qemu_opt_get(opts, "serial");
+
+    if ((buf = qemu_opt_get(opts, "if")) != NULL) {
+        pstrcpy(devname, sizeof(devname), buf);
+        if (!strcmp(buf, "ide")) {
+	    type = IF_IDE;
+            max_devs = MAX_IDE_DEVS;
+        } else if (!strcmp(buf, "scsi")) {
+	    type = IF_SCSI;
+            max_devs = MAX_SCSI_DEVS;
+        } else if (!strcmp(buf, "floppy")) {
+	    type = IF_FLOPPY;
+            max_devs = 0;
+        } else if (!strcmp(buf, "pflash")) {
+	    type = IF_PFLASH;
+            max_devs = 0;
+	} else if (!strcmp(buf, "mtd")) {
+	    type = IF_MTD;
+            max_devs = 0;
+	} else if (!strcmp(buf, "sd")) {
+	    type = IF_SD;
+            max_devs = 0;
+        } else if (!strcmp(buf, "virtio")) {
+            type = IF_VIRTIO;
+            max_devs = 0;
+	} else if (!strcmp(buf, "xen")) {
+	    type = IF_XEN;
+            max_devs = 0;
+	} else if (!strcmp(buf, "none")) {
+	    type = IF_NONE;
+            max_devs = 0;
+	} else {
+            fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
+            return NULL;
+	}
+    }
+
+    if (cyls || heads || secs) {
+        if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
+            fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
+	    return NULL;
+	}
+        if (heads < 1 || (type == IF_IDE && heads > 16)) {
+            fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
+	    return NULL;
+	}
+        if (secs < 1 || (type == IF_IDE && secs > 63)) {
+            fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
+	    return NULL;
+	}
+    }
+
+    if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
+        if (!cyls) {
+            fprintf(stderr,
+                    "qemu: '%s' trans must be used with cyls,heads and secs\n",
+                    buf);
+            return NULL;
+        }
+        if (!strcmp(buf, "none"))
+            translation = BIOS_ATA_TRANSLATION_NONE;
+        else if (!strcmp(buf, "lba"))
+            translation = BIOS_ATA_TRANSLATION_LBA;
+        else if (!strcmp(buf, "auto"))
+            translation = BIOS_ATA_TRANSLATION_AUTO;
+	else {
+            fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
+	    return NULL;
+	}
+    }
+
+    if ((buf = qemu_opt_get(opts, "media")) != NULL) {
+        if (!strcmp(buf, "disk")) {
+	    media = MEDIA_DISK;
+	} else if (!strcmp(buf, "cdrom")) {
+            if (cyls || secs || heads) {
+                fprintf(stderr,
+                        "qemu: '%s' invalid physical CHS format\n", buf);
+	        return NULL;
+            }
+	    media = MEDIA_CDROM;
+	} else {
+	    fprintf(stderr, "qemu: '%s' invalid media\n", buf);
+	    return NULL;
+	}
+    }
+
+    if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
+        if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
+            bdrv_flags |= BDRV_O_NOCACHE;
+        } else if (!strcmp(buf, "writeback")) {
+            bdrv_flags |= BDRV_O_CACHE_WB;
+        } else if (!strcmp(buf, "unsafe")) {
+            bdrv_flags |= BDRV_O_CACHE_WB;
+            bdrv_flags |= BDRV_O_NO_FLUSH;
+        } else if (!strcmp(buf, "writethrough")) {
+            /* this is the default */
+        } else {
+           fprintf(stderr, "qemu: invalid cache option\n");
+           return NULL;
+        }
+    }
+
+#ifdef CONFIG_LINUX_AIO
+    if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
+        if (!strcmp(buf, "native")) {
+            bdrv_flags |= BDRV_O_NATIVE_AIO;
+        } else if (!strcmp(buf, "threads")) {
+            /* this is the default */
+        } else {
+           fprintf(stderr, "qemu: invalid aio option\n");
+           return NULL;
+        }
+    }
+#endif
+
+    if ((buf = qemu_opt_get(opts, "format")) != NULL) {
+       if (strcmp(buf, "?") == 0) {
+            fprintf(stderr, "qemu: Supported formats:");
+            bdrv_iterate_format(bdrv_format_print, NULL);
+            fprintf(stderr, "\n");
+	    return NULL;
+        }
+        drv = bdrv_find_whitelisted_format(buf);
+        if (!drv) {
+            fprintf(stderr, "qemu: '%s' invalid format\n", buf);
+            return NULL;
+        }
+    }
+
+    on_write_error = BLOCK_ERR_STOP_ENOSPC;
+    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
+        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
+            fprintf(stderr, "werror is no supported by this format\n");
+            return NULL;
+        }
+
+        on_write_error = parse_block_error_action(buf, 0);
+        if (on_write_error < 0) {
+            return NULL;
+        }
+    }
+
+    on_read_error = BLOCK_ERR_REPORT;
+    if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
+        if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
+            fprintf(stderr, "rerror is no supported by this format\n");
+            return NULL;
+        }
+
+        on_read_error = parse_block_error_action(buf, 1);
+        if (on_read_error < 0) {
+            return NULL;
+        }
+    }
+
+    if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
+        if (type != IF_VIRTIO) {
+            fprintf(stderr, "addr is not supported\n");
+            return NULL;
+        }
+    }
+
+    /* compute bus and unit according index */
+
+    if (index != -1) {
+        if (bus_id != 0 || unit_id != -1) {
+            fprintf(stderr,
+                    "qemu: index cannot be used with bus and unit\n");
+            return NULL;
+        }
+        if (max_devs == 0)
+        {
+            unit_id = index;
+            bus_id = 0;
+        } else {
+            unit_id = index % max_devs;
+            bus_id = index / max_devs;
+        }
+    }
+
+    /* if user doesn't specify a unit_id,
+     * try to find the first free
+     */
+
+    if (unit_id == -1) {
+       unit_id = 0;
+       while (drive_get(type, bus_id, unit_id) != NULL) {
+           unit_id++;
+           if (max_devs && unit_id >= max_devs) {
+               unit_id -= max_devs;
+               bus_id++;
+           }
+       }
+    }
+
+    /* check unit id */
+
+    if (max_devs && unit_id >= max_devs) {
+        fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
+                unit_id, max_devs - 1);
+        return NULL;
+    }
+
+    /*
+     * ignore multiple definitions
+     */
+
+    if (drive_get(type, bus_id, unit_id) != NULL) {
+        *fatal_error = 0;
+        return NULL;
+    }
+
+    /* init */
+
+    dinfo = qemu_mallocz(sizeof(*dinfo));
+    if ((buf = qemu_opts_id(opts)) != NULL) {
+        dinfo->id = qemu_strdup(buf);
+    } else {
+        /* no id supplied -> create one */
+        dinfo->id = qemu_mallocz(32);
+        if (type == IF_IDE || type == IF_SCSI)
+            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
+        if (max_devs)
+            snprintf(dinfo->id, 32, "%s%i%s%i",
+                     devname, bus_id, mediastr, unit_id);
+        else
+            snprintf(dinfo->id, 32, "%s%s%i",
+                     devname, mediastr, unit_id);
+    }
+    dinfo->bdrv = bdrv_new(dinfo->id);
+    dinfo->devaddr = devaddr;
+    dinfo->type = type;
+    dinfo->bus = bus_id;
+    dinfo->unit = unit_id;
+    dinfo->on_read_error = on_read_error;
+    dinfo->on_write_error = on_write_error;
+    dinfo->opts = opts;
+    if (serial)
+        strncpy(dinfo->serial, serial, sizeof(serial));
+    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+
+    switch(type) {
+    case IF_IDE:
+    case IF_SCSI:
+    case IF_XEN:
+    case IF_NONE:
+        switch(media) {
+	case MEDIA_DISK:
+            if (cyls != 0) {
+                bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
+                bdrv_set_translation_hint(dinfo->bdrv, translation);
+            }
+	    break;
+	case MEDIA_CDROM:
+            bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
+	    break;
+	}
+        break;
+    case IF_SD:
+        /* FIXME: This isn't really a floppy, but it's a reasonable
+           approximation.  */
+    case IF_FLOPPY:
+        bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
+        break;
+    case IF_PFLASH:
+    case IF_MTD:
+        break;
+    case IF_VIRTIO:
+        /* add virtio block device */
+        opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+        qemu_opt_set(opts, "driver", "virtio-blk-pci");
+        qemu_opt_set(opts, "drive", dinfo->id);
+        if (devaddr)
+            qemu_opt_set(opts, "addr", devaddr);
+        break;
+    case IF_COUNT:
+        abort();
+    }
+    if (!file) {
+        *fatal_error = 0;
+        return NULL;
+    }
+    if (snapshot) {
+        /* always use cache=unsafe with snapshot */
+        bdrv_flags &= ~BDRV_O_CACHE_MASK;
+        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
+    }
+
+    if (media == MEDIA_CDROM) {
+        /* CDROM is fine for any interface, don't check.  */
+        ro = 1;
+    } else if (ro == 1) {
+        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
+            fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
+            return NULL;
+        }
+    }
+
+    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
+
+    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+    if (ret < 0) {
+        fprintf(stderr, "qemu: could not open disk image %s: %s\n",
+                        file, strerror(-ret));
+        return NULL;
+    }
+
+    if (bdrv_key_required(dinfo->bdrv))
+        autostart = 0;
+    *fatal_error = 0;
+    return dinfo;
+}
+
+void do_commit(Monitor *mon, const QDict *qdict)
+{
+    int all_devices;
+    DriveInfo *dinfo;
+    const char *device = qdict_get_str(qdict, "device");
+
+    all_devices = !strcmp(device, "all");
+    QTAILQ_FOREACH(dinfo, &drives, next) {
+        if (!all_devices)
+            if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
+                continue;
+        bdrv_commit(dinfo->bdrv);
+    }
+}
+
+static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
+{
+    if (bdrv_is_inserted(bs)) {
+        if (!force) {
+            if (!bdrv_is_removable(bs)) {
+                qerror_report(QERR_DEVICE_NOT_REMOVABLE,
+                               bdrv_get_device_name(bs));
+                return -1;
+            }
+            if (bdrv_is_locked(bs)) {
+                qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+                return -1;
+            }
+        }
+        bdrv_close(bs);
+    }
+    return 0;
+}
+
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    BlockDriverState *bs;
+    int force = qdict_get_int(qdict, "force");
+    const char *filename = qdict_get_str(qdict, "device");
+
+    bs = bdrv_find(filename);
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, filename);
+        return -1;
+    }
+    return eject_device(mon, bs, force);
+}
+
+int do_block_set_passwd(Monitor *mon, const QDict *qdict,
+                        QObject **ret_data)
+{
+    BlockDriverState *bs;
+    int err;
+
+    bs = bdrv_find(qdict_get_str(qdict, "device"));
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
+        return -1;
+    }
+
+    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+    if (err == -EINVAL) {
+        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+        return -1;
+    } else if (err < 0) {
+        qerror_report(QERR_INVALID_PASSWORD);
+        return -1;
+    }
+
+    return 0;
+}
+
+int do_change_block(Monitor *mon, const char *device,
+                    const char *filename, const char *fmt)
+{
+    BlockDriverState *bs;
+    BlockDriver *drv = NULL;
+    int bdrv_flags;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, device);
+        return -1;
+    }
+    if (fmt) {
+        drv = bdrv_find_whitelisted_format(fmt);
+        if (!drv) {
+            qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
+            return -1;
+        }
+    }
+    if (eject_device(mon, bs, 0) < 0) {
+        return -1;
+    }
+    bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
+    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
+        qerror_report(QERR_OPEN_FILE_FAILED, filename);
+        return -1;
+    }
+    return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+}
diff --git a/blockdev.h b/blockdev.h
new file mode 100644
index 0000000..dfc9de1
--- /dev/null
+++ b/blockdev.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#ifndef BLOCKDEV_H
+#define BLOCKDEV_H
+
+#include "block.h"
+#include "qemu-queue.h"
+
+typedef enum {
+    IF_NONE,
+    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+    IF_COUNT
+} BlockInterfaceType;
+
+typedef enum {
+    BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
+    BLOCK_ERR_STOP_ANY
+} BlockInterfaceErrorAction;
+
+#define BLOCK_SERIAL_STRLEN 20
+
+typedef struct DriveInfo {
+    BlockDriverState *bdrv;
+    char *id;
+    const char *devaddr;
+    BlockInterfaceType type;
+    int bus;
+    int unit;
+    QemuOpts *opts;
+    BlockInterfaceErrorAction on_read_error;
+    BlockInterfaceErrorAction on_write_error;
+    char serial[BLOCK_SERIAL_STRLEN + 1];
+    QTAILQ_ENTRY(DriveInfo) next;
+} DriveInfo;
+
+#define MAX_IDE_DEVS	2
+#define MAX_SCSI_DEVS	7
+
+extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
+
+extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
+extern DriveInfo *drive_get_by_id(const char *id);
+extern int drive_get_max_bus(BlockInterfaceType type);
+extern void drive_uninit(DriveInfo *dinfo);
+extern const char *drive_get_serial(BlockDriverState *bdrv);
+
+extern BlockInterfaceErrorAction drive_get_on_error(
+    BlockDriverState *bdrv, int is_read);
+
+extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
+extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
+                             int *fatal_error);
+
+/* device-hotplug */
+
+DriveInfo *add_init_drive(const char *opts);
+
+void do_commit(Monitor *mon, const QDict *qdict);
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_change_block(Monitor *mon, const char *device,
+                    const char *filename, const char *fmt);
+
+#endif
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958..a87286b 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -21,6 +21,7 @@
 #include "pm_smbus.h"
 #include "pci.h"
 #include "acpi.h"
+#include "sysemu.h"
 
 //#define DEBUG
 
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b53e3c3..31c8d70 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -31,6 +31,7 @@
 #include "pci_host.h"
 #include "rwhandler.h"
 #include "apb_pci.h"
+#include "sysemu.h"
 
 /* debug APB */
 //#define DEBUG_APB
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index a3fe99e..c1a9a56 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -25,8 +25,6 @@
 #include "hw.h"
 #include "boards.h"
 #include "net.h"
-#include "block_int.h"
-#include "sysemu.h"
 
 DriveInfo *add_init_drive(const char *optstr)
 {
diff --git a/hw/fdc.c b/hw/fdc.c
index 6306496..b978957 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -29,7 +29,6 @@
 
 #include "hw.h"
 #include "fdc.h"
-#include "block.h"
 #include "qemu-timer.h"
 #include "isa.h"
 #include "sysbus.h"
diff --git a/hw/fdc.h b/hw/fdc.h
index c48b5e0..b6b3772 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -2,7 +2,7 @@
 #define HW_FDC_H
 
 /* fdc.c */
-#include "sysemu.h"
+#include "blockdev.h"
 #define MAX_FD 2
 
 typedef struct FDCtrl FDCtrl;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 70af1b6..045d18d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -26,8 +26,6 @@
 #include <hw/pc.h>
 #include <hw/pci.h>
 #include <hw/scsi.h>
-#include "block.h"
-#include "block_int.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "dma.h"
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 6231d77..0f9f22e 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -17,7 +17,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <hw/hw.h>
-#include "sysemu.h"
 #include "dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 16d3330..b996dc4 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "net.h"
 #include "devices.h"
+#include "sysemu.h"
 /* For crc32 */
 #include <zlib.h>
 
diff --git a/hw/nand.c b/hw/nand.c
index 40d5a6a..cd7444f 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -13,9 +13,8 @@
 
 # include "hw.h"
 # include "flash.h"
-# include "block.h"
+# include "blockdev.h"
 /* FIXME: Pass block device as an argument.  */
-# include "sysemu.h"
 
 # define NAND_CMD_READ0		0x00
 # define NAND_CMD_READ1		0x01
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e..666c15a 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -17,6 +17,8 @@
  * You should have received a copy of the GNU General Public License along
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
+
+#include "blockdev.h"
 #include "hw.h"
 #include "arm-misc.h"
 #include "omap.h"
diff --git a/hw/onenand.c b/hw/onenand.c
index c1e7e4d..4118db9 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -21,8 +21,7 @@
 #include "qemu-common.h"
 #include "flash.h"
 #include "irq.h"
-#include "sysemu.h"
-#include "block.h"
+#include "blockdev.h"
 
 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
 #define PAGE_SHIFT	11
diff --git a/hw/parallel.c b/hw/parallel.c
index be8e2d5..6b11672 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -26,6 +26,7 @@
 #include "qemu-char.h"
 #include "isa.h"
 #include "pc.h"
+#include "sysemu.h"
 
 //#define DEBUG_PARALLEL
 
diff --git a/hw/pc.c b/hw/pc.c
index 9b85c42..6e7c468 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@
 #include "elf.h"
 #include "multiboot.h"
 #include "mc146818rtc.h"
+#include "sysemu.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 70f563a..dc46846 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -32,6 +32,7 @@
 #include "boards.h"
 #include "ide.h"
 #include "kvm.h"
+#include "sysemu.h"
 
 #define MAX_IDE_BUS 2
 
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index a8f3df1..c39e640 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -26,10 +26,8 @@
 #include "boards.h"
 #include "pci.h"
 #include "net.h"
-#include "sysemu.h"
 #include "pc.h"
 #include "monitor.h"
-#include "block_int.h"
 #include "scsi.h"
 #include "virtio-blk.h"
 #include "qemu-config.h"
diff --git a/hw/pcmcia.h b/hw/pcmcia.h
index cf2db9d..3602923 100644
--- a/hw/pcmcia.h
+++ b/hw/pcmcia.h
@@ -1,7 +1,7 @@
 /* PCMCIA/Cardbus */
 
 #include "qemu-common.h"
-#include "sysemu.h"
+#include "blockdev.h"
 
 typedef struct {
     qemu_irq irq;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 48a6b45..5a8739d 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,4 +1,3 @@
-#include "sysemu.h"
 #include "net.h"
 #include "qdev.h"
 #include "qerror.h"
diff --git a/hw/qdev.h b/hw/qdev.h
index 0ad6c95..be5ad67 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -2,7 +2,7 @@
 #define QDEV_H
 
 #include "hw.h"
-#include "sysemu.h"
+#include "blockdev.h"
 #include "qemu-queue.h"
 #include "qemu-char.h"
 #include "qemu-option.h"
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 383240b..055a94d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -2,7 +2,6 @@
 #include "qemu-error.h"
 #include "scsi.h"
 #include "scsi-defs.h"
-#include "block.h"
 #include "qdev.h"
 
 static struct BusInfo scsi_bus_info = {
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a3559d1..a9bf7d2 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -33,9 +33,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 
 #include "qemu-common.h"
 #include "qemu-error.h"
-#include "block.h"
 #include "scsi.h"
 #include "scsi-defs.h"
+#include "sysemu.h"
 
 #define SCSI_DMA_BUF_SIZE    131072
 #define SCSI_MAX_INQUIRY_LEN 256
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c9aa853..e31060e 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -13,7 +13,6 @@
 
 #include "qemu-common.h"
 #include "qemu-error.h"
-#include "block.h"
 #include "scsi.h"
 
 #ifdef __linux__
diff --git a/hw/serial.c b/hw/serial.c
index 9102edb..c7e4e77 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -27,6 +27,7 @@
 #include "isa.h"
 #include "pc.h"
 #include "qemu-timer.h"
+#include "sysemu.h"
 
 //#define DEBUG_SERIAL
 
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8e6c6e0..228d0a0 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -25,6 +25,7 @@
 #include "hw.h"
 #include "console.h"
 #include "usb.h"
+#include "sysemu.h"
 
 /* HID interface requests */
 #define GET_REPORT   0xa101
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 0ba4a64..003bd8a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,10 +11,10 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "usb.h"
-#include "block.h"
 #include "scsi.h"
 #include "console.h"
 #include "monitor.h"
+#include "sysemu.h"
 
 //#define DEBUG_MSD
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 80d51c4..cdcb492 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -12,9 +12,7 @@
  */
 
 #include <qemu-common.h>
-#include <sysemu.h>
 #include "virtio-blk.h"
-#include "block_int.h"
 #ifdef __linux__
 # include <scsi/sg.h>
 #endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 7ddf612..e101fa0 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,7 +22,6 @@
 #include "qemu-error.h"
 #include "msix.h"
 #include "net.h"
-#include "block_int.h"
 #include "loader.h"
 #include "kvm.h"
 
diff --git a/monitor.c b/monitor.c
index 15b53b9..57f24ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -38,7 +38,7 @@
 #include "monitor.h"
 #include "readline.h"
 #include "console.h"
-#include "block.h"
+#include "blockdev.h"
 #include "audio/audio.h"
 #include "disas.h"
 #include "balloon.h"
@@ -530,21 +530,6 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
     help_cmd(mon, qdict_get_try_str(qdict, "name"));
 }
 
-static void do_commit(Monitor *mon, const QDict *qdict)
-{
-    int all_devices;
-    DriveInfo *dinfo;
-    const char *device = qdict_get_str(qdict, "device");
-
-    all_devices = !strcmp(device, "all");
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (!all_devices)
-            if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
-                continue;
-        bdrv_commit(dinfo->bdrv);
-    }
-}
-
 static void user_monitor_complete(void *opaque, QObject *ret_data)
 {
     MonitorCompletionData *data = (MonitorCompletionData *)opaque; 
@@ -949,93 +934,6 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return 0;
 }
 
-static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
-{
-    if (bdrv_is_inserted(bs)) {
-        if (!force) {
-            if (!bdrv_is_removable(bs)) {
-                qerror_report(QERR_DEVICE_NOT_REMOVABLE,
-                               bdrv_get_device_name(bs));
-                return -1;
-            }
-            if (bdrv_is_locked(bs)) {
-                qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
-                return -1;
-            }
-        }
-        bdrv_close(bs);
-    }
-    return 0;
-}
-
-static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
-    BlockDriverState *bs;
-    int force = qdict_get_int(qdict, "force");
-    const char *filename = qdict_get_str(qdict, "device");
-
-    bs = bdrv_find(filename);
-    if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, filename);
-        return -1;
-    }
-    return eject_device(mon, bs, force);
-}
-
-static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
-                                QObject **ret_data)
-{
-    BlockDriverState *bs;
-    int err;
-
-    bs = bdrv_find(qdict_get_str(qdict, "device"));
-    if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
-        return -1;
-    }
-
-    err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
-    if (err == -EINVAL) {
-        qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
-        return -1;
-    } else if (err < 0) {
-        qerror_report(QERR_INVALID_PASSWORD);
-        return -1;
-    }
-
-    return 0;
-}
-
-static int do_change_block(Monitor *mon, const char *device,
-                           const char *filename, const char *fmt)
-{
-    BlockDriverState *bs;
-    BlockDriver *drv = NULL;
-    int bdrv_flags;
-
-    bs = bdrv_find(device);
-    if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, device);
-        return -1;
-    }
-    if (fmt) {
-        drv = bdrv_find_whitelisted_format(fmt);
-        if (!drv) {
-            qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
-            return -1;
-        }
-    }
-    if (eject_device(mon, bs, 0) < 0) {
-        return -1;
-    }
-    bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
-    if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
-        qerror_report(QERR_OPEN_FILE_FAILED, filename);
-        return -1;
-    }
-    return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
-}
-
 static int change_vnc_password(const char *password)
 {
     if (vnc_display_password(NULL, password) < 0) {
diff --git a/qemu-char.c b/qemu-char.c
index faaf624..87628ea 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
-#include "block.h"
 #include "hw/usb.h"
 #include "hw/baum.h"
 #include "hw/msmouse.h"
diff --git a/savevm.c b/savevm.c
index af92ba2..1173a22 100644
--- a/savevm.c
+++ b/savevm.c
@@ -77,7 +77,7 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
-#include "block.h"
+#include "blockdev.h"
 #include "audio/audio.h"
 #include "migration.h"
 #include "qemu_socket.h"
diff --git a/sysemu.h b/sysemu.h
index dce13c1..5fa45ed 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -147,55 +147,6 @@ extern int nb_option_roms;
 extern const char *prom_envs[MAX_PROM_ENVS];
 extern unsigned int nb_prom_envs;
 
-typedef enum {
-    IF_NONE,
-    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
-    IF_COUNT
-} BlockInterfaceType;
-
-typedef enum {
-    BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
-    BLOCK_ERR_STOP_ANY
-} BlockInterfaceErrorAction;
-
-#define BLOCK_SERIAL_STRLEN 20
-
-typedef struct DriveInfo {
-    BlockDriverState *bdrv;
-    char *id;
-    const char *devaddr;
-    BlockInterfaceType type;
-    int bus;
-    int unit;
-    QemuOpts *opts;
-    BlockInterfaceErrorAction on_read_error;
-    BlockInterfaceErrorAction on_write_error;
-    char serial[BLOCK_SERIAL_STRLEN + 1];
-    QTAILQ_ENTRY(DriveInfo) next;
-} DriveInfo;
-
-#define MAX_IDE_DEVS	2
-#define MAX_SCSI_DEVS	7
-
-extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
-
-extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
-extern DriveInfo *drive_get_by_id(const char *id);
-extern int drive_get_max_bus(BlockInterfaceType type);
-extern void drive_uninit(DriveInfo *dinfo);
-extern const char *drive_get_serial(BlockDriverState *bdrv);
-
-extern BlockInterfaceErrorAction drive_get_on_error(
-    BlockDriverState *bdrv, int is_read);
-
-extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
-extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
-                             int *fatal_error);
-
-/* device-hotplug */
-
-DriveInfo *add_init_drive(const char *opts);
-
 /* pci-hotplug */
 void pci_device_hot_add(Monitor *mon, const QDict *qdict);
 void drive_hot_add(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index db1fefd..0a9862f 100644
--- a/vl.c
+++ b/vl.c
@@ -140,7 +140,7 @@ int main(int argc, char **argv)
 #include "qemu-char.h"
 #include "cache-utils.h"
 #include "block.h"
-#include "block_int.h"
+#include "blockdev.h"
 #include "block-migration.h"
 #include "dma.h"
 #include "audio/audio.h"
@@ -172,7 +172,6 @@ int main(int argc, char **argv)
 
 static const char *data_dir;
 const char *bios_name = NULL;
-struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 DisplayType display_type = DT_DEFAULT;
 const char* keyboard_layout = NULL;
@@ -651,486 +650,6 @@ static int bt_parse(const char *opt)
 #define MTD_ALIAS "if=mtd"
 #define SD_ALIAS "index=0,if=sd"
 
-QemuOpts *drive_add(const char *file, const char *fmt, ...)
-{
-    va_list ap;
-    char optstr[1024];
-    QemuOpts *opts;
-
-    va_start(ap, fmt);
-    vsnprintf(optstr, sizeof(optstr), fmt, ap);
-    va_end(ap);
-
-    opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
-    if (!opts) {
-        return NULL;
-    }
-    if (file)
-        qemu_opt_set(opts, "file", file);
-    return opts;
-}
-
-DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
-{
-    DriveInfo *dinfo;
-
-    /* seek interface, bus and unit */
-
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (dinfo->type == type &&
-	    dinfo->bus == bus &&
-	    dinfo->unit == unit)
-            return dinfo;
-    }
-
-    return NULL;
-}
-
-DriveInfo *drive_get_by_id(const char *id)
-{
-    DriveInfo *dinfo;
-
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (strcmp(id, dinfo->id))
-            continue;
-        return dinfo;
-    }
-    return NULL;
-}
-
-int drive_get_max_bus(BlockInterfaceType type)
-{
-    int max_bus;
-    DriveInfo *dinfo;
-
-    max_bus = -1;
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if(dinfo->type == type &&
-           dinfo->bus > max_bus)
-            max_bus = dinfo->bus;
-    }
-    return max_bus;
-}
-
-const char *drive_get_serial(BlockDriverState *bdrv)
-{
-    DriveInfo *dinfo;
-
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (dinfo->bdrv == bdrv)
-            return dinfo->serial;
-    }
-
-    return "\0";
-}
-
-BlockInterfaceErrorAction drive_get_on_error(
-    BlockDriverState *bdrv, int is_read)
-{
-    DriveInfo *dinfo;
-
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (dinfo->bdrv == bdrv)
-            return is_read ? dinfo->on_read_error : dinfo->on_write_error;
-    }
-
-    return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
-}
-
-static void bdrv_format_print(void *opaque, const char *name)
-{
-    fprintf(stderr, " %s", name);
-}
-
-void drive_uninit(DriveInfo *dinfo)
-{
-    qemu_opts_del(dinfo->opts);
-    bdrv_delete(dinfo->bdrv);
-    QTAILQ_REMOVE(&drives, dinfo, next);
-    qemu_free(dinfo);
-}
-
-static int parse_block_error_action(const char *buf, int is_read)
-{
-    if (!strcmp(buf, "ignore")) {
-        return BLOCK_ERR_IGNORE;
-    } else if (!is_read && !strcmp(buf, "enospc")) {
-        return BLOCK_ERR_STOP_ENOSPC;
-    } else if (!strcmp(buf, "stop")) {
-        return BLOCK_ERR_STOP_ANY;
-    } else if (!strcmp(buf, "report")) {
-        return BLOCK_ERR_REPORT;
-    } else {
-        fprintf(stderr, "qemu: '%s' invalid %s error action\n",
-            buf, is_read ? "read" : "write");
-        return -1;
-    }
-}
-
-DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
-{
-    const char *buf;
-    const char *file = NULL;
-    char devname[128];
-    const char *serial;
-    const char *mediastr = "";
-    BlockInterfaceType type;
-    enum { MEDIA_DISK, MEDIA_CDROM } media;
-    int bus_id, unit_id;
-    int cyls, heads, secs, translation;
-    BlockDriver *drv = NULL;
-    int max_devs;
-    int index;
-    int ro = 0;
-    int bdrv_flags = 0;
-    int on_read_error, on_write_error;
-    const char *devaddr;
-    DriveInfo *dinfo;
-    int snapshot = 0;
-    int ret;
-
-    *fatal_error = 1;
-
-    translation = BIOS_ATA_TRANSLATION_AUTO;
-
-    if (default_to_scsi) {
-        type = IF_SCSI;
-        max_devs = MAX_SCSI_DEVS;
-        pstrcpy(devname, sizeof(devname), "scsi");
-    } else {
-        type = IF_IDE;
-        max_devs = MAX_IDE_DEVS;
-        pstrcpy(devname, sizeof(devname), "ide");
-    }
-    media = MEDIA_DISK;
-
-    /* extract parameters */
-    bus_id  = qemu_opt_get_number(opts, "bus", 0);
-    unit_id = qemu_opt_get_number(opts, "unit", -1);
-    index   = qemu_opt_get_number(opts, "index", -1);
-
-    cyls  = qemu_opt_get_number(opts, "cyls", 0);
-    heads = qemu_opt_get_number(opts, "heads", 0);
-    secs  = qemu_opt_get_number(opts, "secs", 0);
-
-    snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
-    ro = qemu_opt_get_bool(opts, "readonly", 0);
-
-    file = qemu_opt_get(opts, "file");
-    serial = qemu_opt_get(opts, "serial");
-
-    if ((buf = qemu_opt_get(opts, "if")) != NULL) {
-        pstrcpy(devname, sizeof(devname), buf);
-        if (!strcmp(buf, "ide")) {
-	    type = IF_IDE;
-            max_devs = MAX_IDE_DEVS;
-        } else if (!strcmp(buf, "scsi")) {
-	    type = IF_SCSI;
-            max_devs = MAX_SCSI_DEVS;
-        } else if (!strcmp(buf, "floppy")) {
-	    type = IF_FLOPPY;
-            max_devs = 0;
-        } else if (!strcmp(buf, "pflash")) {
-	    type = IF_PFLASH;
-            max_devs = 0;
-	} else if (!strcmp(buf, "mtd")) {
-	    type = IF_MTD;
-            max_devs = 0;
-	} else if (!strcmp(buf, "sd")) {
-	    type = IF_SD;
-            max_devs = 0;
-        } else if (!strcmp(buf, "virtio")) {
-            type = IF_VIRTIO;
-            max_devs = 0;
-	} else if (!strcmp(buf, "xen")) {
-	    type = IF_XEN;
-            max_devs = 0;
-	} else if (!strcmp(buf, "none")) {
-	    type = IF_NONE;
-            max_devs = 0;
-	} else {
-            fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
-            return NULL;
-	}
-    }
-
-    if (cyls || heads || secs) {
-        if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
-            fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
-	    return NULL;
-	}
-        if (heads < 1 || (type == IF_IDE && heads > 16)) {
-            fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
-	    return NULL;
-	}
-        if (secs < 1 || (type == IF_IDE && secs > 63)) {
-            fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
-	    return NULL;
-	}
-    }
-
-    if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
-        if (!cyls) {
-            fprintf(stderr,
-                    "qemu: '%s' trans must be used with cyls,heads and secs\n",
-                    buf);
-            return NULL;
-        }
-        if (!strcmp(buf, "none"))
-            translation = BIOS_ATA_TRANSLATION_NONE;
-        else if (!strcmp(buf, "lba"))
-            translation = BIOS_ATA_TRANSLATION_LBA;
-        else if (!strcmp(buf, "auto"))
-            translation = BIOS_ATA_TRANSLATION_AUTO;
-	else {
-            fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
-	    return NULL;
-	}
-    }
-
-    if ((buf = qemu_opt_get(opts, "media")) != NULL) {
-        if (!strcmp(buf, "disk")) {
-	    media = MEDIA_DISK;
-	} else if (!strcmp(buf, "cdrom")) {
-            if (cyls || secs || heads) {
-                fprintf(stderr,
-                        "qemu: '%s' invalid physical CHS format\n", buf);
-	        return NULL;
-            }
-	    media = MEDIA_CDROM;
-	} else {
-	    fprintf(stderr, "qemu: '%s' invalid media\n", buf);
-	    return NULL;
-	}
-    }
-
-    if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
-        if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
-            bdrv_flags |= BDRV_O_NOCACHE;
-        } else if (!strcmp(buf, "writeback")) {
-            bdrv_flags |= BDRV_O_CACHE_WB;
-        } else if (!strcmp(buf, "unsafe")) {
-            bdrv_flags |= BDRV_O_CACHE_WB;
-            bdrv_flags |= BDRV_O_NO_FLUSH;
-        } else if (!strcmp(buf, "writethrough")) {
-            /* this is the default */
-        } else {
-           fprintf(stderr, "qemu: invalid cache option\n");
-           return NULL;
-        }
-    }
-
-#ifdef CONFIG_LINUX_AIO
-    if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
-        if (!strcmp(buf, "native")) {
-            bdrv_flags |= BDRV_O_NATIVE_AIO;
-        } else if (!strcmp(buf, "threads")) {
-            /* this is the default */
-        } else {
-           fprintf(stderr, "qemu: invalid aio option\n");
-           return NULL;
-        }
-    }
-#endif
-
-    if ((buf = qemu_opt_get(opts, "format")) != NULL) {
-       if (strcmp(buf, "?") == 0) {
-            fprintf(stderr, "qemu: Supported formats:");
-            bdrv_iterate_format(bdrv_format_print, NULL);
-            fprintf(stderr, "\n");
-	    return NULL;
-        }
-        drv = bdrv_find_whitelisted_format(buf);
-        if (!drv) {
-            fprintf(stderr, "qemu: '%s' invalid format\n", buf);
-            return NULL;
-        }
-    }
-
-    on_write_error = BLOCK_ERR_STOP_ENOSPC;
-    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
-        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
-            fprintf(stderr, "werror is no supported by this format\n");
-            return NULL;
-        }
-
-        on_write_error = parse_block_error_action(buf, 0);
-        if (on_write_error < 0) {
-            return NULL;
-        }
-    }
-
-    on_read_error = BLOCK_ERR_REPORT;
-    if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
-        if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
-            fprintf(stderr, "rerror is no supported by this format\n");
-            return NULL;
-        }
-
-        on_read_error = parse_block_error_action(buf, 1);
-        if (on_read_error < 0) {
-            return NULL;
-        }
-    }
-
-    if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
-        if (type != IF_VIRTIO) {
-            fprintf(stderr, "addr is not supported\n");
-            return NULL;
-        }
-    }
-
-    /* compute bus and unit according index */
-
-    if (index != -1) {
-        if (bus_id != 0 || unit_id != -1) {
-            fprintf(stderr,
-                    "qemu: index cannot be used with bus and unit\n");
-            return NULL;
-        }
-        if (max_devs == 0)
-        {
-            unit_id = index;
-            bus_id = 0;
-        } else {
-            unit_id = index % max_devs;
-            bus_id = index / max_devs;
-        }
-    }
-
-    /* if user doesn't specify a unit_id,
-     * try to find the first free
-     */
-
-    if (unit_id == -1) {
-       unit_id = 0;
-       while (drive_get(type, bus_id, unit_id) != NULL) {
-           unit_id++;
-           if (max_devs && unit_id >= max_devs) {
-               unit_id -= max_devs;
-               bus_id++;
-           }
-       }
-    }
-
-    /* check unit id */
-
-    if (max_devs && unit_id >= max_devs) {
-        fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
-                unit_id, max_devs - 1);
-        return NULL;
-    }
-
-    /*
-     * ignore multiple definitions
-     */
-
-    if (drive_get(type, bus_id, unit_id) != NULL) {
-        *fatal_error = 0;
-        return NULL;
-    }
-
-    /* init */
-
-    dinfo = qemu_mallocz(sizeof(*dinfo));
-    if ((buf = qemu_opts_id(opts)) != NULL) {
-        dinfo->id = qemu_strdup(buf);
-    } else {
-        /* no id supplied -> create one */
-        dinfo->id = qemu_mallocz(32);
-        if (type == IF_IDE || type == IF_SCSI)
-            mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-        if (max_devs)
-            snprintf(dinfo->id, 32, "%s%i%s%i",
-                     devname, bus_id, mediastr, unit_id);
-        else
-            snprintf(dinfo->id, 32, "%s%s%i",
-                     devname, mediastr, unit_id);
-    }
-    dinfo->bdrv = bdrv_new(dinfo->id);
-    dinfo->devaddr = devaddr;
-    dinfo->type = type;
-    dinfo->bus = bus_id;
-    dinfo->unit = unit_id;
-    dinfo->on_read_error = on_read_error;
-    dinfo->on_write_error = on_write_error;
-    dinfo->opts = opts;
-    if (serial)
-        strncpy(dinfo->serial, serial, sizeof(serial));
-    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
-
-    switch(type) {
-    case IF_IDE:
-    case IF_SCSI:
-    case IF_XEN:
-    case IF_NONE:
-        switch(media) {
-	case MEDIA_DISK:
-            if (cyls != 0) {
-                bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
-                bdrv_set_translation_hint(dinfo->bdrv, translation);
-            }
-	    break;
-	case MEDIA_CDROM:
-            bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
-	    break;
-	}
-        break;
-    case IF_SD:
-        /* FIXME: This isn't really a floppy, but it's a reasonable
-           approximation.  */
-    case IF_FLOPPY:
-        bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
-        break;
-    case IF_PFLASH:
-    case IF_MTD:
-        break;
-    case IF_VIRTIO:
-        /* add virtio block device */
-        opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
-        qemu_opt_set(opts, "driver", "virtio-blk-pci");
-        qemu_opt_set(opts, "drive", dinfo->id);
-        if (devaddr)
-            qemu_opt_set(opts, "addr", devaddr);
-        break;
-    case IF_COUNT:
-        abort();
-    }
-    if (!file) {
-        *fatal_error = 0;
-        return NULL;
-    }
-    if (snapshot) {
-        /* always use cache=unsafe with snapshot */
-        bdrv_flags &= ~BDRV_O_CACHE_MASK;
-        bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
-    }
-
-    if (media == MEDIA_CDROM) {
-        /* CDROM is fine for any interface, don't check.  */
-        ro = 1;
-    } else if (ro == 1) {
-        if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
-            fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
-            return NULL;
-        }
-    }
-
-    bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
-
-    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
-    if (ret < 0) {
-        fprintf(stderr, "qemu: could not open disk image %s: %s\n",
-                        file, strerror(-ret));
-        return NULL;
-    }
-
-    if (bdrv_key_required(dinfo->bdrv))
-        autostart = 0;
-    *fatal_error = 0;
-    return dinfo;
-}
-
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
     int *use_scsi = opaque;
commit 7b370f513002b340a383fac961dc8c6fdf39eddc
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Jun 2 13:31:56 2010 +0200

    qdev: Move declaration of qdev_init_bdrv() into qdev.h
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/pl181.c b/hw/pl181.c
index 1924053..85cadc4 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 #include "sd.h"
-#include "sysemu.h"
 
 //#define DEBUG_PL181 1
 
diff --git a/hw/qdev.h b/hw/qdev.h
index 51a24e2..0ad6c95 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -125,6 +125,8 @@ void qdev_machine_creation_done(void);
 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
 void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
 
+BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
+
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
 /*** Device API.  ***/
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 5e74e5d..96b33ed 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -9,7 +9,6 @@
 
 #include "ssi.h"
 #include "sd.h"
-#include "sysemu.h"
 
 //#define DEBUG_SSI_SD 1
 
diff --git a/sysemu.h b/sysemu.h
index 46a1b2f..dce13c1 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -188,8 +188,6 @@ extern const char *drive_get_serial(BlockDriverState *bdrv);
 extern BlockInterfaceErrorAction drive_get_on_error(
     BlockDriverState *bdrv, int is_read);
 
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
-
 extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
 extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
                              int *fatal_error);
commit a803cb8eb8ada1add74f1b393b8a553a7e7f3acf
Author: Markus Armbruster <armbru at redhat.com>
Date:   Wed Jun 2 13:31:55 2010 +0200

    blockdev: Hide QEMUMachine from drive_init()
    
    To pave the way for moving it out of vl.c.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 9cc8376..a3fe99e 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -38,7 +38,7 @@ DriveInfo *add_init_drive(const char *optstr)
     if (!opts)
         return NULL;
 
-    dinfo = drive_init(opts, current_machine, &fatal_error);
+    dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
     if (!dinfo) {
         qemu_opts_del(opts);
         return NULL;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index c1c2537..0ba4a64 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(const char *filename)
     qemu_opt_set(opts, "if", "none");
 
     /* create host drive */
-    dinfo = drive_init(opts, NULL, &fatal_error);
+    dinfo = drive_init(opts, 0, &fatal_error);
     if (!dinfo) {
         qemu_opts_del(opts);
         return NULL;
diff --git a/sysemu.h b/sysemu.h
index fd83b7d..46a1b2f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -191,7 +191,8 @@ extern BlockInterfaceErrorAction drive_get_on_error(
 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
 
 extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
-extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
+extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
+                             int *fatal_error);
 
 /* device-hotplug */
 
diff --git a/vl.c b/vl.c
index 551138f..db1fefd 100644
--- a/vl.c
+++ b/vl.c
@@ -767,8 +767,7 @@ static int parse_block_error_action(const char *buf, int is_read)
     }
 }
 
-DriveInfo *drive_init(QemuOpts *opts, void *opaque,
-                      int *fatal_error)
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 {
     const char *buf;
     const char *file = NULL;
@@ -780,7 +779,6 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     int bus_id, unit_id;
     int cyls, heads, secs, translation;
     BlockDriver *drv = NULL;
-    QEMUMachine *machine = opaque;
     int max_devs;
     int index;
     int ro = 0;
@@ -795,7 +793,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
     translation = BIOS_ATA_TRANSLATION_AUTO;
 
-    if (machine && machine->use_scsi) {
+    if (default_to_scsi) {
         type = IF_SCSI;
         max_devs = MAX_SCSI_DEVS;
         pstrcpy(devname, sizeof(devname), "scsi");
@@ -1135,10 +1133,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
-    QEMUMachine *machine = opaque;
+    int *use_scsi = opaque;
     int fatal_error = 0;
 
-    if (drive_init(opts, machine, &fatal_error) == NULL) {
+    if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
         if (fatal_error)
             return 1;
     }
@@ -3641,7 +3639,7 @@ int main(int argc, char **argv, char **envp)
     /* open the virtual block devices */
     if (snapshot)
         qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
-    if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0)
+    if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
     register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, 
commit 7cdb1f6d305e1000b5f882257cbee71b8bb08ef5
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri May 28 11:44:58 2010 +0900

    block: call the snapshot handlers of the protocol drivers
    
    When snapshot handlers are not defined in the format driver, it is
    better to call the ones of the protocol driver.  This enables us to
    implement snapshot support in the protocol driver.
    
    We need to call bdrv_close() and bdrv_open() handlers of the format
    driver before and after bdrv_snapshot_goto() call of the protocol.  It is
    because the contents of the block driver state may need to be changed
    after loading vmstate.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index b1ef85c..cacf11b 100644
--- a/block.c
+++ b/block.c
@@ -1631,9 +1631,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_save_vmstate)
-        return -ENOTSUP;
-    return drv->bdrv_save_vmstate(bs, buf, pos, size);
+    if (drv->bdrv_save_vmstate)
+        return drv->bdrv_save_vmstate(bs, buf, pos, size);
+    if (bs->file)
+        return bdrv_save_vmstate(bs->file, buf, pos, size);
+    return -ENOTSUP;
 }
 
 int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
@@ -1642,9 +1644,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_load_vmstate)
-        return -ENOTSUP;
-    return drv->bdrv_load_vmstate(bs, buf, pos, size);
+    if (drv->bdrv_load_vmstate)
+        return drv->bdrv_load_vmstate(bs, buf, pos, size);
+    if (bs->file)
+        return bdrv_load_vmstate(bs->file, buf, pos, size);
+    return -ENOTSUP;
 }
 
 void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
@@ -1668,20 +1672,37 @@ int bdrv_snapshot_create(BlockDriverState *bs,
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_snapshot_create)
-        return -ENOTSUP;
-    return drv->bdrv_snapshot_create(bs, sn_info);
+    if (drv->bdrv_snapshot_create)
+        return drv->bdrv_snapshot_create(bs, sn_info);
+    if (bs->file)
+        return bdrv_snapshot_create(bs->file, sn_info);
+    return -ENOTSUP;
 }
 
 int bdrv_snapshot_goto(BlockDriverState *bs,
                        const char *snapshot_id)
 {
     BlockDriver *drv = bs->drv;
+    int ret, open_ret;
+
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_snapshot_goto)
-        return -ENOTSUP;
-    return drv->bdrv_snapshot_goto(bs, snapshot_id);
+    if (drv->bdrv_snapshot_goto)
+        return drv->bdrv_snapshot_goto(bs, snapshot_id);
+
+    if (bs->file) {
+        drv->bdrv_close(bs);
+        ret = bdrv_snapshot_goto(bs->file, snapshot_id);
+        open_ret = drv->bdrv_open(bs, bs->open_flags);
+        if (open_ret < 0) {
+            bdrv_delete(bs->file);
+            bs->drv = NULL;
+            return open_ret;
+        }
+        return ret;
+    }
+
+    return -ENOTSUP;
 }
 
 int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
@@ -1689,9 +1710,11 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_snapshot_delete)
-        return -ENOTSUP;
-    return drv->bdrv_snapshot_delete(bs, snapshot_id);
+    if (drv->bdrv_snapshot_delete)
+        return drv->bdrv_snapshot_delete(bs, snapshot_id);
+    if (bs->file)
+        return bdrv_snapshot_delete(bs->file, snapshot_id);
+    return -ENOTSUP;
 }
 
 int bdrv_snapshot_list(BlockDriverState *bs,
@@ -1700,9 +1723,11 @@ int bdrv_snapshot_list(BlockDriverState *bs,
     BlockDriver *drv = bs->drv;
     if (!drv)
         return -ENOMEDIUM;
-    if (!drv->bdrv_snapshot_list)
-        return -ENOTSUP;
-    return drv->bdrv_snapshot_list(bs, psn_info);
+    if (drv->bdrv_snapshot_list)
+        return drv->bdrv_snapshot_list(bs, psn_info);
+    if (bs->file)
+        return bdrv_snapshot_list(bs->file, psn_info);
+    return -ENOTSUP;
 }
 
 #define NB_SUFFIXES 4
commit 2bc93fed76c89f7adaa0e5bb357dcdc6c2b097a8
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri May 28 11:44:57 2010 +0900

    close all the block drivers before the qemu process exits
    
    This patch calls the close handler of the block driver before the qemu
    process exits.
    
    This is necessary because the sheepdog block driver releases the lock
    of VM images in the close handler.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index ecd9867..b1ef85c 100644
--- a/block.c
+++ b/block.c
@@ -648,6 +648,15 @@ void bdrv_close(BlockDriverState *bs)
     }
 }
 
+void bdrv_close_all(void)
+{
+    BlockDriverState *bs;
+
+    QTAILQ_FOREACH(bs, &bdrv_states, list) {
+        bdrv_close(bs);
+    }
+}
+
 void bdrv_delete(BlockDriverState *bs)
 {
     /* remove from list, if necessary */
diff --git a/block.h b/block.h
index 756670d..25744b1 100644
--- a/block.h
+++ b/block.h
@@ -123,6 +123,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
 /* Ensure contents are flushed to disk.  */
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
+void bdrv_close_all(void);
 
 int bdrv_has_zero_init(BlockDriverState *bs);
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
diff --git a/vl.c b/vl.c
index 2769d1a..551138f 100644
--- a/vl.c
+++ b/vl.c
@@ -1991,6 +1991,7 @@ static void main_loop(void)
             vm_stop(r);
         }
     }
+    bdrv_close_all();
     pause_all_vcpus();
 }
 
commit 08a00559f00975cebcb3f844fe7c708d65b6a3b3
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Jun 1 18:37:31 2010 +0200

    block: Assume raw for drives without media
    
    qemu -cdrom /dev/cdrom with an empty CD-ROM drive doesn't work any more because
    we try to guess the format and when this fails (because there is no medium) we
    exit with an error message.
    
    This patch should restore the old behaviour by assuming raw format for such
    drives.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 9c43332..ecd9867 100644
--- a/block.c
+++ b/block.c
@@ -331,8 +331,8 @@ static BlockDriver *find_image_format(const char *filename)
     if (ret < 0)
         return NULL;
 
-    /* Return the raw BlockDriver * to scsi-generic devices */
-    if (bs->sg) {
+    /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
+    if (bs->sg || !bdrv_is_inserted(bs)) {
         bdrv_delete(bs);
         return bdrv_find_format("raw");
     }
commit 236f1f672ca4b5dea70c0c101036224297c53895
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Jun 1 13:20:57 2010 +0200

    Fix error message in drive_init
    
    The real error is the return value of bdrv_open. errno might be overwritten or
    not even set to that value in the first place.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/vl.c b/vl.c
index 76a9b25..2769d1a 100644
--- a/vl.c
+++ b/vl.c
@@ -789,6 +789,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
     const char *devaddr;
     DriveInfo *dinfo;
     int snapshot = 0;
+    int ret;
 
     *fatal_error = 1;
 
@@ -1119,9 +1120,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
 
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
-    if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
+    ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+    if (ret < 0) {
         fprintf(stderr, "qemu: could not open disk image %s: %s\n",
-                        file, strerror(errno));
+                        file, strerror(-ret));
         return NULL;
     }
 
commit 552fee931bf52bf60f4210f607a78f415000f015
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:35 2010 +0200

    scsi: Fix info qtree for scsi-disk.ver
    
    Show the actual default value instead of <null> when the property has
    not been set.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index e8c066a..a3559d1 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -462,8 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
     }
     memcpy(&outbuf[8], "QEMU    ", 8);
     memset(&outbuf[32], 0, 4);
-    memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
-           MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
+    memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
     /*
      * We claim conformance to SPC-3, which is required for guests
      * to ask for modern features like READ CAPACITY(16) or the
@@ -1066,6 +1065,10 @@ static int scsi_disk_initfn(SCSIDevice *dev)
         }
     }
 
+    if (!s->version) {
+        s->version = qemu_strdup(QEMU_VERSION);
+    }
+
     if (bdrv_is_sg(s->bs)) {
         error_report("scsi-disk: unwanted /dev/sg*");
         return -1;
commit a0fef654f6dec1348a074a17a6b809d0ba77b34e
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:34 2010 +0200

    scsi: Turn drive serial into a qdev property scsi-disk.serial
    
    It needs to be a qdev property, because it belongs to the drive's
    guest part.
    
    Bonus: info qtree now shows the serial number.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4d20919..e8c066a 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -66,6 +66,7 @@ struct SCSIDiskState
     uint64_t max_lba;
     QEMUBH *bh;
     char *version;
+    char *serial;
 };
 
 static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
@@ -359,9 +360,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
 
         case 0x80: /* Device serial number, optional */
         {
-            const char *serial = req->dev->conf.dinfo->serial ?
-                req->dev->conf.dinfo->serial : "0";
-            int l = strlen(serial);
+            int l = strlen(s->serial);
 
             if (l > req->cmd.xfer)
                 l = req->cmd.xfer;
@@ -371,7 +370,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
             DPRINTF("Inquiry EVPD[Serial number] "
                     "buffer size %zd\n", req->cmd.xfer);
             outbuf[buflen++] = l;
-            memcpy(outbuf+buflen, serial, l);
+            memcpy(outbuf+buflen, s->serial, l);
             buflen += l;
             break;
         }
@@ -1058,6 +1057,15 @@ static int scsi_disk_initfn(SCSIDevice *dev)
     }
     s->bs = s->qdev.conf.dinfo->bdrv;
 
+    if (!s->serial) {
+        if (*dev->conf.dinfo->serial) {
+            /* try to fall back to value set with legacy -drive serial=... */
+            s->serial = qemu_strdup(dev->conf.dinfo->serial);
+        } else {
+            s->serial = qemu_strdup("0");
+        }
+    }
+
     if (bdrv_is_sg(s->bs)) {
         error_report("scsi-disk: unwanted /dev/sg*");
         return -1;
@@ -1090,6 +1098,7 @@ static SCSIDeviceInfo scsi_disk_info = {
     .qdev.props   = (Property[]) {
         DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
         DEFINE_PROP_STRING("ver",  SCSIDiskState, version),
+        DEFINE_PROP_STRING("serial",  SCSIDiskState, serial),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
commit 03432407256b8e39d76c9e6cd39dc553e7b646d8
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:33 2010 +0200

    ide: Fix info qtree for ide-drive.ver
    
    Show the actual default value instead of <null> when the property has
    not been set.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 5e549d9..6231d77 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -110,6 +110,9 @@ static int ide_drive_initfn(IDEDevice *dev)
 
     ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
 
+    if (!dev->version) {
+        dev->version = qemu_strdup(s->version);
+    }
     if (!dev->serial) {
         dev->serial = qemu_strdup(s->drive_serial_str);
     }
commit 6ced55a57d7f6e647d683b5c41df0c176594f824
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:32 2010 +0200

    ide: Turn drive serial into a qdev property ide-drive.serial
    
    It needs to be a qdev property, because it belongs to the drive's
    guest part.
    
    Bonus: info qtree now shows the serial number.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index d3328cd..70af1b6 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2596,7 +2596,8 @@ void ide_bus_reset(IDEBus *bus)
     ide_clear_hob(bus);
 }
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+                    const char *version, const char *serial)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
@@ -2618,9 +2619,9 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
         s->is_cdrom = 1;
         bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
     }
-    strncpy(s->drive_serial_str, drive_get_serial(s->bs),
-            sizeof(s->drive_serial_str));
-    if (!*s->drive_serial_str) {
+    if (serial && *serial) {
+        strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
+    } else {
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
                  "QM%05d", s->drive_serial);
     }
@@ -2669,7 +2670,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
         dinfo = i == 0 ? hd0 : hd1;
         ide_init1(bus, i);
         if (dinfo) {
-            ide_init_drive(&bus->ifs[i], dinfo, NULL);
+            ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial);
         } else {
             ide_reset(&bus->ifs[i]);
         }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 6b0024d..eef1ee1 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -457,6 +457,7 @@ struct IDEDevice {
     uint32_t unit;
     BlockConf conf;
     char *version;
+    char *serial;
 };
 
 typedef int (*ide_qdev_initfn)(IDEDevice *dev);
@@ -554,7 +555,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
 void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+                    const char *version, const char *serial);
 void ide_init2(IDEBus *bus, qemu_irq irq);
 void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
                                     DriveInfo *hd1, qemu_irq irq);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 9ebb906..5e549d9 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -99,7 +99,20 @@ typedef struct IDEDrive {
 static int ide_drive_initfn(IDEDevice *dev)
 {
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
-    ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version);
+    IDEState *s = bus->ifs + dev->unit;
+    const char *serial;
+
+    serial = dev->serial;
+    if (!serial) {
+        /* try to fall back to value set with legacy -drive serial=... */
+        serial = dev->conf.dinfo->serial;
+    }
+
+    ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
+
+    if (!dev->serial) {
+        dev->serial = qemu_strdup(s->drive_serial_str);
+    }
     return 0;
 }
 
@@ -111,6 +124,7 @@ static IDEDeviceInfo ide_drive_info = {
         DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
         DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
         DEFINE_PROP_STRING("ver",  IDEDrive, dev.version),
+        DEFINE_PROP_STRING("serial",  IDEDrive, dev.serial),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
commit d21357df9a2a6b7e6bb2f579d04877f3bd65c557
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:31 2010 +0200

    qdev: Don't leak string property value on hot unplug
    
    parse_string() qemu_strdup()s the property value.  It is never freed.
    It needs to be freed along with the device.  Otherwise, the value of
    scsi-disk property "ver" gets leaked when hot-unplugging the disk, for
    instance.
    
    Call new PropertyInfo method free() from qdev_free().  Implement it
    for qdev_prop_string.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index b6ee50f..48a6b45 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -260,6 +260,11 @@ static int parse_string(DeviceState *dev, Property *prop, const char *str)
     return 0;
 }
 
+static void free_string(DeviceState *dev, Property *prop)
+{
+    qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
+}
+
 static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
 {
     char **ptr = qdev_get_prop_ptr(dev, prop);
@@ -274,6 +279,7 @@ PropertyInfo qdev_prop_string = {
     .size  = sizeof(char*),
     .parse = parse_string,
     .print = print_string,
+    .free  = free_string,
 };
 
 /* --- drive --- */
diff --git a/hw/qdev.c b/hw/qdev.c
index aa2ce01..29f6e9f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -334,6 +334,7 @@ void qdev_init_nofail(DeviceState *dev)
 void qdev_free(DeviceState *dev)
 {
     BusState *bus;
+    Property *prop;
 
     if (dev->state == DEV_STATE_INITIALIZED) {
         while (dev->num_child_bus) {
@@ -349,6 +350,11 @@ void qdev_free(DeviceState *dev)
     }
     qemu_unregister_reset(qdev_reset, dev);
     QLIST_REMOVE(dev, sibling);
+    for (prop = dev->info->props; prop && prop->name; prop++) {
+        if (prop->info->free) {
+            prop->info->free(dev, prop);
+        }
+    }
     qemu_free(dev);
 }
 
diff --git a/hw/qdev.h b/hw/qdev.h
index 7c25a94..51a24e2 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -98,6 +98,7 @@ struct PropertyInfo {
     enum PropertyType type;
     int (*parse)(DeviceState *dev, Property *prop, const char *str);
     int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+    void (*free)(DeviceState *dev, Property *prop);
 };
 
 typedef struct GlobalProperty {
commit cc98467327e13adca8f65b5a841c08930ee68220
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:30 2010 +0200

    qdev: New qdev_prop_set_string()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 9ffdba7..b6ee50f 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -617,6 +617,11 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
     qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
 }
 
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
+{
+    qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
+}
+
 void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
 {
     qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
diff --git a/hw/qdev.h b/hw/qdev.h
index a44060e..7c25a94 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -268,6 +268,7 @@ void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value);
 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
 void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value);
 void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
commit 57234ee40d314f91cf5bd16a926f30a6985e06e2
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:29 2010 +0200

    ide: Split non-qdev code off ide_init2()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index cdcc9bf..559147f 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -260,8 +260,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
     ide_bus_new(&d->bus[0], &d->dev.qdev);
     ide_bus_new(&d->bus[1], &d->dev.qdev);
-    ide_init2(&d->bus[0], NULL, NULL, irq[0]);
-    ide_init2(&d->bus[1], NULL, NULL, irq[1]);
+    ide_init2(&d->bus[0], irq[0]);
+    ide_init2(&d->bus[1], irq[1]);
 
     vmstate_register(0, &vmstate_ide_pci, d);
     qemu_register_reset(cmd646_reset, d);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index cb7af38..d3328cd 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2632,7 +2632,7 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
     ide_reset(s);
 }
 
-static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
+static void ide_init1(IDEBus *bus, int unit)
 {
     static int drive_serial = 1;
     IDEState *s = &bus->ifs[unit];
@@ -2645,20 +2645,34 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
     s->smart_selftest_data = qemu_blockalign(s->bs, 512);
     s->sector_write_timer = qemu_new_timer(vm_clock,
                                            ide_sector_write_timer_cb, s);
-    if (dinfo) {
-        ide_init_drive(s, dinfo, NULL);
-    } else {
-        ide_reset(s);
+}
+
+void ide_init2(IDEBus *bus, qemu_irq irq)
+{
+    int i;
+
+    for(i = 0; i < 2; i++) {
+        ide_init1(bus, i);
+        ide_reset(&bus->ifs[i]);
     }
+    bus->irq = irq;
 }
 
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
-               qemu_irq irq)
+/* TODO convert users to qdev and remove */
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+                                    DriveInfo *hd1, qemu_irq irq)
 {
     int i;
+    DriveInfo *dinfo;
 
     for(i = 0; i < 2; i++) {
-        ide_init1(bus, i, i == 0 ? hd0 : hd1);
+        dinfo = i == 0 ? hd0 : hd1;
+        ide_init1(bus, i);
+        if (dinfo) {
+            ide_init_drive(&bus->ifs[i], dinfo, NULL);
+        } else {
+            ide_reset(&bus->ifs[i]);
+        }
     }
     bus->irq = irq;
 }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index cf71019..6b0024d 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -555,8 +555,9 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
 void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
-               qemu_irq irq);
+void ide_init2(IDEBus *bus, qemu_irq irq);
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+                                    DriveInfo *hd1, qemu_irq irq);
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
 
 /* hw/ide/qdev.c */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index dff7c79..b6c6347 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -70,7 +70,7 @@ static int isa_ide_initfn(ISADevice *dev)
     ide_bus_new(&s->bus, &s->dev.qdev);
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
-    ide_init2(&s->bus, NULL, NULL, s->irq);
+    ide_init2(&s->bus, s->irq);
     vmstate_register(0, &vmstate_ide_isa, s);
     return 0;
 };
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 639f3f6..f76c0fa 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -314,7 +314,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
     int pmac_ide_memory;
 
     d = qemu_mallocz(sizeof(MACIOIDEState));
-    ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
+    ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
 
     if (dbdma)
         DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index bfdb8c8..a7beac5 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -539,7 +539,8 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
     md->card.cis = dscm1xxxx_cis;
     md->card.cis_len = sizeof(dscm1xxxx_cis);
 
-    ide_init2(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
+                                   qemu_allocate_irqs(md_set_irq, md, 1)[0]);
     md->bus.ifs[0].is_cf = 1;
     md->bus.ifs[0].mdata_size = METADATA_SIZE;
     md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index cca883f..e75cccf 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -125,7 +125,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
     MMIOState *s = qemu_mallocz(sizeof(MMIOState));
     int mem1, mem2;
 
-    ide_init2(&s->bus, hd0, hd1, irq);
+    ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
 
     s->shift = shift;
 
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 4fa3851..dad6e86 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -135,8 +135,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
     ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->bus[1], 0x170, 0x376);
 
-    ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14));
-    ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15));
+    ide_init2(&d->bus[0], isa_reserve_irq(14));
+    ide_init2(&d->bus[1], isa_reserve_irq(15));
     return 0;
 }
 
commit 870111c8ed95df62a101eae0acd08c84233a6341
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Jun 1 20:32:28 2010 +0200

    ide: Change ide_init_drive() to require valid dinfo argument
    
    IDEState members drive_serial_str and version are now left empty until
    an actual drive is connected.  Before, they got a default value that
    was overwritten when a drive got connected.  Doesn't matter, because
    they're used only while a drive is connected.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 443ff10..cb7af38 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2601,30 +2601,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
     int cylinders, heads, secs;
     uint64_t nb_sectors;
 
-    if (dinfo && dinfo->bdrv) {
-        s->bs = dinfo->bdrv;
-        bdrv_get_geometry(s->bs, &nb_sectors);
-        bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
-        s->cylinders = cylinders;
-        s->heads = heads;
-        s->sectors = secs;
-        s->nb_sectors = nb_sectors;
-        /* The SMART values should be preserved across power cycles
-           but they aren't.  */
-        s->smart_enabled = 1;
-        s->smart_autosave = 1;
-        s->smart_errors = 0;
-        s->smart_selftest_count = 0;
-        if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
-            s->is_cdrom = 1;
-            bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
-        }
-        strncpy(s->drive_serial_str, drive_get_serial(s->bs),
-                sizeof(s->drive_serial_str));
+    s->bs = dinfo->bdrv;
+    bdrv_get_geometry(s->bs, &nb_sectors);
+    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
+    s->cylinders = cylinders;
+    s->heads = heads;
+    s->sectors = secs;
+    s->nb_sectors = nb_sectors;
+    /* The SMART values should be preserved across power cycles
+       but they aren't.  */
+    s->smart_enabled = 1;
+    s->smart_autosave = 1;
+    s->smart_errors = 0;
+    s->smart_selftest_count = 0;
+    if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+        s->is_cdrom = 1;
+        bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
     }
-    if (strlen(s->drive_serial_str) == 0)
+    strncpy(s->drive_serial_str, drive_get_serial(s->bs),
+            sizeof(s->drive_serial_str));
+    if (!*s->drive_serial_str) {
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
                  "QM%05d", s->drive_serial);
+    }
     if (version) {
         pstrcpy(s->version, sizeof(s->version), version);
     } else {
@@ -2646,7 +2645,11 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
     s->smart_selftest_data = qemu_blockalign(s->bs, 512);
     s->sector_write_timer = qemu_new_timer(vm_clock,
                                            ide_sector_write_timer_cb, s);
-    ide_init_drive(s, dinfo, NULL);
+    if (dinfo) {
+        ide_init_drive(s, dinfo, NULL);
+    } else {
+        ide_reset(s);
+    }
 }
 
 void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
commit d459da0ed4bcdc38d5aaaa78f0c83fdeac6dd190
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:47 2010 +0200

    ide: Split ide_init1() off ide_init2()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index c3334b1..443ff10 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2633,27 +2633,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
     ide_reset(s);
 }
 
+static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
+{
+    static int drive_serial = 1;
+    IDEState *s = &bus->ifs[unit];
+
+    s->bus = bus;
+    s->unit = unit;
+    s->drive_serial = drive_serial++;
+    s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
+    s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
+    s->smart_selftest_data = qemu_blockalign(s->bs, 512);
+    s->sector_write_timer = qemu_new_timer(vm_clock,
+                                           ide_sector_write_timer_cb, s);
+    ide_init_drive(s, dinfo, NULL);
+}
+
 void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
                qemu_irq irq)
 {
-    IDEState *s;
-    static int drive_serial = 1;
     int i;
 
     for(i = 0; i < 2; i++) {
-        s = bus->ifs + i;
-        s->bus = bus;
-        s->unit = i;
-        s->drive_serial = drive_serial++;
-        s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
-        s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
-        s->smart_selftest_data = qemu_blockalign(s->bs, 512);
-        s->sector_write_timer = qemu_new_timer(vm_clock,
-                                               ide_sector_write_timer_cb, s);
-        if (i == 0)
-            ide_init_drive(s, hd0, NULL);
-        if (i == 1)
-            ide_init_drive(s, hd1, NULL);
+        ide_init1(bus, i, i == 0 ? hd0 : hd1);
     }
     bus->irq = irq;
 }
commit 57dac7ef8aeabcd17b1ceee2296917bc48ccd526
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:46 2010 +0200

    ide: Remove redundant IDEState member conf
    
    Commit 428c149b added IDEState member conf to let commit 0009baf1 find
    the BlockConf from there.  It exists only for qdev drives, created via
    ide_drive_initfn(), not for drives created via ide_init2().
    
    But for a qdev drive, we can just as well reach its IDEDevice, which
    contains the BlockConf.  Do that, and revert the parts of commit
    428c149b that add IDEState member conf.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 066fecb..c3334b1 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -98,6 +98,7 @@ static void ide_identify(IDEState *s)
 {
     uint16_t *p;
     unsigned int oldsize;
+    IDEDevice *dev;
 
     if (s->identify_set) {
 	memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -165,8 +166,9 @@ static void ide_identify(IDEState *s)
     put_le16(p + 101, s->nb_sectors >> 16);
     put_le16(p + 102, s->nb_sectors >> 32);
     put_le16(p + 103, s->nb_sectors >> 48);
-    if (s->conf && s->conf->physical_block_size)
-        put_le16(p + 106, 0x6000 | get_physical_block_exp(s->conf));
+    dev = s->unit ? s->bus->slave : s->bus->master;
+    if (dev && dev->conf.physical_block_size)
+        put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
 
     memcpy(s->identify_data, p, sizeof(s->identify_data));
     s->identify_set = 1;
@@ -2594,8 +2596,7 @@ void ide_bus_reset(IDEBus *bus)
     ide_clear_hob(bus);
 }
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
-        const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
 {
     int cylinders, heads, secs;
     uint64_t nb_sectors;
@@ -2620,9 +2621,6 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
         }
         strncpy(s->drive_serial_str, drive_get_serial(s->bs),
                 sizeof(s->drive_serial_str));
-        if (conf) {
-            s->conf = conf;
-        }
     }
     if (strlen(s->drive_serial_str) == 0)
         snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
@@ -2653,9 +2651,9 @@ void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
         s->sector_write_timer = qemu_new_timer(vm_clock,
                                                ide_sector_write_timer_cb, s);
         if (i == 0)
-            ide_init_drive(s, hd0, NULL, NULL);
+            ide_init_drive(s, hd0, NULL);
         if (i == 1)
-            ide_init_drive(s, hd1, NULL, NULL);
+            ide_init_drive(s, hd1, NULL);
     }
     bus->irq = irq;
 }
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index b4554ce..cf71019 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -398,7 +398,6 @@ struct IDEState {
     /* set for lba48 access */
     uint8_t lba48;
     BlockDriverState *bs;
-    BlockConf *conf;
     char version[9];
     /* ATAPI specific */
     uint8_t sense_key;
@@ -555,8 +554,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
 void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
-    const char *version);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
 void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
                qemu_irq irq);
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index b18693d..9ebb906 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -99,8 +99,7 @@ typedef struct IDEDrive {
 static int ide_drive_initfn(IDEDevice *dev)
 {
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
-    ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf,
-                   dev->version);
+    ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version);
     return 0;
 }
 
commit 124964b54e0c50706385691142795b6e43dad817
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:45 2010 +0200

    ide: Remove useless IDEDeviceInfo members unit, drive
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 2efc784..b4554ce 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -464,8 +464,6 @@ typedef int (*ide_qdev_initfn)(IDEDevice *dev);
 struct IDEDeviceInfo {
     DeviceInfo qdev;
     ide_qdev_initfn init;
-    uint32_t unit;
-    DriveInfo *drive;
 };
 
 #define BM_STATUS_DMAING 0x01
commit fb08000cee257bbd3f3a043933a6474d870c665f
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:44 2010 +0200

    usb: Remove unused usb_device_add() parameter is_hotplug
    
    Unused since commit b3e461d3.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/vl.c b/vl.c
index 9283469..76a9b25 100644
--- a/vl.c
+++ b/vl.c
@@ -1315,7 +1315,7 @@ static void smp_parse(const char *optarg)
 /***********************************************************/
 /* USB devices */
 
-static int usb_device_add(const char *devname, int is_hotplug)
+static int usb_device_add(const char *devname)
 {
     const char *p;
     USBDevice *dev = NULL;
@@ -1367,7 +1367,7 @@ static int usb_device_del(const char *devname)
 static int usb_parse(const char *cmdline)
 {
     int r;
-    r = usb_device_add(cmdline, 0);
+    r = usb_device_add(cmdline);
     if (r < 0) {
         fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
     }
@@ -1377,7 +1377,7 @@ static int usb_parse(const char *cmdline)
 void do_usb_add(Monitor *mon, const QDict *qdict)
 {
     const char *devname = qdict_get_str(qdict, "devname");
-    if (usb_device_add(devname, 1) < 0) {
+    if (usb_device_add(devname) < 0) {
         error_report("could not add USB device '%s'", devname);
     }
 }
commit f274776028ddb026f8891cabaf59bd58dbfc31bd
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:43 2010 +0200

    blockdev: Belatedly remove driveopts
    
    Unused since commit 9dfd7c7a.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/sysemu.h b/sysemu.h
index 063319c..fd83b7d 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -178,7 +178,6 @@ typedef struct DriveInfo {
 #define MAX_SCSI_DEVS	7
 
 extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
-extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
 
 extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 extern DriveInfo *drive_get_by_id(const char *id);
diff --git a/vl.c b/vl.c
index f8d3034..9283469 100644
--- a/vl.c
+++ b/vl.c
@@ -173,7 +173,6 @@ int main(int argc, char **argv)
 static const char *data_dir;
 const char *bios_name = NULL;
 struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
-struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 DisplayType display_type = DT_DEFAULT;
 const char* keyboard_layout = NULL;
commit 1a43782e34e148a00a0bb8f5de56f2d93a0f0320
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri May 28 15:38:42 2010 +0200

    blockdev: Belatedly remove MAX_DRIVES
    
    Unused since commit 751c6a17.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/sysemu.h b/sysemu.h
index 879446a..063319c 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -176,7 +176,6 @@ typedef struct DriveInfo {
 
 #define MAX_IDE_DEVS	2
 #define MAX_SCSI_DEVS	7
-#define MAX_DRIVES 32
 
 extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
 extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
diff --git a/vl.c b/vl.c
index 7121cd0..f8d3034 100644
--- a/vl.c
+++ b/vl.c
@@ -172,8 +172,6 @@ int main(int argc, char **argv)
 
 static const char *data_dir;
 const char *bios_name = NULL;
-/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
-   to store the VM snapshots */
 struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
 struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
commit 0923c577f993d61eeaf41f66db1e1010fa113976
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri May 28 20:10:48 2010 +0200

    qemu-io: Fix error messages
    
    The truncate and getlength commands passed a negative error number to strerror.
    They also happen to be the two functions that are lacking a newline at the end
    of their error message.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-io.c b/qemu-io.c
index 72a4524..7c6120b 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1317,7 +1317,7 @@ truncate_f(int argc, char **argv)
 
 	ret = bdrv_truncate(bs, offset);
 	if (ret < 0) {
-		printf("truncate: %s", strerror(ret));
+		printf("truncate: %s\n", strerror(-ret));
 		return 0;
 	}
 
@@ -1342,7 +1342,7 @@ length_f(int argc, char **argv)
 
 	size = bdrv_getlength(bs);
 	if (size < 0) {
-		printf("getlength: %s", strerror(size));
+		printf("getlength: %s\n", strerror(-size));
 		return 0;
 	}
 
commit 1573a35d99fe60f98d30f50e9187040586c2b801
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu May 27 16:20:33 2010 +0200

    Cleanup: virtio-blk.c: Be more consistent using BDRV_SECTOR_SIZE instead
    
    Clean up virtio-blk.c to be more consistent using BDRV_SECTOR_SIZE
    instead of hard coded 512 values.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 5d7f1a2..80d51c4 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -277,7 +277,7 @@ static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
     }
 
     blkreq[*num_writes].sector = req->out->sector;
-    blkreq[*num_writes].nb_sectors = req->qiov.size / 512;
+    blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
     blkreq[*num_writes].qiov = &req->qiov;
     blkreq[*num_writes].cb = virtio_blk_rw_complete;
     blkreq[*num_writes].opaque = req;
@@ -296,7 +296,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
     }
 
     acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
-                         req->qiov.size / 512, virtio_blk_rw_complete, req);
+                         req->qiov.size / BDRV_SECTOR_SIZE,
+                         virtio_blk_rw_complete, req);
     if (!acb) {
         virtio_blk_rw_complete(req, -EIO);
     }
@@ -505,7 +506,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     s->bs = conf->dinfo->bdrv;
     s->conf = conf;
     s->rq = NULL;
-    s->sector_mask = (s->conf->logical_block_size / 512) - 1;
+    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
     bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
 
     s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
commit 9040385dcc0a4b32ca8ceeda6dc679aea56e3832
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu May 27 16:20:32 2010 +0200

    Cleanup: raw-posix.c: Be more consistent using BDRV_SECTOR_SIZE instead of 512
    
    Clean up raw-posix.c to be more consistent using BDRV_SECTOR_SIZE
    instead of hard coded 512 values.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 7541ed2..3f0701b 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -392,8 +392,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num,
 {
     int ret;
 
-    ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
-    if (ret == (nb_sectors * 512))
+    ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+                    nb_sectors * BDRV_SECTOR_SIZE);
+    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
         ret = 0;
     return ret;
 }
@@ -480,8 +481,9 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
     int ret;
-    ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
-    if (ret == (nb_sectors * 512))
+    ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+                     nb_sectors * BDRV_SECTOR_SIZE);
+    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
         ret = 0;
     return ret;
 }
@@ -494,7 +496,7 @@ static int qiov_is_aligned(QEMUIOVector *qiov)
     int i;
 
     for (i = 0; i < qiov->niov; i++) {
-        if ((uintptr_t) qiov->iov[i].iov_base % 512) {
+        if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) {
             return 0;
         }
     }
@@ -703,7 +705,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
     /* Read out options */
     while (options && options->name) {
         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
-            total_size = options->value.n / 512;
+            total_size = options->value.n / BDRV_SECTOR_SIZE;
         }
         options++;
     }
@@ -713,7 +715,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
     if (fd < 0) {
         result = -errno;
     } else {
-        if (ftruncate(fd, total_size * 512) != 0) {
+        if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
             result = -errno;
         }
         if (close(fd) != 0) {
@@ -976,7 +978,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
     /* Read out options */
     while (options && options->name) {
         if (!strcmp(options->name, "size")) {
-            total_size = options->value.n / 512;
+            total_size = options->value.n / BDRV_SECTOR_SIZE;
         }
         options++;
     }
@@ -989,7 +991,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
         ret = -errno;
     else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
         ret = -ENODEV;
-    else if (lseek(fd, 0, SEEK_END) < total_size * 512)
+    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
         ret = -ENOSPC;
 
     close(fd);
commit eb5a316514144bc1def4cb9b88fb996420ca80cc
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu May 27 16:20:31 2010 +0200

    Cleanup: Be consistent and use BDRV_SECTOR_SIZE instead of 512
    
    Clean up block.c and use BDRV_SECTOR_SIZE rather than hard coded
    numbers (512) when referring to sector size throughout the code.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 8385b4f..9c43332 100644
--- a/block.c
+++ b/block.c
@@ -684,7 +684,7 @@ int bdrv_commit(BlockDriverState *bs)
     int64_t i, total_sectors;
     int n, j, ro, open_flags;
     int ret = 0, rw_ret = 0;
-    unsigned char sector[512];
+    unsigned char sector[BDRV_SECTOR_SIZE];
     char filename[1024];
     BlockDriverState *bs_rw, *bs_ro;
 
@@ -824,7 +824,8 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
 static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
                               int nb_sectors)
 {
-    return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
+    return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
+                                   nb_sectors * BDRV_SECTOR_SIZE);
 }
 
 /* return < 0 if error. See bdrv_write() for the return codes */
@@ -1059,7 +1060,7 @@ struct partition {
 static int guess_disk_lchs(BlockDriverState *bs,
                            int *pcylinders, int *pheads, int *psectors)
 {
-    uint8_t buf[512];
+    uint8_t buf[BDRV_SECTOR_SIZE];
     int ret, i, heads, sectors, cylinders;
     struct partition *p;
     uint32_t nr_sects;
@@ -1535,7 +1536,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
                              "} }",
                              bs->rd_bytes, bs->wr_bytes,
                              bs->rd_ops, bs->wr_ops,
-                             bs->wr_highest_sector * 512);
+                             bs->wr_highest_sector * (long)BDRV_SECTOR_SIZE);
     dict  = qobject_to_qdict(res);
 
     if (*bs->device_name) {
@@ -2197,7 +2198,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
 
     async_ret = NOT_DONE;
     iov.iov_base = (void *)buf;
-    iov.iov_len = nb_sectors * 512;
+    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&qiov, &iov, 1);
     acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
         bdrv_rw_em_cb, &async_ret);
@@ -2228,7 +2229,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
 
     async_ret = NOT_DONE;
     iov.iov_base = (void *)buf;
-    iov.iov_len = nb_sectors * 512;
+    iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&qiov, &iov, 1);
     acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
         bdrv_rw_em_cb, &async_ret);
commit 3e82990b52d5afeb4957dd9b87be83d752e369b9
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu May 27 16:20:30 2010 +0200

    Cleanup: bdrv_open() no need to shift total_size just to shift back.
    
    In bdrv_open() there is no need to shift total_size >> 9 just to
    multiply it by 512 again just a few lines later, since this is the
    only place the variable is used.
    
    Mask with BDRV_SECTOR_MASK to protect against case where we are
    passed a corrupted image.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 39724c1..8385b4f 100644
--- a/block.c
+++ b/block.c
@@ -522,7 +522,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
             bdrv_delete(bs1);
             return ret;
         }
-        total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;
+        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
 
         if (bs1->drv && bs1->drv->protocol_name)
             is_protocol = 1;
@@ -541,7 +541,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         bdrv_qcow2 = bdrv_find_format("qcow2");
         options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
 
-        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
+        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
         set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
         if (drv) {
             set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
commit 358c360feb346dff8f911e2d1dbcdd6319393f1d
Merge: 41ef56e... 1a39685...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Jun 3 14:55:49 2010 -0500

    Merge remote branch 'kwolf/for-anthony' into staging

commit 41ef56e61153d7bd27d34a634633bb51b1c5988d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Jun 2 14:55:25 2010 -0500

    migration: respect exit status with exec:
    
    This patch makes sure that if the exec: process exits with a non-zero return
    status, we treat the migration as failed.
    
    This fixes https://bugs.launchpad.net/qemu/+bug/391879
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration-exec.c b/migration-exec.c
index 5435827..93bde62 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -43,13 +43,21 @@ static int file_write(FdMigrationState *s, const void * buf, size_t size)
 
 static int exec_close(FdMigrationState *s)
 {
+    int ret = 0;
     DPRINTF("exec_close\n");
     if (s->opaque) {
-        qemu_fclose(s->opaque);
+        ret = qemu_fclose(s->opaque);
         s->opaque = NULL;
         s->fd = -1;
+        if (ret != -1 &&
+            WIFEXITED(ret)
+            && WEXITSTATUS(ret) == 0) {
+            ret = 0;
+        } else {
+            ret = -1;
+        }
     }
-    return 0;
+    return ret;
 }
 
 MigrationState *exec_start_outgoing_migration(Monitor *mon,
diff --git a/migration.c b/migration.c
index 706fe55..fbf2339 100644
--- a/migration.c
+++ b/migration.c
@@ -252,13 +252,17 @@ void migrate_fd_error(FdMigrationState *s)
     migrate_fd_cleanup(s);
 }
 
-void migrate_fd_cleanup(FdMigrationState *s)
+int migrate_fd_cleanup(FdMigrationState *s)
 {
+    int ret = 0;
+
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
 
     if (s->file) {
         DPRINTF("closing file\n");
-        qemu_fclose(s->file);
+        if (qemu_fclose(s->file) != 0) {
+            ret = -1;
+        }
         s->file = NULL;
     }
 
@@ -271,6 +275,8 @@ void migrate_fd_cleanup(FdMigrationState *s)
     }
 
     s->fd = -1;
+
+    return ret;
 }
 
 void migrate_fd_put_notify(void *opaque)
@@ -349,7 +355,12 @@ void migrate_fd_put_ready(void *opaque)
         } else {
             state = MIG_STATE_COMPLETED;
         }
-        migrate_fd_cleanup(s);
+        if (migrate_fd_cleanup(s) < 0) {
+            if (old_vm_running) {
+                vm_start();
+            }
+            state = MIG_STATE_ERROR;
+        }
         s->state = state;
     }
 }
diff --git a/migration.h b/migration.h
index 385423f..97eef4a 100644
--- a/migration.h
+++ b/migration.h
@@ -107,7 +107,7 @@ void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon);
 
 void migrate_fd_error(FdMigrationState *s);
 
-void migrate_fd_cleanup(FdMigrationState *s);
+int migrate_fd_cleanup(FdMigrationState *s);
 
 void migrate_fd_put_notify(void *opaque);
 
diff --git a/savevm.c b/savevm.c
index dc20390..af92ba2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -235,9 +235,10 @@ static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
 static int stdio_pclose(void *opaque)
 {
     QEMUFileStdio *s = opaque;
-    pclose(s->stdio_file);
+    int ret;
+    ret = pclose(s->stdio_file);
     qemu_free(s);
-    return 0;
+    return ret;
 }
 
 static int stdio_fclose(void *opaque)
commit 4309a79bffce10d6d8de82c5ee403ffa4f45db64
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jun 3 00:02:30 2010 +0200

    tcg-i386: fix a typo
    
    Fix a typo introduced by c28b14c694d759f39fe3ae4f8d03b567da5b93f8.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index e16557e..3600c35 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -726,7 +726,7 @@ static void *qemu_st_helpers[4] = {
 
 static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
                                     int mem_index, int s_bits,
-                                    const TCGArg *args
+                                    const TCGArg *args,
                                     uint8_t **label_ptr, int which)
 {
     const int addrlo = args[addrlo_idx];
commit c28b14c694d759f39fe3ae4f8d03b567da5b93f8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jun 1 13:55:18 2010 +0200

    tcg-i386: declare tcg_out_tlb_load() inline
    
    Declare tcg_out_tlb_load() inline so that we don't loose optimisations
    with commit 8516a04467cb7954cdc32e8b79b4b7df56dccb16.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8a9122c..e16557e 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -724,9 +724,10 @@ static void *qemu_st_helpers[4] = {
 
    EDX is clobbered.  */
 
-static void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
-                             int s_bits, const TCGArg *args,
-                             uint8_t **label_ptr, int which)
+static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
+                                    int mem_index, int s_bits,
+                                    const TCGArg *args
+                                    uint8_t **label_ptr, int which)
 {
     const int addrlo = args[addrlo_idx];
     const int r0 = TCG_REG_EAX;
commit 82bb07db0c3f0685dbdc5050d57f0c26ad6ff844
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 09:03:04 2010 -0700

    tcg-i386: Remove some ifdefs in qemu_ld/st.
    
    Tidy some code by replacing ifdefs by C ifs.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index cf621da..8a9122c 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -842,7 +842,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     int data_reg, data_reg2 = 0;
     int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
-    int mem_index, s_bits;
+    int mem_index, s_bits, arg_idx;
     uint8_t *label_ptr[3];
 #endif
 
@@ -877,12 +877,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     }
 
     /* XXX: move that code at the end of the TB */
-#if TARGET_LONG_BITS == 32
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
-#else
-    tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
-    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
-#endif
+    /* EAX is already loaded.  */
+    arg_idx = 1;
+    if (TARGET_LONG_BITS == 64) {
+        tcg_out_mov(s, tcg_target_call_iarg_regs[arg_idx++],
+                    args[addrlo_idx + 1]);
+    }
+    tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
+                 mem_index);
     tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
 
     switch(opc) {
@@ -1018,51 +1020,40 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     }
 
     /* XXX: move that code at the end of the TB */
-#if TARGET_LONG_BITS == 32
-    if (opc == 3) {
+    if (TARGET_LONG_BITS == 32) {
         tcg_out_mov(s, TCG_REG_EDX, data_reg);
-        tcg_out_mov(s, TCG_REG_ECX, data_reg2);
-        tcg_out_pushi(s, mem_index);
-        stack_adjust = 4;
-    } else {
-        switch(opc) {
-        case 0:
-            tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
-            break;
-        case 1:
-            tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
-            break;
-        case 2:
-            tcg_out_mov(s, TCG_REG_EDX, data_reg);
-            break;
+        if (opc == 3) {
+            tcg_out_mov(s, TCG_REG_ECX, data_reg2);
+            tcg_out_pushi(s, mem_index);
+            stack_adjust = 4;
+        } else {
+            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
+            stack_adjust = 0;
         }
-        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
-        stack_adjust = 0;
-    }
-#else
-    if (opc == 3) {
-        tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
-        tcg_out_pushi(s, mem_index);
-        tcg_out_push(s, data_reg2);
-        tcg_out_push(s, data_reg);
-        stack_adjust = 12;
     } else {
-        tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
-        switch(opc) {
-        case 0:
-            tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
-            break;
-        case 1:
-            tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
-            break;
-        case 2:
-            tcg_out_mov(s, TCG_REG_ECX, data_reg);
-            break;
+        if (opc == 3) {
+            tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+            tcg_out_pushi(s, mem_index);
+            tcg_out_push(s, data_reg2);
+            tcg_out_push(s, data_reg);
+            stack_adjust = 12;
+        } else {
+            tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+            switch(opc) {
+            case 0:
+                tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
+                break;
+            case 1:
+                tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
+                break;
+            case 2:
+                tcg_out_mov(s, TCG_REG_ECX, data_reg);
+                break;
+            }
+            tcg_out_pushi(s, mem_index);
+            stack_adjust = 4;
         }
-        tcg_out_pushi(s, mem_index);
-        stack_adjust = 4;
     }
-#endif
 
     tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
 
commit 8516a04467cb7954cdc32e8b79b4b7df56dccb16
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 09:03:03 2010 -0700

    tcg-i386: Split out tlb load function.
    
    Share some code between qemu_ld and qemu_st.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 0d85ec0..cf621da 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -702,6 +702,74 @@ static void *qemu_st_helpers[4] = {
     __stl_mmu,
     __stq_mmu,
 };
+
+/* Perform the TLB load and compare.
+
+   Inputs:
+   ADDRLO_IDX contains the index into ARGS of the low part of the
+   address; the high part of the address is at ADDR_LOW_IDX+1.
+
+   MEM_INDEX and S_BITS are the memory context and log2 size of the load.
+
+   WHICH is the offset into the CPUTLBEntry structure of the slot to read.
+   This should be offsetof addr_read or addr_write.
+
+   Outputs:
+   LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
+   positions of the displacements of forward jumps to the TLB miss case.
+
+   EAX is loaded with the low part of the address.  In the TLB hit case,
+   it has been adjusted as indicated by the TLB and so is a host address.
+   In the TLB miss case, it continues to hold a guest address.
+
+   EDX is clobbered.  */
+
+static void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
+                             int s_bits, const TCGArg *args,
+                             uint8_t **label_ptr, int which)
+{
+    const int addrlo = args[addrlo_idx];
+    const int r0 = TCG_REG_EAX;
+    const int r1 = TCG_REG_EDX;
+
+    tcg_out_mov(s, r1, addrlo);
+    tcg_out_mov(s, r0, addrlo);
+
+    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+
+    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
+
+    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+                             offsetof(CPUState, tlb_table[mem_index][0])
+                             + which);
+
+    /* cmp 0(r1), r0 */
+    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
+
+    tcg_out_mov(s, r0, addrlo);
+
+    /* jne label1 */
+    tcg_out8(s, OPC_JCC_short + JCC_JNE);
+    label_ptr[0] = s->code_ptr;
+    s->code_ptr++;
+
+    if (TARGET_LONG_BITS == 64) {
+        /* cmp 4(r1), addrhi */
+        tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
+
+        /* jne label1 */
+        tcg_out8(s, OPC_JCC_short + JCC_JNE);
+        label_ptr[1] = s->code_ptr;
+        s->code_ptr++;
+    }
+
+    /* TLB Hit.  */
+
+    /* add addend(r1), r0 */
+    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+                         offsetof(CPUTLBEntry, addend) - which);
+}
 #endif
 
 static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
@@ -771,68 +839,29 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, addr_reg2 = 0;
     int data_reg, data_reg2 = 0;
-    int r0, r1, mem_index, s_bits;
+    int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
+    int mem_index, s_bits;
     uint8_t *label_ptr[3];
 #endif
 
-    data_reg = *args++;
+    data_reg = args[0];
+    addrlo_idx = 1;
     if (opc == 3) {
-        data_reg2 = *args++;
+        data_reg2 = args[1];
+        addrlo_idx = 2;
     }
-    addr_reg = *args++;
-    if (TARGET_LONG_BITS == 64) {
-        addr_reg2 = *args++;
-    }
-    mem_index = *args;
-    s_bits = opc & 3;
-
-    r0 = TCG_REG_EAX;
-    r1 = TCG_REG_EDX;
 
 #if defined(CONFIG_SOFTMMU)
-    tcg_out_mov(s, r1, addr_reg);
-    tcg_out_mov(s, r0, addr_reg);
-
-    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
-    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
-    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
-
-    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
-                             offsetof(CPUState,
-                                      tlb_table[mem_index][0].addr_read));
-
-    /* cmp 0(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
-    tcg_out_mov(s, r0, addr_reg);
-
-    /* jne label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JNE);
-    label_ptr[0] = s->code_ptr;
-    s->code_ptr++;
-
-    if (TARGET_LONG_BITS == 64) {
-        /* cmp 4(r1), addr_reg2 */
-        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+    mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+    s_bits = opc & 3;
 
-        /* jne label1 */
-        tcg_out8(s, OPC_JCC_short + JCC_JNE);
-        label_ptr[1] = s->code_ptr;
-        s->code_ptr++;
-    }
+    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+                     label_ptr, offsetof(CPUTLBEntry, addr_read));
 
     /* TLB Hit.  */
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
-                         offsetof(CPUTLBEntry, addend) -
-                         offsetof(CPUTLBEntry, addr_read));
-
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
 
     /* jmp label2 */
     tcg_out8(s, OPC_JMP_short);
@@ -851,7 +880,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 #if TARGET_LONG_BITS == 32
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
 #else
-    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+    tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
 #endif
     tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
@@ -888,7 +917,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     /* label2: */
     *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
+                           args[addrlo_idx], GUEST_BASE, opc);
 #endif
 }
 
@@ -949,70 +979,30 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, addr_reg2 = 0;
     int data_reg, data_reg2 = 0;
-    int r0, r1, mem_index, s_bits;
+    int addrlo_idx;
 #if defined(CONFIG_SOFTMMU)
+    int mem_index, s_bits;
     int stack_adjust;
     uint8_t *label_ptr[3];
 #endif
 
-    data_reg = *args++;
+    data_reg = args[0];
+    addrlo_idx = 1;
     if (opc == 3) {
-        data_reg2 = *args++;
+        data_reg2 = args[1];
+        addrlo_idx = 2;
     }
-    addr_reg = *args++;
-    if (TARGET_LONG_BITS == 64) {
-        addr_reg2 = *args++;
-    }
-    mem_index = *args;
-
-    s_bits = opc;
-
-    r0 = TCG_REG_EAX;
-    r1 = TCG_REG_EDX;
 
 #if defined(CONFIG_SOFTMMU)
-    tcg_out_mov(s, r1, addr_reg);
-    tcg_out_mov(s, r0, addr_reg);
-
-    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
-    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
-    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
-
-    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
-                             offsetof(CPUState,
-                                      tlb_table[mem_index][0].addr_write));
-
-    /* cmp 0(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
-    tcg_out_mov(s, r0, addr_reg);
-
-    /* jne label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JNE);
-    label_ptr[0] = s->code_ptr;
-    s->code_ptr++;
-
-    if (TARGET_LONG_BITS == 64) {
-        /* cmp 4(r1), addr_reg2 */
-        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+    mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+    s_bits = opc;
 
-        /* jne label1 */
-        tcg_out8(s, OPC_JCC_short + JCC_JNE);
-        label_ptr[1] = s->code_ptr;
-        s->code_ptr++;
-    }
+    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+                     label_ptr, offsetof(CPUTLBEntry, addr_write));
 
     /* TLB Hit.  */
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
-                         offsetof(CPUTLBEntry, addend) -
-                         offsetof(CPUTLBEntry, addr_write));
-
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
 
     /* jmp label2 */
     tcg_out8(s, OPC_JMP_short);
@@ -1051,13 +1041,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     }
 #else
     if (opc == 3) {
-        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+        tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
         tcg_out_pushi(s, mem_index);
         tcg_out_push(s, data_reg2);
         tcg_out_push(s, data_reg);
         stack_adjust = 12;
     } else {
-        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+        tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
         switch(opc) {
         case 0:
             tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
@@ -1086,7 +1076,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     /* label2: */
     *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2,
+                           args[addrlo_idx], GUEST_BASE, opc);
 #endif
 }
 
commit 1a6dc1e4060e3c5dd44735f2a210b2efc56b7726
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 09:03:02 2010 -0700

    tcg-i386: Swap order of TLB hit and miss paths.
    
    Make fallthru be TLB hit and branch be TLB miss.  Doing this
    both improves branch prediction and will allow further cleanup.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 30c933c..0d85ec0 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -771,26 +771,21 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
+    int addr_reg, addr_reg2 = 0;
+    int data_reg, data_reg2 = 0;
+    int r0, r1, mem_index, s_bits;
 #if defined(CONFIG_SOFTMMU)
-    uint8_t *label1_ptr, *label2_ptr;
-#endif
-#if TARGET_LONG_BITS == 64
-#if defined(CONFIG_SOFTMMU)
-    uint8_t *label3_ptr;
-#endif
-    int addr_reg2;
+    uint8_t *label_ptr[3];
 #endif
 
     data_reg = *args++;
-    if (opc == 3)
+    if (opc == 3) {
         data_reg2 = *args++;
-    else
-        data_reg2 = 0;
+    }
     addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-#endif
+    if (TARGET_LONG_BITS == 64) {
+        addr_reg2 = *args++;
+    }
     mem_index = *args;
     s_bits = opc & 3;
 
@@ -815,28 +810,42 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
 
     tcg_out_mov(s, r0, addr_reg);
 
-#if TARGET_LONG_BITS == 32
-    /* je label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JE);
-    label1_ptr = s->code_ptr;
-    s->code_ptr++;
-#else
-    /* jne label3 */
+    /* jne label1 */
     tcg_out8(s, OPC_JCC_short + JCC_JNE);
-    label3_ptr = s->code_ptr;
+    label_ptr[0] = s->code_ptr;
     s->code_ptr++;
 
-    /* cmp 4(r1), addr_reg2 */
-    tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+    if (TARGET_LONG_BITS == 64) {
+        /* cmp 4(r1), addr_reg2 */
+        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+
+        /* jne label1 */
+        tcg_out8(s, OPC_JCC_short + JCC_JNE);
+        label_ptr[1] = s->code_ptr;
+        s->code_ptr++;
+    }
+
+    /* TLB Hit.  */
+
+    /* add x(r1), r0 */
+    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+                         offsetof(CPUTLBEntry, addend) -
+                         offsetof(CPUTLBEntry, addr_read));
+
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
 
-    /* je label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JE);
-    label1_ptr = s->code_ptr;
+    /* jmp label2 */
+    tcg_out8(s, OPC_JMP_short);
+    label_ptr[2] = s->code_ptr;
     s->code_ptr++;
 
-    /* label3: */
-    *label3_ptr = s->code_ptr - label3_ptr - 1;
-#endif
+    /* TLB Miss.  */
+
+    /* label1: */
+    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
+    if (TARGET_LONG_BITS == 64) {
+        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
+    }
 
     /* XXX: move that code at the end of the TB */
 #if TARGET_LONG_BITS == 32
@@ -876,23 +885,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
         break;
     }
 
-    /* jmp label2 */
-    tcg_out8(s, OPC_JMP_short);
-    label2_ptr = s->code_ptr;
-    s->code_ptr++;
-
-    /* label1: */
-    *label1_ptr = s->code_ptr - label1_ptr - 1;
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
-                         offsetof(CPUTLBEntry, addend) -
-                         offsetof(CPUTLBEntry, addr_read));
-
-    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
-
     /* label2: */
-    *label2_ptr = s->code_ptr - label2_ptr - 1;
+    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
     tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
 #endif
@@ -955,27 +949,22 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
+    int addr_reg, addr_reg2 = 0;
+    int data_reg, data_reg2 = 0;
+    int r0, r1, mem_index, s_bits;
 #if defined(CONFIG_SOFTMMU)
     int stack_adjust;
-    uint8_t *label1_ptr, *label2_ptr;
-#endif
-#if TARGET_LONG_BITS == 64
-#if defined(CONFIG_SOFTMMU)
-    uint8_t *label3_ptr;
-#endif
-    int addr_reg2;
+    uint8_t *label_ptr[3];
 #endif
 
     data_reg = *args++;
-    if (opc == 3)
+    if (opc == 3) {
         data_reg2 = *args++;
-    else
-        data_reg2 = 0;
+    }
     addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
-    addr_reg2 = *args++;
-#endif
+    if (TARGET_LONG_BITS == 64) {
+        addr_reg2 = *args++;
+    }
     mem_index = *args;
 
     s_bits = opc;
@@ -1001,28 +990,42 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
 
     tcg_out_mov(s, r0, addr_reg);
 
-#if TARGET_LONG_BITS == 32
-    /* je label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JE);
-    label1_ptr = s->code_ptr;
-    s->code_ptr++;
-#else
-    /* jne label3 */
+    /* jne label1 */
     tcg_out8(s, OPC_JCC_short + JCC_JNE);
-    label3_ptr = s->code_ptr;
+    label_ptr[0] = s->code_ptr;
     s->code_ptr++;
 
-    /* cmp 4(r1), addr_reg2 */
-    tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+    if (TARGET_LONG_BITS == 64) {
+        /* cmp 4(r1), addr_reg2 */
+        tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+
+        /* jne label1 */
+        tcg_out8(s, OPC_JCC_short + JCC_JNE);
+        label_ptr[1] = s->code_ptr;
+        s->code_ptr++;
+    }
+
+    /* TLB Hit.  */
+
+    /* add x(r1), r0 */
+    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+                         offsetof(CPUTLBEntry, addend) -
+                         offsetof(CPUTLBEntry, addr_write));
+
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
 
-    /* je label1 */
-    tcg_out8(s, OPC_JCC_short + JCC_JE);
-    label1_ptr = s->code_ptr;
+    /* jmp label2 */
+    tcg_out8(s, OPC_JMP_short);
+    label_ptr[2] = s->code_ptr;
     s->code_ptr++;
 
-    /* label3: */
-    *label3_ptr = s->code_ptr - label3_ptr - 1;
-#endif
+    /* TLB Miss.  */
+
+    /* label1: */
+    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
+    if (TARGET_LONG_BITS == 64) {
+        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
+    }
 
     /* XXX: move that code at the end of the TB */
 #if TARGET_LONG_BITS == 32
@@ -1080,23 +1083,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
         tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
     }
 
-    /* jmp label2 */
-    tcg_out8(s, OPC_JMP_short);
-    label2_ptr = s->code_ptr;
-    s->code_ptr++;
-
-    /* label1: */
-    *label1_ptr = s->code_ptr - label1_ptr - 1;
-
-    /* add x(r1), r0 */
-    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
-                         offsetof(CPUTLBEntry, addend) -
-                         offsetof(CPUTLBEntry, addr_write));
-
-    tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
-
     /* label2: */
-    *label2_ptr = s->code_ptr - label2_ptr - 1;
+    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
 #else
     tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
 #endif
commit be5a4eb7f071e358cefca78e3f93bf9d199cd4fa
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 09:03:01 2010 -0700

    tcg-i386: Split out TLB Hit path from qemu_ld/st.
    
    Splitting out these functions will allow further cleanups.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9226c1e..30c933c 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -704,9 +704,66 @@ static void *qemu_st_helpers[4] = {
 };
 #endif
 
-#ifndef CONFIG_USER_ONLY
-#define GUEST_BASE 0
+static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
+                                   int base, tcg_target_long ofs, int sizeop)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    const int bswap = 1;
+#else
+    const int bswap = 0;
 #endif
+    switch (sizeop) {
+    case 0:
+        /* movzbl */
+        tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
+        break;
+    case 0 | 4:
+        /* movsbl */
+        tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
+        break;
+    case 1:
+        /* movzwl */
+        tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
+        if (bswap) {
+            tcg_out_rolw_8(s, datalo);
+        }
+        break;
+    case 1 | 4:
+        /* movswl */
+        tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
+        if (bswap) {
+            tcg_out_rolw_8(s, datalo);
+            tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
+        }
+        break;
+    case 2:
+        tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+        if (bswap) {
+            tcg_out_bswap32(s, datalo);
+        }
+        break;
+    case 3:
+        if (bswap) {
+            int t = datalo;
+            datalo = datahi;
+            datahi = t;
+        }
+        if (base != datalo) {
+            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+        } else {
+            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+        }
+        if (bswap) {
+            tcg_out_bswap32(s, datalo);
+            tcg_out_bswap32(s, datahi);
+        }
+        break;
+    default:
+        tcg_abort();
+    }
+}
 
 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
    EAX. It will be useful once fixed registers globals are less
@@ -714,7 +771,7 @@ static void *qemu_st_helpers[4] = {
 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
 #if defined(CONFIG_SOFTMMU)
     uint8_t *label1_ptr, *label2_ptr;
 #endif
@@ -831,80 +888,74 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
     tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
                          offsetof(CPUTLBEntry, addend) -
                          offsetof(CPUTLBEntry, addr_read));
+
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
+
+    /* label2: */
+    *label2_ptr = s->code_ptr - label2_ptr - 1;
 #else
-    r0 = addr_reg;
+    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
 #endif
+}
 
+static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
+                                   int base, tcg_target_long ofs, int sizeop)
+{
 #ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
+    const int bswap = 1;
 #else
-    bswap = 0;
+    const int bswap = 0;
 #endif
-    switch(opc) {
+    /* ??? Ideally we wouldn't need a scratch register.  For user-only,
+       we could perform the bswap twice to restore the original value
+       instead of moving to the scratch.  But as it is, the L constraint
+       means that EDX is definitely free here.  */
+    int scratch = TCG_REG_EDX;
+
+    switch (sizeop) {
     case 0:
-        /* movzbl */
-        tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
-        break;
-    case 0 | 4:
-        /* movsbl */
-        tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
+        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
         break;
     case 1:
-        /* movzwl */
-        tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
-        if (bswap) {
-            tcg_out_rolw_8(s, data_reg);
-        }
-        break;
-    case 1 | 4:
-        /* movswl */
-        tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
         if (bswap) {
-            tcg_out_rolw_8(s, data_reg);
-
-            /* movswl data_reg, data_reg */
-            tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
+            tcg_out_mov(s, scratch, datalo);
+            tcg_out_rolw_8(s, scratch);
+            datalo = scratch;
         }
+        /* movw */
+        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+                             datalo, base, ofs);
         break;
     case 2:
-        tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
         if (bswap) {
-            tcg_out_bswap32(s, data_reg);
+            tcg_out_mov(s, scratch, datalo);
+            tcg_out_bswap32(s, scratch);
+            datalo = scratch;
         }
+        tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
         break;
     case 3:
         if (bswap) {
-            int t = data_reg;
-            data_reg = data_reg2;
-            data_reg2 = t;
-        }
-        if (r0 != data_reg) {
-            tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
-            tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
+            tcg_out_mov(s, scratch, datahi);
+            tcg_out_bswap32(s, scratch);
+            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
+            tcg_out_mov(s, scratch, datalo);
+            tcg_out_bswap32(s, scratch);
+            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
         } else {
-            tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
-            tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
-        }
-        if (bswap) {
-            tcg_out_bswap32(s, data_reg);
-            tcg_out_bswap32(s, data_reg2);
+            tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
+            tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
         }
         break;
     default:
         tcg_abort();
     }
-
-#if defined(CONFIG_SOFTMMU)
-    /* label2: */
-    *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
 }
 
-
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                             int opc)
 {
-    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
 #if defined(CONFIG_SOFTMMU)
     int stack_adjust;
     uint8_t *label1_ptr, *label2_ptr;
@@ -1041,57 +1092,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
     tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
                          offsetof(CPUTLBEntry, addend) -
                          offsetof(CPUTLBEntry, addr_write));
-#else
-    r0 = addr_reg;
-#endif
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    bswap = 1;
-#else
-    bswap = 0;
-#endif
-    switch(opc) {
-    case 0:
-        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
-        break;
-    case 1:
-        if (bswap) {
-            tcg_out_mov(s, r1, data_reg);
-            tcg_out_rolw_8(s, r1);
-            data_reg = r1;
-        }
-        /* movw */
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
-                             data_reg, r0, GUEST_BASE);
-        break;
-    case 2:
-        if (bswap) {
-            tcg_out_mov(s, r1, data_reg);
-            tcg_out_bswap32(s, r1);
-            data_reg = r1;
-        }
-        tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
-        break;
-    case 3:
-        if (bswap) {
-            tcg_out_mov(s, r1, data_reg2);
-            tcg_out_bswap32(s, r1);
-            tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
-            tcg_out_mov(s, r1, data_reg);
-            tcg_out_bswap32(s, r1);
-            tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
-        } else {
-            tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
-            tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
-        }
-        break;
-    default:
-        tcg_abort();
-    }
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
 
-#if defined(CONFIG_SOFTMMU)
     /* label2: */
     *label2_ptr = s->code_ptr - label2_ptr - 1;
+#else
+    tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
 #endif
 }
 
commit 96b4cf38f050d61d01d23d373ce059013b8a6090
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri May 21 09:03:00 2010 -0700

    tcg-i386: Tidy data16 prefixes.
    
    Include it in the opcode as an extension, as with P_EXT
    or the REX bits in the x86-64 port.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 396a2f1..9226c1e 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -156,7 +156,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
         return 0;
 }
 
-#define P_EXT   0x100 /* 0x0f opcode prefix */
+#define P_EXT		0x100		/* 0x0f opcode prefix */
+#define P_DATA16	0x200		/* 0x66 opcode prefix */
 
 #define OPC_ARITH_EvIz	(0x81)
 #define OPC_ARITH_EvIb	(0x83)
@@ -262,8 +263,12 @@ static const uint8_t tcg_cond_to_jcc[10] = {
 
 static inline void tcg_out_opc(TCGContext *s, int opc)
 {
-    if (opc & P_EXT)
+    if (opc & P_DATA16) {
+        tcg_out8(s, 0x66);
+    }
+    if (opc & P_EXT) {
         tcg_out8(s, 0x0f);
+    }
     tcg_out8(s, opc);
 }
 
@@ -396,10 +401,14 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
 
 static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
 {
+    /* Propagate an opcode prefix, such as P_DATA16.  */
+    int ext = subopc & ~0x7;
+    subopc &= 0x7;
+
     if (count == 1) {
-        tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
+        tcg_out_modrm(s, OPC_SHIFT_1 | ext, subopc, reg);
     } else {
-        tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
+        tcg_out_modrm(s, OPC_SHIFT_Ib | ext, subopc, reg);
         tcg_out8(s, count);
     }
 }
@@ -411,8 +420,7 @@ static inline void tcg_out_bswap32(TCGContext *s, int reg)
 
 static inline void tcg_out_rolw_8(TCGContext *s, int reg)
 {
-    tcg_out8(s, 0x66);
-    tcg_out_shifti(s, SHIFT_ROL, reg, 8);
+    tcg_out_shifti(s, SHIFT_ROL | P_DATA16, reg, 8);
 }
 
 static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
@@ -1053,8 +1061,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
             data_reg = r1;
         }
         /* movw */
-        tcg_out8(s, 0x66);
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
+        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+                             data_reg, r0, GUEST_BASE);
         break;
     case 2:
         if (bswap) {
@@ -1159,8 +1167,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_st16_i32:
         /* movw */
-        tcg_out8(s, 0x66);
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
+        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+                             args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i32:
         tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
commit fb170183e7387ade9aef2bddd59a8a62fceedac6
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:58 2010 +0400

    sparc64: fix umul and smul insns
    
    - truncate and sign or zero extend operands before multiplication
    - factor out common code to gen_op_multiply() with parameter to sign/zero extend
    - call gen_op_multiply from gen_op_umul and gen_op_smul
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0bc1a82..23f9519 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -662,50 +662,53 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
     tcg_gen_mov_tl(dst, cpu_cc_dst);
 }
 
-static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
+static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
 {
+    TCGv_i32 r_src1, r_src2;
     TCGv_i64 r_temp, r_temp2;
 
+    r_src1 = tcg_temp_new_i32();
+    r_src2 = tcg_temp_new_i32();
+
+    tcg_gen_trunc_tl_i32(r_src1, src1);
+    tcg_gen_trunc_tl_i32(r_src2, src2);
+
     r_temp = tcg_temp_new_i64();
     r_temp2 = tcg_temp_new_i64();
 
-    tcg_gen_extu_tl_i64(r_temp, src2);
-    tcg_gen_extu_tl_i64(r_temp2, src1);
+    if (sign_ext) {
+        tcg_gen_ext_i32_i64(r_temp, r_src2);
+        tcg_gen_ext_i32_i64(r_temp2, r_src1);
+    } else {
+        tcg_gen_extu_i32_i64(r_temp, r_src2);
+        tcg_gen_extu_i32_i64(r_temp2, r_src1);
+    }
+
     tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);
 
     tcg_gen_shri_i64(r_temp, r_temp2, 32);
     tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
     tcg_temp_free_i64(r_temp);
     tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
-#ifdef TARGET_SPARC64
-    tcg_gen_mov_i64(dst, r_temp2);
-#else
+
     tcg_gen_trunc_i64_tl(dst, r_temp2);
-#endif
+
     tcg_temp_free_i64(r_temp2);
+
+    tcg_temp_free_i32(r_src1);
+    tcg_temp_free_i32(r_src2);
 }
 
-static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
+static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
 {
-    TCGv_i64 r_temp, r_temp2;
-
-    r_temp = tcg_temp_new_i64();
-    r_temp2 = tcg_temp_new_i64();
-
-    tcg_gen_ext_tl_i64(r_temp, src2);
-    tcg_gen_ext_tl_i64(r_temp2, src1);
-    tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);
+    /* zero-extend truncated operands before multiplication */
+    gen_op_multiply(dst, src1, src2, 0);
+}
 
-    tcg_gen_shri_i64(r_temp, r_temp2, 32);
-    tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
-    tcg_temp_free_i64(r_temp);
-    tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
-#ifdef TARGET_SPARC64
-    tcg_gen_mov_i64(dst, r_temp2);
-#else
-    tcg_gen_trunc_i64_tl(dst, r_temp2);
-#endif
-    tcg_temp_free_i64(r_temp2);
+static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
+{
+    /* sign-extend truncated operands before multiplication */
+    gen_op_multiply(dst, src1, src2, 1);
 }
 
 #ifdef TARGET_SPARC64
commit 09487205bb03548d260300d32595ba17ab597337
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:53 2010 +0400

    sparc64: fix udiv and sdiv insns
    
    - truncate second operand to 32bit
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 470c710..be3c1e0 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3306,7 +3306,7 @@ target_ulong helper_udiv(target_ulong a, target_ulong b)
     uint32_t x1;
 
     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
-    x1 = b;
+    x1 = (b & 0xffffffff);
 
     if (x1 == 0) {
         raise_exception(TT_DIV_ZERO);
@@ -3328,7 +3328,7 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b)
     int32_t x1;
 
     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
-    x1 = b;
+    x1 = (b & 0xffffffff);
 
     if (x1 == 0) {
         raise_exception(TT_DIV_ZERO);
commit 0e2fa9cab9c124788077de728f1e6744d1dd8bb2
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:48 2010 +0400

    sparc64: improve ldf and stf insns
    
    - implemented block load/store primary/secondary with user privilege
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 842dbd3..470c710 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3164,6 +3164,20 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
         }
 
         return;
+    case 0x70: // Block load primary, user privilege
+    case 0x71: // Block load secondary, user privilege
+        if (rd & 7) {
+            raise_exception(TT_ILL_INSN);
+            return;
+        }
+        helper_check_align(addr, 0x3f);
+        for (i = 0; i < 16; i++) {
+            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x1f, 4,
+                                                         0);
+            addr += 4;
+        }
+
+        return;
     default:
         break;
     }
@@ -3210,6 +3224,20 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
         }
 
         return;
+    case 0x70: // Block store primary, user privilege
+    case 0x71: // Block store secondary, user privilege
+        if (rd & 7) {
+            raise_exception(TT_ILL_INSN);
+            return;
+        }
+        helper_check_align(addr, 0x3f);
+        for (i = 0; i < 16; i++) {
+            val = *(uint32_t *)&env->fpr[rd++];
+            helper_st_asi(addr, val, asi & 0x1f, 4);
+            addr += 4;
+        }
+
+        return;
     default:
         break;
     }
commit b219094acea73602e3a5ef8bfb4f3ca60c2ee56f
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 23:39:09 2010 +0400

    sparc64: use symbolic name for MMU index v1
    
    - use symbolic name for MMU index
    v0->v1:
    - change debug traces to DPRINTF_MMU
    - fix debug trace function names
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index f5e4633..842dbd3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3321,18 +3321,19 @@ void helper_stdf(target_ulong addr, int mem_idx)
     helper_check_align(addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
-    case 0:
+    case MMU_USER_IDX:
         stfq_user(addr, DT0);
         break;
-    case 1:
+    case MMU_KERNEL_IDX:
         stfq_kernel(addr, DT0);
         break;
 #ifdef TARGET_SPARC64
-    case 2:
+    case MMU_HYPV_IDX:
         stfq_hypv(addr, DT0);
         break;
 #endif
     default:
+        DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx);
         break;
     }
 #else
@@ -3345,18 +3346,19 @@ void helper_lddf(target_ulong addr, int mem_idx)
     helper_check_align(addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
-    case 0:
+    case MMU_USER_IDX:
         DT0 = ldfq_user(addr);
         break;
-    case 1:
+    case MMU_KERNEL_IDX:
         DT0 = ldfq_kernel(addr);
         break;
 #ifdef TARGET_SPARC64
-    case 2:
+    case MMU_HYPV_IDX:
         DT0 = ldfq_hypv(addr);
         break;
 #endif
     default:
+        DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx);
         break;
     }
 #else
@@ -3372,24 +3374,25 @@ void helper_ldqf(target_ulong addr, int mem_idx)
     helper_check_align(addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
-    case 0:
+    case MMU_USER_IDX:
         u.ll.upper = ldq_user(addr);
         u.ll.lower = ldq_user(addr + 8);
         QT0 = u.q;
         break;
-    case 1:
+    case MMU_KERNEL_IDX:
         u.ll.upper = ldq_kernel(addr);
         u.ll.lower = ldq_kernel(addr + 8);
         QT0 = u.q;
         break;
 #ifdef TARGET_SPARC64
-    case 2:
+    case MMU_HYPV_IDX:
         u.ll.upper = ldq_hypv(addr);
         u.ll.lower = ldq_hypv(addr + 8);
         QT0 = u.q;
         break;
 #endif
     default:
+        DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx);
         break;
     }
 #else
@@ -3407,24 +3410,25 @@ void helper_stqf(target_ulong addr, int mem_idx)
     helper_check_align(addr, 7);
 #if !defined(CONFIG_USER_ONLY)
     switch (mem_idx) {
-    case 0:
+    case MMU_USER_IDX:
         u.q = QT0;
         stq_user(addr, u.ll.upper);
         stq_user(addr + 8, u.ll.lower);
         break;
-    case 1:
+    case MMU_KERNEL_IDX:
         u.q = QT0;
         stq_kernel(addr, u.ll.upper);
         stq_kernel(addr + 8, u.ll.lower);
         break;
 #ifdef TARGET_SPARC64
-    case 2:
+    case MMU_HYPV_IDX:
         u.q = QT0;
         stq_hypv(addr, u.ll.upper);
         stq_hypv(addr + 8, u.ll.lower);
         break;
 #endif
     default:
+        DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx);
         break;
     }
 #else
commit fe987e2394e1fca01aba581095f219423fbbdd39
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:37 2010 +0400

    sparc64: fix ldxfsr insn
    
    - rearrange code to break from switch when appropriate
    - allow deprecated ldfsr insn
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index eff64d4..0bc1a82 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4476,7 +4476,11 @@ static void disas_sparc_insn(DisasContext * dc)
                     if (rd == 1) {
                         tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
                         gen_helper_ldxfsr(cpu_tmp64);
-                    } else
+                    } else {
+                        tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
+                        tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
+                        gen_helper_ldfsr(cpu_tmp32);
+                    }
 #else
                     {
                         tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
commit c086b783eb7a578993d6d2ab62c4c2666800b63d
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:32 2010 +0400

    sparc64: fix 32bit load sign extension
    
    - change return type of ldl_* to uint32_t to prevent unwanted sign extension
      visible in sparc64 load alternate address space methods
    - note this change makes ldl_* softmmu implementations match ldl_phys one
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/softmmu_header.h b/softmmu_header.h
index 6a36e01..2f95c33 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -60,7 +60,7 @@
 #if DATA_SIZE == 8
 #define RES_TYPE uint64_t
 #else
-#define RES_TYPE int
+#define RES_TYPE uint32_t
 #endif
 
 #if ACCESS_TYPE == (NB_MMU_MODES + 1)
commit 1295001c53fe816776bae810bed0a653ea0c6475
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 23:38:45 2010 +0400

    sparc64: fix missing address masking v1
    
    - address masking for ldqf and stqf insns
    - address masking for lddf and stdf insns
    - address masking for translating ASI (Ultrasparc IIi)
    v0->v1:
    - move arch-specific code to helpers and drop more ifdefs at call sites
      using new helper asi_address_mask()
    - change user emulation to use asi_address_mask()
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index ef3504f..f5e4633 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -247,6 +247,42 @@ static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
     return addr;
 }
 
+/* returns true if access using this ASI is to have address translated by MMU
+   otherwise access is to raw physical address */
+static inline int is_translating_asi(int asi)
+{
+#ifdef TARGET_SPARC64
+    /* Ultrasparc IIi translating asi
+       - note this list is defined by cpu implementation
+     */
+    switch (asi) {
+    case 0x04 ... 0x11:
+    case 0x18 ... 0x19:
+    case 0x24 ... 0x2C:
+    case 0x70 ... 0x73:
+    case 0x78 ... 0x79:
+    case 0x80 ... 0xFF:
+        return 1;
+
+    default:
+        return 0;
+    }
+#else
+    /* TODO: check sparc32 bits */
+    return 0;
+#endif
+}
+
+static inline target_ulong asi_address_mask(CPUState *env1,
+                                            int asi, target_ulong addr)
+{
+    if (is_translating_asi(asi)) {
+        return address_mask(env, addr);
+    } else {
+        return addr;
+    }
+}
+
 static void raise_exception(int tt)
 {
     env->exception_index = tt;
@@ -2151,7 +2187,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
-    addr = address_mask(env, addr);
+    addr = asi_address_mask(env, asi, addr);
 
     switch (asi) {
     case 0x82: // Primary no-fault
@@ -2254,7 +2290,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
-    addr = address_mask(env, addr);
+    addr = asi_address_mask(env, asi, addr);
 
     /* Convert to little endian */
     switch (asi) {
@@ -2331,6 +2367,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
+    addr = asi_address_mask(env, asi, addr);
+
     switch (asi) {
     case 0x82: // Primary no-fault
     case 0x8a: // Primary no-fault LE
@@ -2682,6 +2720,8 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
         raise_exception(TT_PRIV_ACT);
 
     helper_check_align(addr, size - 1);
+    addr = asi_address_mask(env, asi, addr);
+
     /* Convert to little endian */
     switch (asi) {
     case 0x0c: // Nucleus Little Endian (LE)
@@ -3056,6 +3096,8 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
             && !(env->hpstate & HS_PRIV)))
         raise_exception(TT_PRIV_ACT);
 
+    addr = asi_address_mask(env, asi, addr);
+
     switch (asi) {
 #if !defined(CONFIG_USER_ONLY)
     case 0x24: // Nucleus quad LDD 128 bit atomic
@@ -3103,6 +3145,8 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
     target_ulong val;
 
     helper_check_align(addr, 3);
+    addr = asi_address_mask(env, asi, addr);
+
     switch (asi) {
     case 0xf0: // Block load primary
     case 0xf1: // Block load secondary
@@ -3145,6 +3189,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
     target_ulong val = 0;
 
     helper_check_align(addr, 3);
+    addr = asi_address_mask(env, asi, addr);
+
     switch (asi) {
     case 0xe0: // UA2007 Block commit store primary (cache flush)
     case 0xe1: // UA2007 Block commit store secondary (cache flush)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 72ca0b4..eff64d4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4490,6 +4490,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         CHECK_FPU_FEATURE(dc, FLOAT128);
                         r_const = tcg_const_i32(dc->mem_idx);
+                        gen_address_mask(dc, cpu_addr);
                         gen_helper_ldqf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
@@ -4500,6 +4501,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         TCGv_i32 r_const;
 
                         r_const = tcg_const_i32(dc->mem_idx);
+                        gen_address_mask(dc, cpu_addr);
                         gen_helper_lddf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_DT0_fpr(DFPREG(rd));
@@ -4635,6 +4637,7 @@ static void disas_sparc_insn(DisasContext * dc)
                         CHECK_FPU_FEATURE(dc, FLOAT128);
                         gen_op_load_fpr_QT0(QFPREG(rd));
                         r_const = tcg_const_i32(dc->mem_idx);
+                        gen_address_mask(dc, cpu_addr);
                         gen_helper_stqf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                     }
@@ -4657,6 +4660,7 @@ static void disas_sparc_insn(DisasContext * dc)
 
                         gen_op_load_fpr_DT0(DFPREG(rd));
                         r_const = tcg_const_i32(dc->mem_idx);
+                        gen_address_mask(dc, cpu_addr);
                         gen_helper_stdf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                     }
commit 9168b3a545fae3db8ad0ee7de872c4302651ba7f
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date:   Wed Jun 2 00:12:22 2010 +0400

    sparc64: fix tag access register on mmu traps
    
    - set mmu tag access register on FAULT and PROT traps as well
    
    Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 96a22f3..aa1fd63 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -495,6 +495,9 @@ static int get_physical_address_data(CPUState *env,
             env->dmmu.sfsr |= (fault_type << 7);
 
             env->dmmu.sfar = address; /* Fault address register */
+
+            env->dmmu.tag_access = (address & ~0x1fffULL) | context;
+
             return 1;
         }
     }
@@ -544,6 +547,8 @@ static int get_physical_address_code(CPUState *env,
                 env->immu.sfsr |= (is_user << 3) | 1;
                 env->exception_index = TT_TFAULT;
 
+                env->immu.tag_access = (address & ~0x1fffULL) | context;
+
                 DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
                             address, context);
 
commit 7f9744812291853425b614f68668f48d49882a1f
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Jun 2 11:40:54 2010 +0300

    virtio-net: stop vhost backend on vmstop
    
    vhost net currently keeps running after vmstop,
    which causes trouble as qemy does not check
    for dirty pages anymore.
    The fix is to simply keep vm and vhost running/stopped
    status in sync.
    
    Tested-by: David L Stevens <dlstevens at us.ibm.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index cb664e6..6a9d560 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -877,12 +877,11 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
 static void virtio_net_vmstate_change(void *opaque, int running, int reason)
 {
     VirtIONet *n = opaque;
-    if (!running) {
-        return;
-    }
-    /* This is called when vm is started, it will start vhost backend if
-     * appropriate e.g. after migration. */
-    virtio_net_set_status(&n->vdev, n->vdev.status);
+    uint8_t status = running ? VIRTIO_CONFIG_S_DRIVER_OK : 0;
+    /* This is called when vm is started/stopped,
+     * it will start/stop vhost backend if * appropriate
+     * e.g. after migration. */
+    virtio_net_set_status(&n->vdev, n->vdev.status & status);
 }
 
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
commit d9b73e47a3d596c5b33802597ec5bd91ef3348e2
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Tue Jun 1 23:05:44 2010 +0200

    vnc: add missing target for vnc-encodings-*.o
    
    vnc-encodings-*.c dependencies where missing.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index cc5fc45..221fbd8 100644
--- a/Makefile
+++ b/Makefile
@@ -120,11 +120,11 @@ vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
 
 vnc-auth-sasl.o: vnc-auth-sasl.c vnc.h
 
-vnc-encoding-zlib.o: vnc.h
+vnc-encoding-zlib.o: vnc-encoding-zlib.c vnc.h
 
-vnc-encoding-hextile.o: vnc.h
+vnc-encoding-hextile.o: vnc-encoding-hextile.c vnc.h
 
-vnc-encoding-tight.o: vnc.h vnc-encoding-tight.h
+vnc-encoding-tight.o: vnc-encoding-tight.c vnc.h vnc-encoding-tight.h
 
 curses.o: curses.c keymaps.h curses_keys.h
 
commit 270ec21929b029e6cca27656fcbf1c775e42f6d7
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Tue Jun 1 23:05:43 2010 +0200

    vnc: tight: don't forget the third color
    
    While couting color, if the third color was only present one
    time it wasn't added to the palette.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 7bde44d..e8604a8 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -177,6 +177,7 @@ static int tight_palette_insert(QDict *palette, uint32_t rgb, int bpp, int max)
         *palette = qdict_new();                                         \
         tight_palette_insert(*palette, c0, bpp, max);                   \
         tight_palette_insert(*palette, c1, bpp, max);                   \
+        tight_palette_insert(*palette, ci, bpp, max);                   \
                                                                         \
         for (i++; i < count; i++) {                                     \
             if (data[i] == ci) {                                        \
commit 54d43eacc5ca300d5a5ce5a83abe75e0167946b5
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Tue Jun 1 23:05:42 2010 +0200

    vnc: tight: don't forget last pixel in tight_encode_indexed_rect
    
    A simple patch would have been to just remove count -= 1, but this
    one also replace the while (count--) with a for(i = 0; i < count; i++)
    which I believe is more easy to understand.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 50be44e..7bde44d 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -249,17 +249,16 @@ static void print_palette(const char *key, QObject *obj, void *opaque)
         uint##bpp##_t *src;                                             \
         uint##bpp##_t rgb;                                              \
         uint8_t key[6];                                                 \
-        int rep = 0;                                                    \
+        int i, rep;                                                     \
         uint8_t idx;                                                    \
                                                                         \
         src = (uint##bpp##_t *) buf;                                    \
                                                                         \
-        count -= 1;                                                     \
-        while (count--) {                                               \
+        for (i = 0; i < count; i++) {                                   \
             rgb = *src++;                                               \
             rep = 0;                                                    \
-            while (count && *src == rgb) {                              \
-                rep++, src++, count--;                                  \
+            while (i < count && *src == rgb) {                          \
+                rep++, src++, i++;                                      \
             }                                                           \
             tight_palette_rgb2buf(rgb, bpp, key);                       \
             if (!qdict_haskey(palette, (char *)key)) {                  \
commit 637503d122eb7656d91a8489e254d9e880be7504
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon May 31 14:43:32 2010 -0300

    Monitor: Drop QMP documentation from code
    
    Previous commit added QMP documentation to the qemu-monitor.hx
    file, it's is a copy of this information.
    
    While it's good to keep it near code, maintaining two copies of
    the same information is too hard and has little benefit as we
    don't expect client writers to consult the code to find how to
    use a QMP command.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/block.c b/block.c
index cd70730..67f0998 100644
--- a/block.c
+++ b/block.c
@@ -1444,33 +1444,6 @@ void bdrv_info_print(Monitor *mon, const QObject *data)
     qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
 }
 
-/**
- * bdrv_info(): Block devices information
- *
- * Each block device information is stored in a QDict and the
- * returned QObject is a QList of all devices.
- *
- * The QDict contains the following:
- *
- * - "device": device name
- * - "type": device type
- * - "removable": true if the device is removable, false otherwise
- * - "locked": true if the device is locked, false otherwise
- * - "inserted": only present if the device is inserted, it is a QDict
- *    containing the following:
- *          - "file": device file name
- *          - "ro": true if read-only, false otherwise
- *          - "drv": driver format name
- *          - "backing_file": backing file name if one is used
- *          - "encrypted": true if encrypted, false otherwise
- *
- * Example:
- *
- * [ { "device": "ide0-hd0", "type": "hd", "removable": false, "locked": false,
- *     "inserted": { "file": "/tmp/foobar", "ro": false, "drv": "qcow2" } },
- *   { "device": "floppy0", "type": "floppy", "removable": true,
- *     "locked": false } ]
- */
 void bdrv_info(Monitor *mon, QObject **ret_data)
 {
     QList *bs_list;
@@ -1576,48 +1549,6 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
     return res;
 }
 
-/**
- * bdrv_info_stats(): show block device statistics
- *
- * Each device statistic information is stored in a QDict and
- * the returned QObject is a QList of all devices.
- *
- * The QDict contains the following:
- *
- * - "device": device name
- * - "stats": A QDict with the statistics information, it contains:
- *     - "rd_bytes": bytes read
- *     - "wr_bytes": bytes written
- *     - "rd_operations": read operations
- *     - "wr_operations": write operations
- *     - "wr_highest_offset": Highest offset of a sector written since the
- *       BlockDriverState has been opened
- * - "parent": A QDict recursively holding the statistics of the underlying
- *    protocol (e.g. the host file for a qcow2 image). If there is no
- *    underlying protocol, this field is omitted.
- *
- * Example:
- *
- * [ { "device": "ide0-hd0",
- *               "stats": { "rd_bytes": 512,
- *                          "wr_bytes": 0,
- *                          "rd_operations": 1,
- *                          "wr_operations": 0,
- *                          "wr_highest_offset": 0 },
- *               "parent": {
- *                      "stats": { "rd_bytes": 1024,
- *                                 "wr_bytes": 0,
- *                                 "rd_operations": 2,
- *                                 "wr_operations": 0,
- *                                 "wr_highest_offset": 0,
- *                      } } },
- *   { "device": "ide1-cd0",
- *               "stats": { "rd_bytes": 0,
- *                          "wr_bytes": 0,
- *                          "rd_operations": 0,
- *                          "wr_operations": 0,
- *                          "wr_highest_offset": 0 } },
- */
 void bdrv_info_stats(Monitor *mon, QObject **ret_data)
 {
     QObject *obj;
diff --git a/hw/pci.c b/hw/pci.c
index f084cc0..cbbd1dd 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1380,67 +1380,6 @@ static QObject *pci_get_bus_dict(PCIBus *bus, int bus_num)
     return NULL;
 }
 
-/**
- * do_pci_info(): PCI buses and devices information
- *
- * The returned QObject is a QList of all buses. Each bus is
- * represented by a QDict, which has a key with a QList of all
- * PCI devices attached to it. Each device is represented by
- * a QDict.
- *
- * The bus QDict contains the following:
- *
- * - "bus": bus number
- * - "devices": a QList of QDicts, each QDict represents a PCI
- *   device
- *
- * The PCI device QDict contains the following:
- *
- * - "bus": identical to the parent's bus number
- * - "slot": slot number
- * - "function": function number
- * - "class_info": a QDict containing:
- *      - "desc": device class description (optional)
- *      - "class": device class number
- * - "id": a QDict containing:
- *      - "device": device ID
- *      - "vendor": vendor ID
- * - "irq": device's IRQ if assigned (optional)
- * - "qdev_id": qdev id string
- * - "pci_bridge": It's a QDict, only present if this device is a
- *   PCI bridge, contains:
- *      - "bus": bus number
- *      - "secondary": secondary bus number
- *      - "subordinate": subordinate bus number
- *      - "io_range": a QDict with memory range information
- *      - "memory_range": a QDict with memory range information
- *      - "prefetchable_range": a QDict with memory range information
- *      - "devices": a QList of PCI devices if there's any attached (optional)
- * - "regions": a QList of QDicts, each QDict represents a
- *   memory region of this device
- *
- * The memory range QDict contains the following:
- *
- * - "base": base memory address
- * - "limit": limit value
- *
- * The region QDict can be an I/O region or a memory region,
- * an I/O region QDict contains the following:
- *
- * - "type": "io"
- * - "bar": BAR number
- * - "address": memory address
- * - "size": memory size
- *
- * A memory region QDict contains the following:
- *
- * - "type": "memory"
- * - "bar": BAR number
- * - "address": memory address
- * - "size": memory size
- * - "mem_type_64": true or false
- * - "prefetch": true or false
- */
 void do_pci_info(Monitor *mon, QObject **ret_data)
 {
     QList *bus_list;
diff --git a/hw/qdev.c b/hw/qdev.c
index af17486..aa2ce01 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -779,19 +779,6 @@ void do_info_qdm(Monitor *mon)
     }
 }
 
-/**
- * do_device_add(): Add a device
- *
- * Argument qdict contains
- * - "driver": the name of the new device's driver
- * - "bus": the device's parent bus (device tree path)
- * - "id": the device's ID (must be unique)
- * - device properties
- *
- * Example:
- *
- * { "driver": "usb-net", "id": "eth1", "netdev": "netdev1" }
- */
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     QemuOpts *opts;
diff --git a/input.c b/input.c
index 8f0941e..651442d 100644
--- a/input.c
+++ b/input.c
@@ -214,24 +214,6 @@ void do_info_mice_print(Monitor *mon, const QObject *data)
     qlist_iter(mice_list, info_mice_iter, mon);
 }
 
-/**
- * do_info_mice(): Show VM mice information
- *
- * Each mouse is represented by a QDict, the returned QObject is a QList of
- * all mice.
- *
- * The mouse QDict contains the following:
- *
- * - "name": mouse's name
- * - "index": mouse's index
- * - "current": true if this mouse is receiving events, false otherwise
- * - "absolute": true if the mouse generates absolute input events
- *
- * Example:
- *
- * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false, "absolute": false },
- *   { "name": "QEMU PS/2 Mouse", "index": 1, "current": true, "absolute": true } ]
- */
 void do_info_mice(Monitor *mon, QObject **ret_data)
 {
     QEMUPutMouseEntry *cursor;
diff --git a/migration.c b/migration.c
index 05f6cc5..706fe55 100644
--- a/migration.c
+++ b/migration.c
@@ -197,44 +197,6 @@ static void migrate_put_status(QDict *qdict, const char *name,
     qdict_put_obj(qdict, name, obj);
 }
 
-/**
- * do_info_migrate(): Migration status
- *
- * Return a QDict. If migration is active there will be another
- * QDict with RAM migration status and if block migration is active
- * another one with block migration status.
- *
- * The main QDict contains the following:
- *
- * - "status": migration status
- * - "ram": only present if "status" is "active", it is a QDict with the
- *   following RAM information (in bytes):
- *          - "transferred": amount transferred
- *          - "remaining": amount remaining
- *          - "total": total
- * - "disk": only present if "status" is "active" and it is a block migration,
- *   it is a QDict with the following disk information (in bytes):
- *          - "transferred": amount transferred
- *          - "remaining": amount remaining
- *          - "total": total
- *
- * Examples:
- *
- * 1. Migration is "completed":
- *
- * { "status": "completed" }
- *
- * 2. Migration is "active" and it is not a block migration:
- *
- * { "status": "active",
- *            "ram": { "transferred": 123, "remaining": 123, "total": 246 } }
- *
- * 3. Migration is "active" and it is a block migration:
- *
- * { "status": "active",
- *   "ram": { "total": 1057024, "remaining": 1053304, "transferred": 3720 },
- *   "disk": { "total": 20971520, "remaining": 20880384, "transferred": 91136 }}
- */
 void do_info_migrate(Monitor *mon, QObject **ret_data)
 {
     QDict *qdict;
diff --git a/monitor.c b/monitor.c
index ad50f12..15b53b9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -677,18 +677,6 @@ static void do_info_version_print(Monitor *mon, const QObject *data)
                                   qdict_get_str(qdict, "package"));
 }
 
-/**
- * do_info_version(): Show QEMU version
- *
- * Return a QDict with the following information:
- *
- * - "qemu": QEMU's version
- * - "package": package's version
- *
- * Example:
- *
- * { "qemu": "0.11.50", "package": "" }
- */
 static void do_info_version(Monitor *mon, QObject **ret_data)
 {
     *ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
@@ -707,17 +695,6 @@ static void do_info_name_print(Monitor *mon, const QObject *data)
     monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
 }
 
-/**
- * do_info_name(): Show VM name
- *
- * Return a QDict with the following information:
- *
- * - "name": VM's name (optional)
- *
- * Example:
- *
- * { "name": "qemu-name" }
- */
 static void do_info_name(Monitor *mon, QObject **ret_data)
 {
     *ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
@@ -739,20 +716,6 @@ static QObject *get_cmd_dict(const char *name)
     return qobject_from_jsonf("{ 'name': %s }", p);
 }
 
-/**
- * do_info_commands(): List QMP available commands
- *
- * Each command is represented by a QDict, the returned QObject is a QList
- * of all commands.
- *
- * The QDict contains:
- *
- * - "name": command's name
- *
- * Example:
- *
- * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
- */
 static void do_info_commands(Monitor *mon, QObject **ret_data)
 {
     QList *cmd_list;
@@ -785,17 +748,6 @@ static void do_info_hpet_print(Monitor *mon, const QObject *data)
                    "enabled" : "disabled");
 }
 
-/**
- * do_info_hpet(): Show HPET state
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if hpet if enabled, false otherwise
- *
- * Example:
- *
- * { "enabled": true }
- */
 static void do_info_hpet(Monitor *mon, QObject **ret_data)
 {
     *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
@@ -807,17 +759,6 @@ static void do_info_uuid_print(Monitor *mon, const QObject *data)
     monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
 }
 
-/**
- * do_info_uuid(): Show VM UUID
- *
- * Return a QDict with the following information:
- *
- * - "UUID": Universally Unique Identifier
- *
- * Example:
- *
- * { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
- */
 static void do_info_uuid(Monitor *mon, QObject **ret_data)
 {
     char uuid[64];
@@ -913,25 +854,6 @@ static void monitor_print_cpus(Monitor *mon, const QObject *data)
     qlist_iter(cpu_list, print_cpu_iter, mon);
 }
 
-/**
- * do_info_cpus(): Show CPU information
- *
- * Return a QList. Each CPU is represented by a QDict, which contains:
- *
- * - "cpu": CPU index
- * - "current": true if this is the current CPU, false otherwise
- * - "halted": true if the cpu is halted, false otherwise
- * - Current program counter. The key's name depends on the architecture:
- *      "pc": i386/x86)64
- *      "nip": PPC
- *      "pc" and "npc": sparc
- *      "PC": mips
- *
- * Example:
- *
- * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
- *   { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
- */
 static void do_info_cpus(Monitor *mon, QObject **ret_data)
 {
     CPUState *env;
@@ -2106,18 +2028,6 @@ static void do_info_kvm_print(Monitor *mon, const QObject *data)
     }
 }
 
-/**
- * do_info_kvm(): Show KVM information
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if KVM support is enabled, false otherwise
- * - "present": true if QEMU has KVM support, false otherwise
- *
- * Example:
- *
- * { "enabled": true, "present": true }
- */
 static void do_info_kvm(Monitor *mon, QObject **ret_data)
 {
 #ifdef CONFIG_KVM
@@ -2261,18 +2171,6 @@ static void do_info_status_print(Monitor *mon, const QObject *data)
     monitor_printf(mon, "\n");
 }
 
-/**
- * do_info_status(): VM status
- *
- * Return a QDict with the following information:
- *
- * - "running": true if the VM is running, or false if it is paused
- * - "singlestep": true if the VM is in single step mode, false otherwise
- *
- * Example:
- *
- * { "running": true, "singlestep": false }
- */
 static void do_info_status(Monitor *mon, QObject **ret_data)
 {
     *ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
diff --git a/net.c b/net.c
index 378edfc..efa8b3d 100644
--- a/net.c
+++ b/net.c
@@ -1194,18 +1194,6 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
     qemu_del_vlan_client(vc);
 }
 
-/**
- * do_netdev_add(): Add a host network device
- *
- * Argument qdict contains
- * - "type": the device type, "tap", "user", ...
- * - "id": the device's ID (must be unique)
- * - device options
- *
- * Example:
- *
- * { "type": "user", "id": "netdev1", "hostname": "a-guest" }
- */
 int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     QemuOpts *opts;
@@ -1220,16 +1208,6 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return res;
 }
 
-/**
- * do_netdev_del(): Delete a host network device
- *
- * Argument qdict contains
- * - "id": the device's ID
- *
- * Example:
- *
- * { "id": "netdev1" }
- */
 int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
diff --git a/qemu-char.c b/qemu-char.c
index ac65a1c..faaf624 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2528,22 +2528,6 @@ void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
     qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
 }
 
-/**
- * qemu_chr_info(): Character devices information
- *
- * Each device is represented by a QDict. The returned QObject is a QList
- * of all devices.
- *
- * The QDict contains the following:
- *
- * - "label": device's label
- * - "filename": device's file
- *
- * Example:
- *
- * [ { "label": "monitor", "filename", "stdio" },
- *   { "label": "serial0", "filename": "vc" } ]
- */
 void qemu_chr_info(Monitor *mon, QObject **ret_data)
 {
     QList *chr_list;
diff --git a/vnc.c b/vnc.c
index 30db8b1..ed0e096 100644
--- a/vnc.c
+++ b/vnc.c
@@ -323,35 +323,6 @@ void do_info_vnc_print(Monitor *mon, const QObject *data)
     }
 }
 
-/**
- * do_info_vnc(): Show VNC server information
- *
- * Return a QDict with server information. Connected clients are returned
- * as a QList of QDicts.
- *
- * The main QDict contains the following:
- *
- * - "enabled": true or false
- * - "host": server's IP address
- * - "family": address family ("ipv4" or "ipv6")
- * - "service": server's port number
- * - "auth": authentication method
- * - "clients": a QList of all connected clients
- *
- * Clients are described by a QDict, with the following information:
- *
- * - "host": client's IP address
- * - "family": address family ("ipv4" or "ipv6")
- * - "service": client's port number
- * - "x509_dname": TLS dname (optional)
- * - "sasl_username": SASL username (optional)
- *
- * Example:
- *
- * { "enabled": true, "host": "0.0.0.0", "service": "50402", "auth": "vnc",
- *   "family": "ipv4",
- *   "clients": [{ "host": "127.0.0.1", "service": "50401", "family": "ipv4" }]}
- */
 void do_info_vnc(Monitor *mon, QObject **ret_data)
 {
     if (vnc_display == NULL || vnc_display->display == NULL) {
commit b40292e7115da8814da3d8acd33267202d27d678
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon May 31 14:43:31 2010 -0300

    QMP: Introduce commands documentation
    
    One of the most important missing feature in QMP today is its
    supported commands documentation.
    
    The plan is to make it part of self-description support, however
    self-description is a big task we have been postponing for a
    long time now and still don't know when it's going to be done.
    
    In order not to compromise QMP adoption and make users' life easier,
    this commit adds a simple text documentation which fully describes
    all QMP supported commands.
    
    This is not ideal for a number of reasons (harder to maintain,
    text-only, etc) but does improve the current situation. To avoid at
    least divering from the user monitor help and texi snippets, QMP bits
    are also maintained inside qemu-monitor.hx, and hxtool is extended to
    generate a single text file from them.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 8fa593b..cc5fc45 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
 LIBS+=-lz $(LIBS_TOOLS)
 
 ifdef BUILD_DOCS
-DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
 else
 DOCS=
 endif
@@ -263,6 +263,9 @@ qemu-options.texi: $(SRC_PATH)/qemu-options.hx
 qemu-monitor.texi: $(SRC_PATH)/qemu-monitor.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@,"  GEN   $@")
 
+QMP/qmp-commands.txt: $(SRC_PATH)/qemu-monitor.hx
+	$(call quiet-command,sh $(SRC_PATH)/hxtool -q < $< > $@,"  GEN   $@")
+
 qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@,"  GEN   $@")
 
diff --git a/QMP/README b/QMP/README
index 9334c25..35a80c7 100644
--- a/QMP/README
+++ b/QMP/README
@@ -15,8 +15,9 @@ QMP is JSON[1] based and has the following features:
 
 For more information, please, refer to the following files:
 
-o qmp-spec.txt    QEMU Monitor Protocol current specification
-o qmp-events.txt  List of available asynchronous events
+o qmp-spec.txt      QEMU Monitor Protocol current specification
+o qmp-commands.txt  QMP supported commands
+o qmp-events.txt    List of available asynchronous events
 
 There are also two simple Python scripts available:
 
diff --git a/configure b/configure
index 3cd2c5f..653c8d2 100755
--- a/configure
+++ b/configure
@@ -2817,3 +2817,7 @@ ln -s $source_path/Makefile.user $d/Makefile
 if test "$static" = "no" -a "$user_pie" = "yes" ; then
   echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
 fi
+
+if test "$docs" = "yes" ; then
+  mkdir -p QMP
+fi
diff --git a/hxtool b/hxtool
index 8f65532..d499dc0 100644
--- a/hxtool
+++ b/hxtool
@@ -7,7 +7,7 @@ hxtoh()
         case $str in
             HXCOMM*)
             ;;
-            STEXI*|ETEXI*) flag=$(($flag^1))
+            STEXI*|ETEXI*|SQMP*|EQMP*) flag=$(($flag^1))
             ;;
             *)
             test $flag -eq 1 && printf "%s\n" "$str"
@@ -38,6 +38,12 @@ hxtotexi()
             fi
             flag=0
             ;;
+            SQMP*|EQMP*)
+            if test $flag -eq 1 ; then
+                echo "line $line: syntax error: expected ETEXI, found $str" >&2
+                exit 1
+            fi
+            ;;
             DEFHEADING*)
             echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
             ;;
@@ -49,9 +55,45 @@ hxtotexi()
     done
 }
 
+hxtoqmp()
+{
+    IFS=
+    flag=0
+    while read -r str; do
+        case "$str" in
+            HXCOMM*)
+            ;;
+            SQMP*)
+            if test $flag -eq 1 ; then
+                echo "line $line: syntax error: expected EQMP, found $str" >&2
+                exit 1
+            fi
+            flag=1
+            ;;
+            EQMP*)
+            if test $flag -ne 1 ; then
+                echo "line $line: syntax error: expected SQMP, found $str" >&2
+                exit 1
+            fi
+            flag=0
+            ;;
+            STEXI*|ETEXI*)
+            if test $flag -eq 1 ; then
+                echo "line $line: syntax error: expected EQMP, found $str" >&2
+                exit 1
+            fi
+            ;;
+            *)
+            test $flag -eq 1 && echo "$str"
+            ;;
+        esac
+    done
+}
+
 case "$1" in
 "-h") hxtoh ;;
 "-t") hxtotexi ;;
+"-q") hxtoqmp ;;
 *) exit 1 ;;
 esac
 
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index b8c765b..f6a94f2 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -1,10 +1,48 @@
 HXCOMM Use DEFHEADING() to define headings in both help text and texi
 HXCOMM Text between STEXI and ETEXI are copied to texi version and
 HXCOMM discarded from C version
+HXCOMM Text between SQMP and EQMP is copied to the QMP documention file and
+HXCOMM does not show up in the other formats.
 HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
 HXCOMM monitor commands
 HXCOMM HXCOMM can be used for comments, discarded from both texi and C
 
+SQMP
+                        QMP Supported Commands
+                        ----------------------
+
+This document describes all commands currently supported by QMP.
+
+Most of the time their usage is exactly the same as in the user Monitor, this
+means that any other document which also describe commands (the manpage,
+QEMU's manual, etc) can and should be consulted.
+
+QMP has two types of commands: regular and query commands. Regular commands
+usually change the Virtual Machine's state someway, while query commands just
+return information. The sections below are divided accordingly.
+
+It's important to observe that all communication examples are formatted in
+a reader-friendly way, so that they're easier to understand. However, in real
+protocol usage, they're emitted as a single line.
+
+Also, the following notation is used to denote data flow:
+
+-> data issued by the Client
+<- Server data response
+
+Please, refer to the QMP specification (QMP/qmp-spec.txt) for detailed
+information on the Server command and response formats.
+
+NOTE: This document is temporary and will be replaced soon.
+
+1. Regular Commands
+===================
+
+Server's responses in the examples below are always a success response, please
+refer to the QMP specification for more details on error responses.
+
+EQMP
+
 STEXI
 @table @option
 ETEXI
@@ -51,6 +89,20 @@ STEXI
 @findex quit
 Quit the emulator.
 ETEXI
+SQMP
+quit
+----
+
+Quit the emulator.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "quit" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "eject",
@@ -66,6 +118,25 @@ STEXI
 @findex eject
 Eject a removable medium (use -f to force it).
 ETEXI
+SQMP
+eject
+-----
+
+Eject a removable medium.
+
+Arguments: 
+
+- force: force ejection (json-bool, optional)
+- device: device name (json-string)
+
+Example:
+
+-> { "execute": "eject", "arguments": { "device": "ide1-cd0" } }
+<- { "return": {} }
+
+Note: The "force" argument defaults to false.
+
+EQMP
 
     {
         .name       = "change",
@@ -113,6 +184,35 @@ Password: ********
 
 @end table
 ETEXI
+SQMP
+change
+------
+
+Change a removable medium or VNC configuration.
+
+Arguments:
+
+- "device": device name (json-string)
+- "target": filename or item (json-string)
+- "arg": additional argument (json-string, optional)
+
+Examples:
+
+1. Change a removable medium
+
+-> { "execute": "change",
+             "arguments": { "device": "ide1-cd0",
+                            "target": "/srv/images/Fedora-12-x86_64-DVD.iso" } }
+<- { "return": {} }
+
+2. Change VNC password
+
+-> { "execute": "change",
+             "arguments": { "device": "vnc", "target": "password",
+                            "arg": "foobar1" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "screendump",
@@ -128,6 +228,22 @@ STEXI
 @findex screendump
 Save screen into PPM image @var{filename}.
 ETEXI
+SQMP
+screendump
+----------
+
+Save screen into PPM image.
+
+Arguments:
+
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "screendump", "arguments": { "filename": "/tmp/image" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "logfile",
@@ -232,6 +348,20 @@ STEXI
 @findex stop
 Stop emulation.
 ETEXI
+SQMP
+stop
+----
+
+Stop the emulator.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "stop" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "c|cont",
@@ -247,6 +377,20 @@ STEXI
 @findex cont
 Resume emulation.
 ETEXI
+SQMP
+cont
+----
+
+Resume emulation.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "cont" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "gdbserver",
@@ -421,6 +565,20 @@ STEXI
 
 Reset the system.
 ETEXI
+SQMP
+system_reset
+------------
+
+Reset the system.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "system_reset" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "system_powerdown",
@@ -437,6 +595,20 @@ STEXI
 
 Power down the system (if supported).
 ETEXI
+SQMP
+system_powerdown
+----------------
+
+Send system power down event.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "system_powerdown" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "sum",
@@ -501,6 +673,33 @@ STEXI
 
 Add device.
 ETEXI
+SQMP
+device_add
+----------
+
+Add a device.
+
+Arguments:
+
+- "driver": the name of the new device's driver (json-string)
+- "bus": the device's parent bus (device tree path, json-string, optional)
+- "id": the device's ID, must be unique (json-string)
+- device properties
+
+Example:
+
+-> { "execute": "device_add", "arguments": { "driver": "e1000", "id": "net1" } }
+<- { "return": {} }
+
+Notes:
+
+(1) For detailed information about this command, please refer to the
+    'docs/qdev-device-use.txt' file.
+
+(2) It's possible to list device properties by running QEMU with the
+    "-device DEVICE,\?" command-line argument, where DEVICE is the device's name
+
+EQMP
 
     {
         .name       = "device_del",
@@ -517,6 +716,22 @@ STEXI
 
 Remove device @var{id}.
 ETEXI
+SQMP
+device_del
+----------
+
+Remove a device.
+
+Arguments:
+
+- "id": the device's ID (json-string)
+
+Example:
+
+-> { "execute": "device_del", "arguments": { "id": "net1" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "cpu",
@@ -532,6 +747,24 @@ STEXI
 @findex cpu
 Set the default CPU.
 ETEXI
+SQMP
+cpu
+---
+
+Set the default CPU.
+
+Arguments:
+
+- "index": the CPU's index (json-int)
+
+Example:
+
+-> { "execute": "cpu", "arguments": { "index": 0 } }
+<- { "return": {} }
+
+Note: CPUs' indexes are obtained with the 'query-cpus' command.
+
+EQMP
 
     {
         .name       = "mouse_move",
@@ -635,6 +868,29 @@ STEXI
 @findex memsave
 save to disk virtual memory dump starting at @var{addr} of size @var{size}.
 ETEXI
+SQMP
+memsave
+-------
+
+Save to disk virtual memory dump starting at 'val' of size 'size'.
+
+Arguments:
+
+- "val": the starting address (json-int)
+- "size": the memory size, in bytes (json-int)
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "memsave",
+             "arguments": { "val": 10,
+                            "size": 100,
+                            "filename": "/tmp/virtual-mem-dump" } }
+<- { "return": {} }
+
+Note: Depends on the current CPU.
+
+EQMP
 
     {
         .name       = "pmemsave",
@@ -650,6 +906,27 @@ STEXI
 @findex pmemsave
 save to disk physical memory dump starting at @var{addr} of size @var{size}.
 ETEXI
+SQMP
+pmemsave
+--------
+
+Save to disk physical memory dump starting at 'val' of size 'size'.
+
+Arguments:
+
+- "val": the starting address (json-int)
+- "size": the memory size, in bytes (json-int)
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "pmemsave",
+             "arguments": { "val": 10,
+                            "size": 100,
+                            "filename": "/tmp/physical-mem-dump" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "boot_set",
@@ -706,6 +983,32 @@ Migrate to @var{uri} (using -d to not wait for completion).
 	-b for migration with full copy of disk
 	-i for migration with incremental copy of disk (base image is shared)
 ETEXI
+SQMP
+migrate
+-------
+
+Migrate to URI.
+
+Arguments:
+
+- "blk": block migration, full disk copy (json-bool, optional)
+- "inc": incremental disk copy (json-bool, optional)
+- "uri": Destination URI (json-string)
+
+Example:
+
+-> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } }
+<- { "return": {} }
+
+Notes:
+
+(1) The 'query-migrate' command should be used to check migration's progress
+    and final result (this information is provided by the 'status' member)
+(2) All boolean arguments default to false
+(3) The user Monitor's "detach" argument is invalid in QMP and should not
+    be used
+
+EQMP
 
     {
         .name       = "migrate_cancel",
@@ -721,6 +1024,20 @@ STEXI
 @findex migrate_cancel
 Cancel the current VM migration.
 ETEXI
+SQMP
+migrate_cancel
+--------------
+
+Cancel the current migration.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "migrate_cancel" }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "migrate_set_speed",
@@ -736,6 +1053,22 @@ STEXI
 @findex migrate_set_speed
 Set maximum speed to @var{value} (in bytes) for migrations.
 ETEXI
+SQMP
+migrate_set_speed
+-----------------
+
+Set maximum speed for migrations.
+
+Arguments:
+
+- "value": maximum speed, in bytes per second (json-number)
+
+Example:
+
+-> { "execute": "migrate_set_speed", "arguments": { "value": 1024 } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "migrate_set_downtime",
@@ -751,6 +1084,22 @@ STEXI
 @findex migrate_set_downtime
 Set maximum tolerated downtime (in seconds) for migration.
 ETEXI
+SQMP
+migrate_set_downtime
+--------------------
+
+Set maximum tolerated downtime (in seconds) for migrations.
+
+Arguments:
+
+- "value": maximum downtime (json-number)
+
+Example:
+
+-> { "execute": "migrate_set_downtime", "arguments": { "value": 0.1 } }
+<- { "return": {} }
+
+EQMP
 
 #if defined(TARGET_I386)
     {
@@ -846,6 +1195,28 @@ STEXI
 @findex netdev_add
 Add host network device.
 ETEXI
+SQMP
+netdev_add
+----------
+
+Add host network device.
+
+Arguments:
+
+- "type": the device type, "tap", "user", ... (json-string)
+- "id": the device's ID, must be unique (json-string)
+- device options
+
+Example:
+
+-> { "execute": "netdev_add", "arguments": { "type": "user", "id": "netdev1" } }
+<- { "return": {} }
+
+Note: The supported device options are the same ones supported by the '-net'
+      command-line argument, which are listed in the '-help' output or QEMU's
+      manual
+
+EQMP
 
     {
         .name       = "netdev_del",
@@ -861,6 +1232,22 @@ STEXI
 @findex netdev_del
 Remove host network device.
 ETEXI
+SQMP
+netdev_del
+----------
+
+Remove host network device.
+
+Arguments:
+
+- "id": the device's ID, must be unique (json-string)
+
+Example:
+
+-> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
+<- { "return": {} }
+
+EQMP
 
 #ifdef CONFIG_SLIRP
     {
@@ -908,6 +1295,22 @@ STEXI
 @findex balloon
 Request VM to change its memory allocation to @var{value} (in MB).
 ETEXI
+SQMP
+balloon
+-------
+
+Request VM to change its memory allocation (in bytes).
+
+Arguments:
+
+- "value": New memory allocation (json-int)
+
+Example:
+
+-> { "execute": "balloon", "arguments": { "value": 536870912 } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "set_link",
@@ -923,6 +1326,23 @@ STEXI
 @findex set_link
 Switch link @var{name} on (i.e. up) or off (i.e. down).
 ETEXI
+SQMP
+set_link
+--------
+
+Change the link status of a network adapter.
+
+Arguments:
+
+- "name": network device name (json-string)
+- "up": status is up (json-bool)
+
+Example:
+
+-> { "execute": "set_link", "arguments": { "name": "e1000.0", "up": false } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "watchdog_action",
@@ -1052,6 +1472,22 @@ If a file descriptor is passed alongside this command using the SCM_RIGHTS
 mechanism on unix sockets, it is stored using the name @var{fdname} for
 later use by other monitor commands.
 ETEXI
+SQMP
+getfd
+-----
+
+Receive a file descriptor via SCM rights and assign it a name.
+
+Arguments:
+
+- "fdname": file descriptor name (json-string)
+
+Example:
+
+-> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "closefd",
@@ -1069,6 +1505,22 @@ Close the file descriptor previously assigned to @var{fdname} using the
 @code{getfd} command. This is only needed if the file descriptor was never
 used by another monitor command.
 ETEXI
+SQMP
+closefd
+-------
+
+Close a file descriptor previously passed via SCM rights.
+
+Arguments:
+
+- "fdname": file descriptor name (json-string)
+
+Example:
+
+-> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "block_passwd",
@@ -1084,6 +1536,24 @@ STEXI
 @findex block_passwd
 Set the encrypted device @var{device} password to @var{password}
 ETEXI
+SQMP
+block_passwd
+------------
+
+Set the password of encrypted block devices.
+
+Arguments:
+
+- "device": device name (json-string)
+- "password": password (json-string)
+
+Example:
+
+-> { "execute": "block_passwd", "arguments": { "device": "ide0-hd0",
+                                               "password": "12345" } }
+<- { "return": {} }
+
+EQMP
 
     {
         .name       = "qmp_capabilities",
@@ -1099,11 +1569,34 @@ STEXI
 @findex qmp_capabilities
 Enable the specified QMP capabilities
 ETEXI
+SQMP
+qmp_capabilities
+----------------
+
+Enable QMP capabilities.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "qmp_capabilities" }
+<- { "return": {} }
+
+Note: This command must be issued before issuing any other command.
+
+EQMP
 
 
 HXCOMM Keep the 'info' command at the end!
 HXCOMM This is required for the QMP documentation layout.
 
+SQMP
+
+2. Query Commands
+=================
+
+EQMP
+
     {
         .name       = "info",
         .args_type  = "item:s?",
@@ -1121,40 +1614,588 @@ Show various information about the system state.
 @table @option
 @item info version
 show the version of QEMU
+ETEXI
+SQMP
+query-version
+-------------
+
+Show QEMU version.
+
+Return a json-object with the following information:
+
+- "qemu": QEMU's version (json-string)
+- "package": package's version (json-string)
+
+Example:
+
+-> { "execute": "query-version" }
+<- { "return": { "qemu": "0.11.50", "package": "" } }
+
+EQMP
+
+STEXI
 @item info commands
 list QMP available commands
+ETEXI
+SQMP
+query-commands
+--------------
+
+List QMP available commands.
+
+Each command is represented by a json-object, the returned value is a json-array
+of all commands.
+
+Each json-object contain:
+
+- "name": command's name (json-string)
+
+Example:
+
+-> { "execute": "query-commands" }
+<- {
+      "return":[
+         {
+            "name":"query-balloon"
+         },
+         {
+            "name":"system_powerdown"
+         }
+      ]
+   }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+STEXI
 @item info network
 show the various VLANs and the associated devices
+ETEXI
+
+STEXI
 @item info chardev
 show the character devices
+ETEXI
+SQMP
+query-chardev
+-------------
+
+Each device is represented by a json-object. The returned value is a json-array
+of all devices.
+
+Each json-object contain the following:
+
+- "label": device's label (json-string)
+- "filename": device's file (json-string)
+
+Example:
+
+-> { "execute": "query-chardev" }
+<- {
+      "return":[
+         {
+            "label":"monitor",
+            "filename":"stdio"
+         },
+         {
+            "label":"serial0",
+            "filename":"vc"
+         }
+      ]
+   }
+
+EQMP
+
+STEXI
 @item info block
 show the block devices
+ETEXI
+SQMP
+query-block
+-----------
+
+Show the block devices.
+
+Each block device information is stored in a json-object and the returned value
+is a json-array of all devices.
+
+Each json-object contain the following:
+
+- "device": device name (json-string)
+- "type": device type (json-string)
+         - Possible values: "hd", "cdrom", "floppy", "unknown"
+- "removable": true if the device is removable, false otherwise (json-bool)
+- "locked": true if the device is locked, false otherwise (json-bool)
+- "inserted": only present if the device is inserted, it is a json-object
+   containing the following:
+         - "file": device file name (json-string)
+         - "ro": true if read-only, false otherwise (json-bool)
+         - "drv": driver format name (json-string)
+             - Possible values: "blkdebug", "bochs", "cloop", "cow", "dmg",
+                                "file", "file", "ftp", "ftps", "host_cdrom",
+                                "host_device", "host_floppy", "http", "https",
+                                "nbd", "parallels", "qcow", "qcow2", "raw",
+                                "tftp", "vdi", "vmdk", "vpc", "vvfat"
+         - "backing_file": backing file name (json-string, optional)
+         - "encrypted": true if encrypted, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-block" }
+<- {
+      "return":[
+         {
+            "device":"ide0-hd0",
+            "locked":false,
+            "removable":false,
+            "inserted":{
+               "ro":false,
+               "drv":"qcow2",
+               "encrypted":false,
+               "file":"disks/test.img"
+            },
+            "type":"hd"
+         },
+         {
+            "device":"ide1-cd0",
+            "locked":false,
+            "removable":true,
+            "type":"cdrom"
+         },
+         {
+            "device":"floppy0",
+            "locked":false,
+            "removable":true,
+            "type": "floppy"
+         },
+         {
+            "device":"sd0",
+            "locked":false,
+            "removable":true,
+            "type":"floppy"
+         }
+      ]
+   }
+
+EQMP
+
+STEXI
 @item info blockstats
 show block device statistics
+ETEXI
+SQMP
+query-blockstats
+----------------
+
+Show block device statistics.
+
+Each device statistic information is stored in a json-object and the returned
+value is a json-array of all devices.
+
+Each json-object contain the following:
+
+- "device": device name (json-string)
+- "stats": A json-object with the statistics information, it contains:
+    - "rd_bytes": bytes read (json-int)
+    - "wr_bytes": bytes written (json-int)
+    - "rd_operations": read operations (json-int)
+    - "wr_operations": write operations (json-int)
+    - "wr_highest_offset": Highest offset of a sector written since the
+                           BlockDriverState has been opened (json-int)
+- "parent": Contains recursively the statistics of the underlying
+            protocol (e.g. the host file for a qcow2 image). If there is
+            no underlying protocol, this field is omitted
+            (json-object, optional)
+
+Example:
+
+-> { "execute": "query-blockstats" }
+<- {
+      "return":[
+         {
+            "device":"ide0-hd0",
+            "parent":{
+               "stats":{
+                  "wr_highest_offset":3686448128,
+                  "wr_bytes":9786368,
+                  "wr_operations":751,
+                  "rd_bytes":122567168,
+                  "rd_operations":36772
+               }
+            },
+            "stats":{
+               "wr_highest_offset":2821110784,
+               "wr_bytes":9786368,
+               "wr_operations":692,
+               "rd_bytes":122739200,
+               "rd_operations":36604
+            }
+         },
+         {
+            "device":"ide1-cd0",
+            "stats":{
+               "wr_highest_offset":0,
+               "wr_bytes":0,
+               "wr_operations":0,
+               "rd_bytes":0,
+               "rd_operations":0
+            }
+         },
+         {
+            "device":"floppy0",
+            "stats":{
+               "wr_highest_offset":0,
+               "wr_bytes":0,
+               "wr_operations":0,
+               "rd_bytes":0,
+               "rd_operations":0
+            }
+         },
+         {
+            "device":"sd0",
+            "stats":{
+               "wr_highest_offset":0,
+               "wr_bytes":0,
+               "wr_operations":0,
+               "rd_bytes":0,
+               "rd_operations":0
+            }
+         }
+      ]
+   }
+
+EQMP
+
+STEXI
 @item info registers
 show the cpu registers
 @item info cpus
 show infos for each CPU
+ETEXI
+SQMP
+query-cpus
+----------
+
+Show CPU information.
+
+Return a json-array. Each CPU is represented by a json-object, which contains:
+
+- "CPU": CPU index (json-int)
+- "current": true if this is the current CPU, false otherwise (json-bool)
+- "halted": true if the cpu is halted, false otherwise (json-bool)
+- Current program counter. The key's name depends on the architecture:
+     "pc": i386/x86_64 (json-int)
+     "nip": PPC (json-int)
+     "pc" and "npc": sparc (json-int)
+     "PC": mips (json-int)
+
+Example:
+
+-> { "execute": "query-cpus" }
+<- {
+      "return":[
+         {
+            "CPU":0,
+            "current":true,
+            "halted":false,
+            "pc":3227107138
+         },
+         {
+            "CPU":1,
+            "current":false,
+            "halted":true,
+            "pc":7108165
+         }
+      ]
+   }
+
+EQMP
+
+STEXI
 @item info history
 show the command line history
 @item info irq
 show the interrupts statistics (if available)
 @item info pic
 show i8259 (PIC) state
+ETEXI
+
+STEXI
 @item info pci
 show emulated PCI device info
+ETEXI
+SQMP
+query-pci
+---------
+
+PCI buses and devices information.
+
+The returned value is a json-array of all buses. Each bus is represented by
+a json-object, which has a key with a json-array of all PCI devices attached
+to it. Each device is represented by a json-object.
+
+The bus json-object contains the following:
+
+- "bus": bus number (json-int)
+- "devices": a json-array of json-objects, each json-object represents a
+             PCI device
+
+The PCI device json-object contains the following:
+
+- "bus": identical to the parent's bus number (json-int)
+- "slot": slot number (json-int)
+- "function": function number (json-int)
+- "class_info": a json-object containing:
+     - "desc": device class description (json-string, optional)
+     - "class": device class number (json-int)
+- "id": a json-object containing:
+     - "device": device ID (json-int)
+     - "vendor": vendor ID (json-int)
+- "irq": device's IRQ if assigned (json-int, optional)
+- "qdev_id": qdev id string (json-string)
+- "pci_bridge": It's a json-object, only present if this device is a
+                PCI bridge, contains:
+     - "bus": bus number (json-int)
+     - "secondary": secondary bus number (json-int)
+     - "subordinate": subordinate bus number (json-int)
+     - "io_range": I/O memory range information, a json-object with the
+                   following members:
+                 - "base": base address, in bytes (json-int)
+                 - "limit": limit address, in bytes (json-int)
+     - "memory_range": memory range information, a json-object with the
+                       following members:
+                 - "base": base address, in bytes (json-int)
+                 - "limit": limit address, in bytes (json-int)
+     - "prefetchable_range": Prefetchable memory range information, a
+                             json-object with the following members:
+                 - "base": base address, in bytes (json-int)
+                 - "limit": limit address, in bytes (json-int)
+     - "devices": a json-array of PCI devices if there's any attached, each
+                  each element is represented by a json-object, which contains
+                  the same members of the 'PCI device json-object' described
+                  above (optional)
+- "regions": a json-array of json-objects, each json-object represents a
+             memory region of this device
+
+The memory range json-object contains the following:
+
+- "base": base memory address (json-int)
+- "limit": limit value (json-int)
+
+The region json-object can be an I/O region or a memory region, an I/O region
+json-object contains the following:
+
+- "type": "io" (json-string, fixed)
+- "bar": BAR number (json-int)
+- "address": memory address (json-int)
+- "size": memory size (json-int)
+
+A memory region json-object contains the following:
+
+- "type": "memory" (json-string, fixed)
+- "bar": BAR number (json-int)
+- "address": memory address (json-int)
+- "size": memory size (json-int)
+- "mem_type_64": true or false (json-bool)
+- "prefetch": true or false (json-bool)
+
+Example:
+
+-> { "execute": "query-pci" }
+<- {
+      "return":[
+         {
+            "bus":0,
+            "devices":[
+               {
+                  "bus":0,
+                  "qdev_id":"",
+                  "slot":0,
+                  "class_info":{
+                     "class":1536,
+                     "desc":"Host bridge"
+                  },
+                  "id":{
+                     "device":32902,
+                     "vendor":4663
+                  },
+                  "function":0,
+                  "regions":[
+   
+                  ]
+               },
+               {
+                  "bus":0,
+                  "qdev_id":"",
+                  "slot":1,
+                  "class_info":{
+                     "class":1537,
+                     "desc":"ISA bridge"
+                  },
+                  "id":{
+                     "device":32902,
+                     "vendor":28672
+                  },
+                  "function":0,
+                  "regions":[
+   
+                  ]
+               },
+               {
+                  "bus":0,
+                  "qdev_id":"",
+                  "slot":1,
+                  "class_info":{
+                     "class":257,
+                     "desc":"IDE controller"
+                  },
+                  "id":{
+                     "device":32902,
+                     "vendor":28688
+                  },
+                  "function":1,
+                  "regions":[
+                     {
+                        "bar":4,
+                        "size":16,
+                        "address":49152,
+                        "type":"io"
+                     }
+                  ]
+               },
+               {
+                  "bus":0,
+                  "qdev_id":"",
+                  "slot":2,
+                  "class_info":{
+                     "class":768,
+                     "desc":"VGA controller"
+                  },
+                  "id":{
+                     "device":4115,
+                     "vendor":184
+                  },
+                  "function":0,
+                  "regions":[
+                     {
+                        "prefetch":true,
+                        "mem_type_64":false,
+                        "bar":0,
+                        "size":33554432,
+                        "address":4026531840,
+                        "type":"memory"
+                     },
+                     {
+                        "prefetch":false,
+                        "mem_type_64":false,
+                        "bar":1,
+                        "size":4096,
+                        "address":4060086272,
+                        "type":"memory"
+                     },
+                     {
+                        "prefetch":false,
+                        "mem_type_64":false,
+                        "bar":6,
+                        "size":65536,
+                        "address":-1,
+                        "type":"memory"
+                     }
+                  ]
+               },
+               {
+                  "bus":0,
+                  "qdev_id":"",
+                  "irq":11,
+                  "slot":4,
+                  "class_info":{
+                     "class":1280,
+                     "desc":"RAM controller"
+                  },
+                  "id":{
+                     "device":6900,
+                     "vendor":4098
+                  },
+                  "function":0,
+                  "regions":[
+                     {
+                        "bar":0,
+                        "size":32,
+                        "address":49280,
+                        "type":"io"
+                     }
+                  ]
+               }
+            ]
+         }
+      ]
+   }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+STEXI
 @item info tlb
 show virtual to physical memory mappings (i386 only)
 @item info mem
 show the active virtual memory mappings (i386 only)
+ETEXI
+
+STEXI
 @item info hpet
 show state of HPET (i386 only)
+ETEXI
+SQMP
+query-hpet
+----------
+
+Show HPET state.
+
+Return a json-object with the following information:
+
+- "enabled": true if hpet if enabled, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-hpet" }
+<- { "return": { "enabled": true } }
+
+EQMP
+
+STEXI
 @item info jit
 show dynamic compiler info
 @item info kvm
 show KVM information
 @item info numa
 show NUMA information
+ETEXI
+
+STEXI
+ at item info kvm
+show KVM information
+ETEXI
+SQMP
+query-kvm
+---------
+
+Show KVM information.
+
+Return a json-object with the following information:
+
+- "enabled": true if KVM support is enabled, false otherwise (json-bool)
+- "present": true if QEMU has KVM support, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-kvm" }
+<- { "return": { "enabled": true, "present": true } }
+
+EQMP
+
+STEXI
 @item info usb
 show USB devices plugged on the virtual USB hub
 @item info usbhost
@@ -1165,26 +2206,307 @@ show profiling information
 show information about active capturing
 @item info snapshots
 show list of VM snapshots
+ETEXI
+
+STEXI
 @item info status
 show the current VM status (running|paused)
+ETEXI
+SQMP
+query-status
+------------
+
+Return a json-object with the following information:
+
+- "running": true if the VM is running, or false if it is paused (json-bool)
+- "singlestep": true if the VM is in single step mode,
+                false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-status" }
+<- { "return": { "running": true, "singlestep": false } }
+
+EQMP
+
+STEXI
 @item info pcmcia
 show guest PCMCIA status
+ETEXI
+
+STEXI
 @item info mice
 show which guest mouse is receiving events
+ETEXI
+SQMP
+query-mice
+----------
+
+Show VM mice information.
+
+Each mouse is represented by a json-object, the returned value is a json-array
+of all mice.
+
+The mouse json-object contains the following:
+
+- "name": mouse's name (json-string)
+- "index": mouse's index (json-int)
+- "current": true if this mouse is receiving events, false otherwise (json-bool)
+- "absolute": true if the mouse generates absolute input events (json-bool)
+
+Example:
+
+-> { "execute": "query-mice" }
+<- {
+      "return":[
+         {
+            "name":"QEMU Microsoft Mouse",
+            "index":0,
+            "current":false,
+            "absolute":false
+         },
+         {
+            "name":"QEMU PS/2 Mouse",
+            "index":1,
+            "current":true,
+            "absolute":true
+         }
+      ]
+   }
+
+EQMP
+
+STEXI
 @item info vnc
 show the vnc server status
+ETEXI
+SQMP
+query-vnc
+---------
+
+Show VNC server information.
+
+Return a json-object with server information. Connected clients are returned
+as a json-array of json-objects.
+
+The main json-object contains the following:
+
+- "enabled": true or false (json-bool)
+- "host": server's IP address (json-string)
+- "family": address family (json-string)
+         - Possible values: "ipv4", "ipv6", "unix", "unknown"
+- "service": server's port number (json-string)
+- "auth": authentication method (json-string)
+         - Possible values: "invalid", "none", "ra2", "ra2ne", "sasl", "tight",
+                            "tls", "ultra", "unknown", "vencrypt", "vencrypt",
+                            "vencrypt+plain", "vencrypt+tls+none",
+                            "vencrypt+tls+plain", "vencrypt+tls+sasl",
+                            "vencrypt+tls+vnc", "vencrypt+x509+none",
+                            "vencrypt+x509+plain", "vencrypt+x509+sasl",
+                            "vencrypt+x509+vnc", "vnc"
+- "clients": a json-array of all connected clients
+
+Clients are described by a json-object, each one contain the following:
+
+- "host": client's IP address (json-string)
+- "family": address family (json-string)
+         - Possible values: "ipv4", "ipv6", "unix", "unknown"
+- "service": client's port number (json-string)
+- "x509_dname": TLS dname (json-string, optional)
+- "sasl_username": SASL username (json-string, optional)
+
+Example:
+
+-> { "execute": "query-vnc" }
+<- {
+      "return":{
+         "enabled":true,
+         "host":"0.0.0.0",
+         "service":"50402",
+         "auth":"vnc",
+         "family":"ipv4",
+         "clients":[
+            {
+               "host":"127.0.0.1",
+               "service":"50401",
+               "family":"ipv4"
+            }
+         ]
+      }
+   }
+
+EQMP
+
+STEXI
 @item info name
 show the current VM name
+ETEXI
+SQMP
+query-name
+----------
+
+Show VM name.
+
+Return a json-object with the following information:
+
+- "name": VM's name (json-string, optional)
+
+Example:
+
+-> { "execute": "query-name" }
+<- { "return": { "name": "qemu-name" } }
+
+EQMP
+
+STEXI
 @item info uuid
 show the current VM UUID
+ETEXI
+SQMP
+query-uuid
+----------
+
+Show VM UUID.
+
+Return a json-object with the following information:
+
+- "UUID": Universally Unique Identifier (json-string)
+
+Example:
+
+-> { "execute": "query-uuid" }
+<- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
+
+EQMP
+
+STEXI
 @item info cpustats
 show CPU statistics
 @item info usernet
 show user network stack connection states
+ETEXI
+
+STEXI
 @item info migrate
 show migration status
+ETEXI
+SQMP
+query-migrate
+-------------
+
+Migration status.
+
+Return a json-object. If migration is active there will be another json-object
+with RAM migration status and if block migration is active another one with
+block migration status.
+
+The main json-object contains the following:
+
+- "status": migration status (json-string)
+     - Possible values: "active", "completed", "failed", "cancelled"
+- "ram": only present if "status" is "active", it is a json-object with the
+  following RAM information (in bytes):
+         - "transferred": amount transferred (json-int)
+         - "remaining": amount remaining (json-int)
+         - "total": total (json-int)
+- "disk": only present if "status" is "active" and it is a block migration,
+  it is a json-object with the following disk information (in bytes):
+         - "transferred": amount transferred (json-int)
+         - "remaining": amount remaining (json-int)
+         - "total": total (json-int)
+
+Examples:
+
+1. Before the first migration
+
+-> { "execute": "query-migrate" }
+<- { "return": {} }
+
+2. Migration is done and has succeeded
+
+-> { "execute": "query-migrate" }
+<- { "return": { "status": "completed" } }
+
+3. Migration is done and has failed
+
+-> { "execute": "query-migrate" }
+<- { "return": { "status": "failed" } }
+
+4. Migration is being performed and is not a block migration:
+
+-> { "execute": "query-migrate" }
+<- {
+      "return":{
+         "status":"active",
+         "ram":{
+            "transferred":123,
+            "remaining":123,
+            "total":246
+         }
+      }
+   }
+
+5. Migration is being performed and is a block migration:
+
+-> { "execute": "query-migrate" }
+<- {
+      "return":{
+         "status":"active",
+         "ram":{
+            "total":1057024,
+            "remaining":1053304,
+            "transferred":3720
+         },
+         "disk":{
+            "total":20971520,
+            "remaining":20880384,
+            "transferred":91136
+         }
+      }
+   }
+
+EQMP
+
+STEXI
 @item info balloon
 show balloon information
+ETEXI
+SQMP
+query-balloon
+-------------
+
+Show balloon information.
+
+Make an asynchronous request for balloon info. When the request completes a
+json-object will be returned containing the following data:
+
+- "actual": current balloon value in bytes (json-int)
+- "mem_swapped_in": Amount of memory swapped in bytes (json-int, optional)
+- "mem_swapped_out": Amount of memory swapped out in bytes (json-int, optional)
+- "major_page_faults": Number of major faults (json-int, optional)
+- "minor_page_faults": Number of minor faults (json-int, optional)
+- "free_mem": Total amount of free and unused memory in
+              bytes (json-int, optional)
+- "total_mem": Total amount of available memory in bytes (json-int, optional)
+
+Example:
+
+-> { "execute": "query-balloon" }
+<- {
+      "return":{
+         "actual":1073741824,
+         "mem_swapped_in":0,
+         "mem_swapped_out":0,
+         "major_page_faults":142,
+         "minor_page_faults":239245,
+         "free_mem":1014185984,
+         "total_mem":1044668416
+      }
+   }
+
+EQMP
+
+STEXI
 @item info qtree
 show device tree
 @item info qdm
commit 33572ece26744889b14b7d72ac81870d076725ac
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Mon May 31 14:43:30 2010 -0300

    monitor: Reorder info documentation
    
    Push the doc fragments for the info command to the end of
    qemu-monitor.hx. This helps to establish a proper layout in the upcoming
    QMP documentation.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f4f88df..b8c765b 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -38,96 +38,6 @@ Commit changes to the disk images (if -snapshot is used) or backing files.
 ETEXI
 
     {
-        .name       = "info",
-        .args_type  = "item:s?",
-        .params     = "[subcommand]",
-        .help       = "show various information about the system state",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_info,
-    },
-
-STEXI
- at item info @var{subcommand}
- at findex info
-Show various information about the system state.
-
- at table @option
- at item info version
-show the version of QEMU
- at item info commands
-list QMP available commands
- at item info network
-show the various VLANs and the associated devices
- at item info chardev
-show the character devices
- at item info block
-show the block devices
- at item info blockstats
-show block device statistics
- at item info registers
-show the cpu registers
- at item info cpus
-show infos for each CPU
- at item info history
-show the command line history
- at item info irq
-show the interrupts statistics (if available)
- at item info pic
-show i8259 (PIC) state
- at item info pci
-show emulated PCI device info
- at item info tlb
-show virtual to physical memory mappings (i386 only)
- at item info mem
-show the active virtual memory mappings (i386 only)
- at item info hpet
-show state of HPET (i386 only)
- at item info jit
-show dynamic compiler info
- at item info kvm
-show KVM information
- at item info numa
-show NUMA information
- at item info usb
-show USB devices plugged on the virtual USB hub
- at item info usbhost
-show all USB host devices
- at item info profile
-show profiling information
- at item info capture
-show information about active capturing
- at item info snapshots
-show list of VM snapshots
- at item info status
-show the current VM status (running|paused)
- at item info pcmcia
-show guest PCMCIA status
- at item info mice
-show which guest mouse is receiving events
- at item info vnc
-show the vnc server status
- at item info name
-show the current VM name
- at item info uuid
-show the current VM UUID
- at item info cpustats
-show CPU statistics
- at item info usernet
-show user network stack connection states
- at item info migrate
-show migration status
- at item info balloon
-show balloon information
- at item info qtree
-show device tree
- at item info qdm
-show qdev device model list
- at item info roms
-show roms
- at end table
-ETEXI
-
-    {
         .name       = "q|quit",
         .args_type  = "",
         .params     = "",
@@ -1190,6 +1100,102 @@ STEXI
 Enable the specified QMP capabilities
 ETEXI
 
+
+HXCOMM Keep the 'info' command at the end!
+HXCOMM This is required for the QMP documentation layout.
+
+    {
+        .name       = "info",
+        .args_type  = "item:s?",
+        .params     = "[subcommand]",
+        .help       = "show various information about the system state",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_info,
+    },
+
+STEXI
+ at item info @var{subcommand}
+ at findex info
+Show various information about the system state.
+
+ at table @option
+ at item info version
+show the version of QEMU
+ at item info commands
+list QMP available commands
+ at item info network
+show the various VLANs and the associated devices
+ at item info chardev
+show the character devices
+ at item info block
+show the block devices
+ at item info blockstats
+show block device statistics
+ at item info registers
+show the cpu registers
+ at item info cpus
+show infos for each CPU
+ at item info history
+show the command line history
+ at item info irq
+show the interrupts statistics (if available)
+ at item info pic
+show i8259 (PIC) state
+ at item info pci
+show emulated PCI device info
+ at item info tlb
+show virtual to physical memory mappings (i386 only)
+ at item info mem
+show the active virtual memory mappings (i386 only)
+ at item info hpet
+show state of HPET (i386 only)
+ at item info jit
+show dynamic compiler info
+ at item info kvm
+show KVM information
+ at item info numa
+show NUMA information
+ at item info usb
+show USB devices plugged on the virtual USB hub
+ at item info usbhost
+show all USB host devices
+ at item info profile
+show profiling information
+ at item info capture
+show information about active capturing
+ at item info snapshots
+show list of VM snapshots
+ at item info status
+show the current VM status (running|paused)
+ at item info pcmcia
+show guest PCMCIA status
+ at item info mice
+show which guest mouse is receiving events
+ at item info vnc
+show the vnc server status
+ at item info name
+show the current VM name
+ at item info uuid
+show the current VM UUID
+ at item info cpustats
+show CPU statistics
+ at item info usernet
+show user network stack connection states
+ at item info migrate
+show migration status
+ at item info balloon
+show balloon information
+ at item info qtree
+show device tree
+ at item info qdm
+show qdev device model list
+ at item info roms
+show roms
+ at end table
+ETEXI
+
+HXCOMM DO NOT add new commands after 'info', move your addition before it!
+
 STEXI
 @end table
 ETEXI
commit 38141097142199a65db142b974c45b3a9c0c809c
Merge: 1d4b638... e075e78...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Jun 1 13:34:20 2010 -0500

    Merge remote branch 'mst/for_anthony' into HEAD

commit 1d4b638ad1fc273a19d93c7d4725fecdd7e5182a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 25 18:25:20 2010 +0200

    vnc: move size-changed check into the vnc_desktop_resize function.
    
    This make sure we send a desktop resize message only in case we actually
    have to, using the new variables which track the clients desktop size.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index 5fc7012..30db8b1 100644
--- a/vnc.c
+++ b/vnc.c
@@ -529,6 +529,10 @@ static void vnc_desktop_resize(VncState *vs)
     if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
         return;
     }
+    if (vs->client_width == ds_get_width(ds) &&
+        vs->client_height == ds_get_height(ds)) {
+        return;
+    }
     vs->client_width = ds_get_width(ds);
     vs->client_height = ds_get_height(ds);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
@@ -541,7 +545,6 @@ static void vnc_desktop_resize(VncState *vs)
 
 static void vnc_dpy_resize(DisplayState *ds)
 {
-    int size_changed;
     VncDisplay *vd = ds->opaque;
     VncState *vs;
 
@@ -559,16 +562,12 @@ static void vnc_dpy_resize(DisplayState *ds)
         vd->guest.ds = qemu_mallocz(sizeof(*vd->guest.ds));
     if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
         console_color_init(ds);
-    size_changed = ds_get_width(ds) != vd->guest.ds->width ||
-                   ds_get_height(ds) != vd->guest.ds->height;
     *(vd->guest.ds) = *(ds->surface);
     memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
         vnc_colordepth(vs);
-        if (size_changed) {
-            vnc_desktop_resize(vs);
-        }
+        vnc_desktop_resize(vs);
         if (vs->vd->cursor) {
             vnc_cursor_define(vs);
         }
commit 847ce6a185f9ccbc089ef24a6c402b8c99113341
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 25 18:25:19 2010 +0200

    vnc: don't send invalid screen updates.
    
    Don't send updates for screen areas which are outside the clients
    desktop.  May happed with vnc clients which don't support the desktop
    resize message.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index c8fe659..5fc7012 100644
--- a/vnc.c
+++ b/vnc.c
@@ -851,6 +851,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
         int y;
         int n_rectangles;
         int saved_offset;
+        int width, height;
         int n;
 
         if (vs->output.offset && !vs->audio_cap && !vs->force_update)
@@ -872,10 +873,13 @@ static int vnc_update_client(VncState *vs, int has_dirty)
         saved_offset = vs->output.offset;
         vnc_write_u16(vs, 0);
 
-        for (y = 0; y < vd->server->height; y++) {
+        width = MIN(vd->server->width, vs->client_width);
+        height = MIN(vd->server->height, vs->client_height);
+
+        for (y = 0; y < height; y++) {
             int x;
             int last_x = -1;
-            for (x = 0; x < vd->server->width / 16; x++) {
+            for (x = 0; x < width / 16; x++) {
                 if (vnc_get_bit(vs->dirty[y], x)) {
                     if (last_x == -1) {
                         last_x = x;
commit 5862d195f90cb63c53b9dc3f54e10f8b9372bcf6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 25 18:25:18 2010 +0200

    vnc: keep track of client desktop size
    
    Add two new variables to keep track of the vnc clients desktop size.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index a3a7840..c8fe659 100644
--- a/vnc.c
+++ b/vnc.c
@@ -529,10 +529,12 @@ static void vnc_desktop_resize(VncState *vs)
     if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
         return;
     }
+    vs->client_width = ds_get_width(ds);
+    vs->client_height = ds_get_height(ds);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1); /* number of rects */
-    vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+    vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
                            VNC_ENCODING_DESKTOPRESIZE);
     vnc_flush(vs);
 }
@@ -1975,8 +1977,10 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     char buf[1024];
     int size;
 
-    vnc_write_u16(vs, ds_get_width(vs->ds));
-    vnc_write_u16(vs, ds_get_height(vs->ds));
+    vs->client_width = ds_get_width(vs->ds);
+    vs->client_height = ds_get_height(vs->ds);
+    vnc_write_u16(vs, vs->client_width);
+    vnc_write_u16(vs, vs->client_height);
 
     pixel_format_message(vs);
 
diff --git a/vnc.h b/vnc.h
index 51595e6..7b64cf7 100644
--- a/vnc.h
+++ b/vnc.h
@@ -134,6 +134,8 @@ struct VncState
     int absolute;
     int last_x;
     int last_y;
+    int client_width;
+    int client_height;
 
     uint32_t vnc_encoding;
 
commit 6356e472512c55a5dc3aaf12ce12a6eb916dd045
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 25 18:25:17 2010 +0200

    vnc: send desktopresize event as reply to set encodings
    
    In case the desktop did resize while the vnc connection setup was still
    in progress the client isn't informed about it.  Send a desktop resize
    event as soon as the client told us it can handle deskop resize via set
    encodings message to make sure the client us up to date.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index 4fb13ba..a3a7840 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1726,6 +1726,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             break;
         }
     }
+    vnc_desktop_resize(vs);
     check_pointer_type_change(&vs->mouse_mode_notifier);
 }
 
commit 621aaeb9991933a367e3964ecfc88a8f96af1f6a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue May 25 18:25:16 2010 +0200

    vnc: factor out vnc_desktop_resize()
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc.c b/vnc.c
index 046bd38..4fb13ba 100644
--- a/vnc.c
+++ b/vnc.c
@@ -522,6 +522,21 @@ void buffer_append(Buffer *buffer, const void *data, size_t len)
     buffer->offset += len;
 }
 
+static void vnc_desktop_resize(VncState *vs)
+{
+    DisplayState *ds = vs->ds;
+
+    if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
+        return;
+    }
+    vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+    vnc_write_u8(vs, 0);
+    vnc_write_u16(vs, 1); /* number of rects */
+    vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+                           VNC_ENCODING_DESKTOPRESIZE);
+    vnc_flush(vs);
+}
+
 static void vnc_dpy_resize(DisplayState *ds)
 {
     int size_changed;
@@ -550,14 +565,7 @@ static void vnc_dpy_resize(DisplayState *ds)
     QTAILQ_FOREACH(vs, &vd->clients, next) {
         vnc_colordepth(vs);
         if (size_changed) {
-            if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
-                vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
-                vnc_write_u8(vs, 0);
-                vnc_write_u16(vs, 1); /* number of rects */
-                vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
-                        VNC_ENCODING_DESKTOPRESIZE);
-                vnc_flush(vs);
-            }
+            vnc_desktop_resize(vs);
         }
         if (vs->vd->cursor) {
             vnc_cursor_define(vs);
commit b627808462de92fd2635de16fa7d10b18d806802
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri May 21 11:59:14 2010 +0200

    Add support for depth 15 to qemu_default_pixelformat()
    
    Makes qemu_default_pixelformat(15) return pixelformat filled for 15 bit
    color depth (16 bpp, 5 bits for red,green,blue each, 1 bit unused).
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index 4c42b28..698bc10 100644
--- a/console.c
+++ b/console.c
@@ -1621,6 +1621,22 @@ PixelFormat qemu_default_pixelformat(int bpp)
     pf.depth = bpp == 32 ? 24 : bpp;
 
     switch (bpp) {
+        case 15:
+            pf.bits_per_pixel = 16;
+            pf.bytes_per_pixel = 2;
+            pf.rmask = 0x00007c00;
+            pf.gmask = 0x000003E0;
+            pf.bmask = 0x0000001F;
+            pf.rmax = 31;
+            pf.gmax = 31;
+            pf.bmax = 31;
+            pf.rshift = 10;
+            pf.gshift = 5;
+            pf.bshift = 0;
+            pf.rbits = 5;
+            pf.gbits = 5;
+            pf.bbits = 5;
+            break;
         case 16:
             pf.rmask = 0x0000F800;
             pf.gmask = 0x000007E0;
commit 26572b8a0e90ee0c77587173a78fa293a1d2beb6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu May 20 15:23:06 2010 +0200

    check for active_console before using it
    
    Other vga_hw_* functions do the same.
    Fixes a segmentation fault.  Trigger: boot with -nodefaults,
    then connect via vnc.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index 7070b1b..4c42b28 100644
--- a/console.c
+++ b/console.c
@@ -167,7 +167,7 @@ void vga_hw_update(void)
 
 void vga_hw_invalidate(void)
 {
-    if (active_console->hw_invalidate)
+    if (active_console && active_console->hw_invalidate)
         active_console->hw_invalidate(active_console->hw);
 }
 
commit 4091da4b7cc251c7d422ccc5707900ed595b1ee0
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu May 20 09:18:52 2010 +0200

    Add dependency of JSON unit tests on config-host.h
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 9deb0f7..8fa593b 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobj
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $@")
 
+check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
+
 check-qint: check-qint.o qint.o qemu-malloc.o
 check-qstring: check-qstring.o qstring.o qemu-malloc.o
 check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o
commit 3fc250b4be58cac2e392d8d01949f9e8471c36f9
Author: Pierre Riteau <Pierre.Riteau at irisa.fr>
Date:   Wed May 12 15:12:44 2010 +0200

    migration: Fix calculation of bytes_transferred
    
    When a page with all identical bytes is transferred, it is counted
    as a full page (TARGET_PAGE_SIZE) although only one byte is actually
    sent. Fix this by changing ram_save_block() to return the number of
    bytes sent instead of a boolean value. This makes bandwidth
    estimation, and consequently downtime estimation, more precise.
    
    Signed-off-by: Pierre Riteau <Pierre.Riteau at irisa.fr>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index cfc03ea..8e849a8 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -108,7 +108,7 @@ static int ram_save_block(QEMUFile *f)
     static ram_addr_t current_addr = 0;
     ram_addr_t saved_addr = current_addr;
     ram_addr_t addr = 0;
-    int found = 0;
+    int bytes_sent = 0;
 
     while (addr < last_ram_offset) {
         if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
@@ -123,19 +123,20 @@ static int ram_save_block(QEMUFile *f)
             if (is_dup_page(p, *p)) {
                 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
                 qemu_put_byte(f, *p);
+                bytes_sent = 1;
             } else {
                 qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
                 qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+                bytes_sent = TARGET_PAGE_SIZE;
             }
 
-            found = 1;
             break;
         }
         addr += TARGET_PAGE_SIZE;
         current_addr = (saved_addr + addr) % last_ram_offset;
     }
 
-    return found;
+    return bytes_sent;
 }
 
 static uint64_t bytes_transferred;
@@ -206,11 +207,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
     bwidth = qemu_get_clock_ns(rt_clock);
 
     while (!qemu_file_rate_limit(f)) {
-        int ret;
+        int bytes_sent;
 
-        ret = ram_save_block(f);
-        bytes_transferred += ret * TARGET_PAGE_SIZE;
-        if (ret == 0) { /* no more blocks */
+        bytes_sent = ram_save_block(f);
+        bytes_transferred += bytes_sent;
+        if (bytes_sent == 0) { /* no more blocks */
             break;
         }
     }
@@ -226,9 +227,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
 
     /* try transferring iterative blocks of memory */
     if (stage == 3) {
+        int bytes_sent;
+
         /* flush all remaining blocks regardless of rate limiting */
-        while (ram_save_block(f) != 0) {
-            bytes_transferred += TARGET_PAGE_SIZE;
+        while ((bytes_sent = ram_save_block(f)) != 0) {
+            bytes_transferred += bytes_sent;
         }
         cpu_physical_memory_set_dirty_tracking(0);
     }
commit a132a679c33ae2f8f6935f92c2a8043015cd917c
Author: Alon Levy <alevy at redhat.com>
Date:   Wed May 19 15:01:38 2010 +0530

    virtio-serial-bus: fix ports_map allocation on init
    
    Fix for too small allocation to ports_map
    
    Signed-off-by: Alon Levy <alevy at redhat.com>
    Signed-off-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 3ce95e8..7f9d28f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -774,7 +774,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
     }
 
     vser->config.max_nr_ports = max_nr_ports;
-    vser->ports_map = qemu_mallocz((max_nr_ports + 31) / 32);
+    vser->ports_map = qemu_mallocz(((max_nr_ports + 31) / 32)
+        * sizeof(vser->ports_map[0]));
     /*
      * Reserve location 0 for a console port for backward compat
      * (old kernel, new qemu)
commit eafaf1e5ab30346d6e9ac676ec6b7a3eca4ccce3
Author: Andre Przywara <andre.przywara at amd.com>
Date:   Fri May 21 09:50:51 2010 +0200

    resent: x86/cpuid: Add kvm32 CPU model
    
    Create a kvm32 CPU model that describes a least common denominator
    for KVM capable guest CPUs. Useful for migration purposes.
    
    Signed-off-by: Andre Przywara <andre.przywara at amd.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 56938e2..7a11215 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -364,6 +364,20 @@ static x86_def_t builtin_x86_defs[] = {
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
     {
+        .name = "kvm32",
+        .level = 5,
+        .family = 15,
+        .model = 6,
+        .stepping = 1,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
+        .ext_features = CPUID_EXT_SSE3,
+        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
+        .ext3_features = 0,
+        .xlevel = 0x80000008,
+        .model_id = "Common 32-bit KVM processor"
+    },
+    {
         .name = "coreduo",
         .level = 10,
         .family = 6,
commit aa7d73fd3db9262f426017a1eeef0d681373db5d
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Wed May 19 09:24:12 2010 +0200

    vnc: tight: add palette encoding
    
    Add palette tight encoding. Palette encoding will try to count the number
    of colors for a given rectangle, and if this number is low enough
    (< 256) it will send the palette + the rectangle with indexed colors.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 2c9dab6..50be44e 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -28,6 +28,8 @@
 
 #include <stdbool.h>
 
+#include "qdict.h"
+#include "qint.h"
 #include "vnc.h"
 #include "vnc-encoding-tight.h"
 
@@ -56,6 +58,285 @@ static const struct {
 };
 
 /*
+ * Code to determine how many different colors used in rectangle.
+ */
+
+static void tight_palette_rgb2buf(uint32_t rgb, int bpp, uint8_t buf[6])
+{
+    memset(buf, 0, 6);
+
+    if (bpp == 32) {
+        buf[0] = ((rgb >> 24) & 0xFF);
+        buf[1] = ((rgb >> 16) & 0xFF);
+        buf[2] = ((rgb >>  8) & 0xFF);
+        buf[3] = ((rgb >>  0) & 0xFF);
+        buf[4] = ((buf[0] & 1) == 0) << 3 | ((buf[1] & 1) == 0) << 2;
+        buf[4]|= ((buf[2] & 1) == 0) << 1 | ((buf[3] & 1) == 0) << 0;
+        buf[0] |= 1;
+        buf[1] |= 1;
+        buf[2] |= 1;
+        buf[3] |= 1;
+    }
+    if (bpp == 16) {
+        buf[0] = ((rgb >> 8) & 0xFF);
+        buf[1] = ((rgb >> 0) & 0xFF);
+        buf[2] = ((buf[0] & 1) == 0) << 1 | ((buf[1] & 1) == 0) << 0;
+        buf[0] |= 1;
+        buf[1] |= 1;
+    }
+}
+
+static uint32_t tight_palette_buf2rgb(int bpp, const uint8_t *buf)
+{
+    uint32_t rgb = 0;
+
+    if (bpp == 32) {
+        rgb |= ((buf[0] & ~1) | !((buf[4] >> 3) & 1)) << 24;
+        rgb |= ((buf[1] & ~1) | !((buf[4] >> 2) & 1)) << 16;
+        rgb |= ((buf[2] & ~1) | !((buf[4] >> 1) & 1)) <<  8;
+        rgb |= ((buf[3] & ~1) | !((buf[4] >> 0) & 1)) <<  0;
+    }
+    if (bpp == 16) {
+        rgb |= ((buf[0] & ~1) | !((buf[2] >> 1) & 1)) << 8;
+        rgb |= ((buf[1] & ~1) | !((buf[2] >> 0) & 1)) << 0;
+    }
+    return rgb;
+}
+
+
+static int tight_palette_insert(QDict *palette, uint32_t rgb, int bpp, int max)
+{
+    uint8_t key[6];
+    int idx = qdict_size(palette);
+    bool present;
+
+    tight_palette_rgb2buf(rgb, bpp, key);
+    present = qdict_haskey(palette, (char *)key);
+    if (idx >= max && !present) {
+        return 0;
+    }
+    if (!present) {
+        qdict_put(palette, (char *)key, qint_from_int(idx));
+    }
+    return qdict_size(palette);
+}
+
+#define DEFINE_FILL_PALETTE_FUNCTION(bpp)                               \
+                                                                        \
+    static int                                                          \
+    tight_fill_palette##bpp(VncState *vs, int x, int y,                 \
+                            int max, size_t count,                      \
+                            uint32_t *bg, uint32_t *fg,                 \
+                            struct QDict **palette) {                   \
+        uint##bpp##_t *data;                                            \
+        uint##bpp##_t c0, c1, ci;                                       \
+        int i, n0, n1;                                                  \
+                                                                        \
+        data = (uint##bpp##_t *)vs->tight.buffer;                       \
+                                                                        \
+        c0 = data[0];                                                   \
+        i = 1;                                                          \
+        while (i < count && data[i] == c0)                              \
+            i++;                                                        \
+        if (i >= count) {                                               \
+            *bg = *fg = c0;                                             \
+            return 1;                                                   \
+        }                                                               \
+                                                                        \
+        if (max < 2) {                                                  \
+            return 0;                                                   \
+        }                                                               \
+                                                                        \
+        n0 = i;                                                         \
+        c1 = data[i];                                                   \
+        n1 = 0;                                                         \
+        for (i++; i < count; i++) {                                     \
+            ci = data[i];                                               \
+            if (ci == c0) {                                             \
+                n0++;                                                   \
+            } else if (ci == c1) {                                      \
+                n1++;                                                   \
+            } else                                                      \
+                break;                                                  \
+        }                                                               \
+        if (i >= count) {                                               \
+            if (n0 > n1) {                                              \
+                *bg = (uint32_t)c0;                                     \
+                *fg = (uint32_t)c1;                                     \
+            } else {                                                    \
+                *bg = (uint32_t)c1;                                     \
+                *fg = (uint32_t)c0;                                     \
+            }                                                           \
+            return 2;                                                   \
+        }                                                               \
+                                                                        \
+        if (max == 2) {                                                 \
+            return 0;                                                   \
+        }                                                               \
+                                                                        \
+        *palette = qdict_new();                                         \
+        tight_palette_insert(*palette, c0, bpp, max);                   \
+        tight_palette_insert(*palette, c1, bpp, max);                   \
+                                                                        \
+        for (i++; i < count; i++) {                                     \
+            if (data[i] == ci) {                                        \
+                continue;                                               \
+            } else {                                                    \
+                if (!tight_palette_insert(*palette, (uint32_t)ci,       \
+                                          bpp, max)) {                  \
+                    return 0;                                           \
+                }                                                       \
+                ci = data[i];                                           \
+            }                                                           \
+        }                                                               \
+                                                                        \
+        return qdict_size(*palette);                                    \
+    }
+
+DEFINE_FILL_PALETTE_FUNCTION(8)
+DEFINE_FILL_PALETTE_FUNCTION(16)
+DEFINE_FILL_PALETTE_FUNCTION(32)
+
+static int tight_fill_palette(VncState *vs, int x, int y,
+                              size_t count, uint32_t *bg, uint32_t *fg,
+                              struct QDict **palette)
+{
+    int max;
+
+    max = count / tight_conf[vs->tight_compression].idx_max_colors_divisor;
+    if (max < 2 &&
+        count >= tight_conf[vs->tight_compression].mono_min_rect_size) {
+        max = 2;
+    }
+    if (max >= 256) {
+        max = 256;
+    }
+
+    switch(vs->clientds.pf.bytes_per_pixel) {
+    case 4:
+        return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette);
+    case 2:
+        return tight_fill_palette16(vs, x, y, max, count, bg, fg, palette);
+    default:
+        max = 2;
+        return tight_fill_palette8(vs, x, y, max, count, bg, fg, palette);
+    }
+    return 0;
+}
+
+/* Callback to dump a palette with qdict_iter
+static void print_palette(const char *key, QObject *obj, void *opaque)
+{
+    uint8_t idx = qint_get_int(qobject_to_qint(obj));
+    uint32_t rgb = tight_palette_buf2rgb(32, (uint8_t *)key);
+
+    fprintf(stderr, "%.2x ", (unsigned char)*key);
+    while (*key++)
+        fprintf(stderr, "%.2x ", (unsigned char)*key);
+
+    fprintf(stderr, ": idx: %x rgb: %x\n", idx, rgb);
+}
+*/
+
+/*
+ * Converting truecolor samples into palette indices.
+ */
+#define DEFINE_IDX_ENCODE_FUNCTION(bpp)                                 \
+                                                                        \
+    static void                                                         \
+    tight_encode_indexed_rect##bpp(uint8_t *buf, int count,             \
+                                   struct QDict *palette) {             \
+        uint##bpp##_t *src;                                             \
+        uint##bpp##_t rgb;                                              \
+        uint8_t key[6];                                                 \
+        int rep = 0;                                                    \
+        uint8_t idx;                                                    \
+                                                                        \
+        src = (uint##bpp##_t *) buf;                                    \
+                                                                        \
+        count -= 1;                                                     \
+        while (count--) {                                               \
+            rgb = *src++;                                               \
+            rep = 0;                                                    \
+            while (count && *src == rgb) {                              \
+                rep++, src++, count--;                                  \
+            }                                                           \
+            tight_palette_rgb2buf(rgb, bpp, key);                       \
+            if (!qdict_haskey(palette, (char *)key)) {                  \
+                /*                                                      \
+                 * Should never happen, but don't break everything      \
+                 * if it does, use the first color instead              \
+                 */                                                     \
+                idx = 0;                                                \
+            } else {                                                    \
+                idx = qdict_get_int(palette, (char *)key);              \
+            }                                                           \
+            while (rep >= 0) {                                          \
+                *buf++ = idx;                                           \
+                rep--;                                                  \
+            }                                                           \
+        }                                                               \
+    }
+
+DEFINE_IDX_ENCODE_FUNCTION(16)
+DEFINE_IDX_ENCODE_FUNCTION(32)
+
+#define DEFINE_MONO_ENCODE_FUNCTION(bpp)                                \
+                                                                        \
+    static void                                                         \
+    tight_encode_mono_rect##bpp(uint8_t *buf, int w, int h,             \
+                                uint##bpp##_t bg, uint##bpp##_t fg) {   \
+        uint##bpp##_t *ptr;                                             \
+        unsigned int value, mask;                                       \
+        int aligned_width;                                              \
+        int x, y, bg_bits;                                              \
+                                                                        \
+        ptr = (uint##bpp##_t *) buf;                                    \
+        aligned_width = w - w % 8;                                      \
+                                                                        \
+        for (y = 0; y < h; y++) {                                       \
+            for (x = 0; x < aligned_width; x += 8) {                    \
+                for (bg_bits = 0; bg_bits < 8; bg_bits++) {             \
+                    if (*ptr++ != bg) {                                 \
+                        break;                                          \
+                    }                                                   \
+                }                                                       \
+                if (bg_bits == 8) {                                     \
+                    *buf++ = 0;                                         \
+                    continue;                                           \
+                }                                                       \
+                mask = 0x80 >> bg_bits;                                 \
+                value = mask;                                           \
+                for (bg_bits++; bg_bits < 8; bg_bits++) {               \
+                    mask >>= 1;                                         \
+                    if (*ptr++ != bg) {                                 \
+                        value |= mask;                                  \
+                    }                                                   \
+                }                                                       \
+                *buf++ = (uint8_t)value;                                \
+            }                                                           \
+                                                                        \
+            mask = 0x80;                                                \
+            value = 0;                                                  \
+            if (x >= w) {                                               \
+                continue;                                               \
+            }                                                           \
+                                                                        \
+            for (; x < w; x++) {                                        \
+                if (*ptr++ != bg) {                                     \
+                    value |= mask;                                      \
+                }                                                       \
+                mask >>= 1;                                             \
+            }                                                           \
+            *buf++ = (uint8_t)value;                                    \
+        }                                                               \
+    }
+
+DEFINE_MONO_ENCODE_FUNCTION(8)
+DEFINE_MONO_ENCODE_FUNCTION(16)
+DEFINE_MONO_ENCODE_FUNCTION(32)
+
+/*
  * Check if a rectangle is all of the same color. If needSameColor is
  * set to non-zero, then also check that its color equals to the
  * *colorPtr value. The result is 1 if the test is successfull, and in
@@ -288,14 +569,12 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
 /*
  * Subencoding implementations.
  */
-static void tight_pack24(VncState *vs, size_t count)
+static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
 {
-    unsigned char *buf;
     uint32_t *buf32;
     uint32_t pix;
     int rshift, gshift, bshift;
 
-    buf = vs->tight.buffer;
     buf32 = (uint32_t *)buf;
 
     if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
@@ -309,7 +588,9 @@ static void tight_pack24(VncState *vs, size_t count)
         bshift = 24 - vs->clientds.pf.bshift;
     }
 
-    vs->tight.offset = count * 3;
+    if (ret) {
+        *ret = count * 3;
+    }
 
     while (count--) {
         pix = *buf32++;
@@ -327,7 +608,7 @@ static int send_full_color_rect(VncState *vs, int w, int h)
     vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
 
     if (vs->tight_pixel24) {
-        tight_pack24(vs, w * h);
+        tight_pack24(vs, vs->tight.buffer, w * h, &vs->tight.offset);
         bytes = 3;
     } else {
         bytes = vs->clientds.pf.bytes_per_pixel;
@@ -347,7 +628,7 @@ static int send_solid_rect(VncState *vs)
     vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
 
     if (vs->tight_pixel24) {
-        tight_pack24(vs, 1);
+        tight_pack24(vs, vs->tight.buffer, 1, &vs->tight.offset);
         bytes = 3;
     } else {
         bytes = vs->clientds.pf.bytes_per_pixel;
@@ -357,6 +638,126 @@ static int send_solid_rect(VncState *vs)
     return 1;
 }
 
+static int send_mono_rect(VncState *vs, int w, int h, uint32_t bg, uint32_t fg)
+{
+    size_t bytes;
+    int stream = 1;
+    int level = tight_conf[vs->tight_compression].mono_zlib_level;
+
+    bytes = ((w + 7) / 8) * h;
+
+    vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
+    vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
+    vnc_write_u8(vs, 1);
+
+    switch(vs->clientds.pf.bytes_per_pixel) {
+    case 4:
+    {
+        uint32_t buf[2] = {bg, fg};
+        size_t ret = sizeof (buf);
+
+        if (vs->tight_pixel24) {
+            tight_pack24(vs, (unsigned char*)buf, 2, &ret);
+        }
+        vnc_write(vs, buf, ret);
+
+        tight_encode_mono_rect32(vs->tight.buffer, w, h, bg, fg);
+        break;
+    }
+    case 2:
+        vnc_write(vs, &bg, 2);
+        vnc_write(vs, &fg, 2);
+        tight_encode_mono_rect16(vs->tight.buffer, w, h, bg, fg);
+        break;
+    default:
+        vnc_write_u8(vs, bg);
+        vnc_write_u8(vs, fg);
+        tight_encode_mono_rect8(vs->tight.buffer, w, h, bg, fg);
+        break;
+    }
+    vs->tight.offset = bytes;
+
+    bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY);
+    return (bytes >= 0);
+}
+
+struct palette_cb_priv {
+    VncState *vs;
+    uint8_t *header;
+};
+
+static void write_palette(const char *key, QObject *obj, void *opaque)
+{
+    struct palette_cb_priv *priv = opaque;
+    VncState *vs = priv->vs;
+    uint32_t bytes = vs->clientds.pf.bytes_per_pixel;
+    uint8_t idx = qint_get_int(qobject_to_qint(obj));
+
+    if (bytes == 4) {
+        uint32_t color = tight_palette_buf2rgb(32, (uint8_t *)key);
+
+        ((uint32_t*)priv->header)[idx] = color;
+    } else {
+        uint16_t color = tight_palette_buf2rgb(16, (uint8_t *)key);
+
+        ((uint16_t*)priv->header)[idx] = color;
+    }
+}
+
+static int send_palette_rect(VncState *vs, int w, int h, struct QDict *palette)
+{
+    int stream = 2;
+    int level = tight_conf[vs->tight_compression].idx_zlib_level;
+    int colors;
+    size_t bytes;
+
+    colors = qdict_size(palette);
+
+    vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
+    vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
+    vnc_write_u8(vs, colors - 1);
+
+    switch(vs->clientds.pf.bytes_per_pixel) {
+    case 4:
+    {
+        size_t old_offset, offset;
+        uint32_t header[qdict_size(palette)];
+        struct palette_cb_priv priv = { vs, (uint8_t *)header };
+
+        old_offset = vs->output.offset;
+        qdict_iter(palette, write_palette, &priv);
+        vnc_write(vs, header, sizeof(header));
+
+        if (vs->tight_pixel24) {
+            tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset);
+            vs->output.offset = old_offset + offset;
+        }
+
+        tight_encode_indexed_rect32(vs->tight.buffer, w * h, palette);
+        break;
+    }
+    case 2:
+    {
+        uint16_t header[qdict_size(palette)];
+        struct palette_cb_priv priv = { vs, (uint8_t *)header };
+
+        qdict_iter(palette, write_palette, &priv);
+        vnc_write(vs, header, sizeof(header));
+        tight_encode_indexed_rect16(vs->tight.buffer, w * h, palette);
+        break;
+    }
+    default:
+        return -1; /* No palette for 8bits colors */
+        break;
+    }
+    bytes = w * h;
+    vs->tight.offset = bytes;
+
+    bytes = tight_compress_data(vs, stream, bytes,
+                                level, Z_DEFAULT_STRATEGY);
+    return (bytes >= 0);
+}
+
 static void vnc_tight_start(VncState *vs)
 {
     buffer_reset(&vs->tight);
@@ -375,18 +776,30 @@ static void vnc_tight_stop(VncState *vs)
 
 static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
 {
+    struct QDict *palette = NULL;
+    uint32_t bg = 0, fg = 0;
+    int colors;
+    int ret = 0;
+
     vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
 
-    /*
-     * Convert pixels and store them in vs->tight
-     * We will probably rework that later, probably
-     * when adding other sub-encodings
-     */
     vnc_tight_start(vs);
     vnc_raw_send_framebuffer_update(vs, x, y, w, h);
     vnc_tight_stop(vs);
 
-    return send_full_color_rect(vs, w, h);
+    colors = tight_fill_palette(vs, x, y, w * h, &fg, &bg, &palette);
+
+    if (colors == 0) {
+        ret = send_full_color_rect(vs, w, h);
+    } else if (colors == 1) {
+        ret = send_solid_rect(vs);
+    } else if (colors == 2) {
+        ret = send_mono_rect(vs, w, h, bg, fg);
+    } else if (colors <= 256) {
+        ret = send_palette_rect(vs, w, h, palette);
+    }
+    QDECREF(palette);
+    return ret;
 }
 
 static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
commit b4bea3f2b848a0815a28e316c14dc22919bc082b
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Wed May 19 09:24:11 2010 +0200

    vnc: add support for tight fill encoding
    
    Fill encoding detects rectangles using only one color and send only
    one pixel value.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index ce9cc49..2c9dab6 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -55,6 +55,139 @@ static const struct {
     { 65536, 2048,  32,  8192, 9, 9, 9, 6, 200, 500,  96, 80,   200,   500 }
 };
 
+/*
+ * Check if a rectangle is all of the same color. If needSameColor is
+ * set to non-zero, then also check that its color equals to the
+ * *colorPtr value. The result is 1 if the test is successfull, and in
+ * that case new color will be stored in *colorPtr.
+ */
+
+#define DEFINE_CHECK_SOLID_FUNCTION(bpp)                                \
+                                                                        \
+    static bool                                                         \
+    check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h,     \
+                          uint32_t* color, bool samecolor)              \
+    {                                                                   \
+        VncDisplay *vd = vs->vd;                                        \
+        uint##bpp##_t *fbptr;                                           \
+        uint##bpp##_t c;                                                \
+        int dx, dy;                                                     \
+                                                                        \
+        fbptr = (uint##bpp##_t *)                                       \
+            (vd->server->data + y * ds_get_linesize(vs->ds) +           \
+             x * ds_get_bytes_per_pixel(vs->ds));                       \
+                                                                        \
+        c = *fbptr;                                                     \
+        if (samecolor && (uint32_t)c != *color) {                       \
+            return false;                                               \
+        }                                                               \
+                                                                        \
+        for (dy = 0; dy < h; dy++) {                                    \
+            for (dx = 0; dx < w; dx++) {                                \
+                if (c != fbptr[dx]) {                                   \
+                    return false;                                       \
+                }                                                       \
+            }                                                           \
+            fbptr = (uint##bpp##_t *)                                   \
+                ((uint8_t *)fbptr + ds_get_linesize(vs->ds));           \
+        }                                                               \
+                                                                        \
+        *color = (uint32_t)c;                                           \
+        return true;                                                    \
+    }
+
+DEFINE_CHECK_SOLID_FUNCTION(32)
+DEFINE_CHECK_SOLID_FUNCTION(16)
+DEFINE_CHECK_SOLID_FUNCTION(8)
+
+static bool check_solid_tile(VncState *vs, int x, int y, int w, int h,
+                             uint32_t* color, bool samecolor)
+{
+    VncDisplay *vd = vs->vd;
+
+    switch(vd->server->pf.bytes_per_pixel) {
+    case 4:
+        return check_solid_tile32(vs, x, y, w, h, color, samecolor);
+    case 2:
+        return check_solid_tile16(vs, x, y, w, h, color, samecolor);
+    default:
+        return check_solid_tile8(vs, x, y, w, h, color, samecolor);
+    }
+}
+
+static void find_best_solid_area(VncState *vs, int x, int y, int w, int h,
+                                 uint32_t color, int *w_ptr, int *h_ptr)
+{
+    int dx, dy, dw, dh;
+    int w_prev;
+    int w_best = 0, h_best = 0;
+
+    w_prev = w;
+
+    for (dy = y; dy < y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+
+        dh = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, y + h - dy);
+        dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, w_prev);
+
+        if (!check_solid_tile(vs, x, dy, dw, dh, &color, true)) {
+            break;
+        }
+
+        for (dx = x + dw; dx < x + w_prev;) {
+            dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, x + w_prev - dx);
+
+            if (!check_solid_tile(vs, dx, dy, dw, dh, &color, true)) {
+                break;
+            }
+            dx += dw;
+        }
+
+        w_prev = dx - x;
+        if (w_prev * (dy + dh - y) > w_best * h_best) {
+            w_best = w_prev;
+            h_best = dy + dh - y;
+        }
+    }
+
+    *w_ptr = w_best;
+    *h_ptr = h_best;
+}
+
+static void extend_solid_area(VncState *vs, int x, int y, int w, int h,
+                              uint32_t color, int *x_ptr, int *y_ptr,
+                              int *w_ptr, int *h_ptr)
+{
+    int cx, cy;
+
+    /* Try to extend the area upwards. */
+    for ( cy = *y_ptr - 1;
+          cy >= y && check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1, &color, true);
+          cy-- );
+    *h_ptr += *y_ptr - (cy + 1);
+    *y_ptr = cy + 1;
+
+    /* ... downwards. */
+    for ( cy = *y_ptr + *h_ptr;
+          cy < y + h &&
+              check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1, &color, true);
+          cy++ );
+    *h_ptr += cy - (*y_ptr + *h_ptr);
+
+    /* ... to the left. */
+    for ( cx = *x_ptr - 1;
+          cx >= x && check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true);
+          cx-- );
+    *w_ptr += *x_ptr - (cx + 1);
+    *x_ptr = cx + 1;
+
+    /* ... to the right. */
+    for ( cx = *x_ptr + *w_ptr;
+          cx < x + w &&
+              check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true);
+          cx++ );
+    *w_ptr += cx - (*x_ptr + *w_ptr);
+}
+
 static int tight_init_stream(VncState *vs, int stream_id,
                              int level, int strategy)
 {
@@ -104,7 +237,7 @@ static void tight_send_compact_size(VncState *vs, size_t len)
             buf[bytes++] = (len >> 14) & 0xFF;
         }
     }
-    for(lpc = 0; lpc < bytes; lpc++) {
+    for (lpc = 0; lpc < bytes; lpc++) {
         vnc_write_u8(vs, buf[lpc]);
     }
 }
@@ -207,6 +340,23 @@ static int send_full_color_rect(VncState *vs, int w, int h)
     return (bytes >= 0);
 }
 
+static int send_solid_rect(VncState *vs)
+{
+    size_t bytes;
+
+    vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
+
+    if (vs->tight_pixel24) {
+        tight_pack24(vs, 1);
+        bytes = 3;
+    } else {
+        bytes = vs->clientds.pf.bytes_per_pixel;
+    }
+
+    vnc_write(vs, vs->tight.buffer, bytes);
+    return 1;
+}
+
 static void vnc_tight_start(VncState *vs)
 {
     buffer_reset(&vs->tight);
@@ -239,6 +389,17 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
     return send_full_color_rect(vs, w, h);
 }
 
+static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
+{
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
+
+    vnc_tight_start(vs);
+    vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+    vnc_tight_stop(vs);
+
+    return send_solid_rect(vs);
+}
+
 static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
 {
     int max_size, max_width;
@@ -268,9 +429,93 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
     return n;
 }
 
+static int find_large_solid_color_rect(VncState *vs, int x, int y,
+                                       int w, int h, int max_rows)
+{
+    int dx, dy, dw, dh;
+    int n = 0;
+
+    /* Try to find large solid-color areas and send them separately. */
+
+    for (dy = y; dy < y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+
+        /* If a rectangle becomes too large, send its upper part now. */
+
+        if (dy - y >= max_rows) {
+            n += send_rect_simple(vs, x, y, w, max_rows);
+            y += max_rows;
+            h -= max_rows;
+        }
+
+        dh = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (y + h - dy));
+
+        for (dx = x; dx < x + w; dx += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+            uint32_t color_value;
+            int x_best, y_best, w_best, h_best;
+
+            dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (x + w - dx));
+
+            if (!check_solid_tile(vs, dx, dy, dw, dh, &color_value, false)) {
+                continue ;
+            }
+
+            /* Get dimensions of solid-color area. */
+
+            find_best_solid_area(vs, dx, dy, w - (dx - x), h - (dy - y),
+                                 color_value, &w_best, &h_best);
+
+            /* Make sure a solid rectangle is large enough
+               (or the whole rectangle is of the same color). */
+
+            if (w_best * h_best != w * h &&
+                w_best * h_best < VNC_TIGHT_MIN_SOLID_SUBRECT_SIZE) {
+                continue;
+            }
+
+            /* Try to extend solid rectangle to maximum size. */
+
+            x_best = dx; y_best = dy;
+            extend_solid_area(vs, x, y, w, h, color_value,
+                              &x_best, &y_best, &w_best, &h_best);
+
+            /* Send rectangles at top and left to solid-color area. */
+
+            if (y_best != y) {
+                n += send_rect_simple(vs, x, y, w, y_best-y);
+            }
+            if (x_best != x) {
+                n += vnc_tight_send_framebuffer_update(vs, x, y_best,
+                                                       x_best-x, h_best);
+            }
+
+            /* Send solid-color rectangle. */
+            n += send_sub_rect_solid(vs, x_best, y_best, w_best, h_best);
+
+            /* Send remaining rectangles (at right and bottom). */
+
+            if (x_best + w_best != x + w) {
+                n += vnc_tight_send_framebuffer_update(vs, x_best+w_best,
+                                                       y_best,
+                                                       w-(x_best-x)-w_best,
+                                                       h_best);
+            }
+            if (y_best + h_best != y + h) {
+                n += vnc_tight_send_framebuffer_update(vs, x, y_best+h_best,
+                                                       w, h-(y_best-y)-h_best);
+            }
+
+            /* Return after all recursive calls are done. */
+            return n;
+        }
+    }
+    return n + send_rect_simple(vs, x, y, w, h);
+}
+
 int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
                                       int w, int h)
 {
+    int max_rows;
+
     if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
         vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
         vs->tight_pixel24 = true;
@@ -278,7 +523,15 @@ int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
         vs->tight_pixel24 = false;
     }
 
-    return send_rect_simple(vs, x, y, w, h);
+    if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE)
+        return send_rect_simple(vs, x, y, w, h);
+
+    /* Calculate maximum number of rows in one non-solid rectangle. */
+
+    max_rows = tight_conf[vs->tight_compression].max_rect_size;
+    max_rows /= MIN(tight_conf[vs->tight_compression].max_rect_width, w);
+
+    return find_large_solid_color_rect(vs, x, y, w, h, max_rows);
 }
 
 void vnc_tight_clear(VncState *vs)
commit 380282b07dcc262f011aa665972dacba5d2178bc
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Wed May 19 09:24:10 2010 +0200

    vnc: add basic tight support
    
    Add support for tight encoding [1]. This patch only add support
    for "basic" tight compression without any filter.
    
    [1] http://tigervnc.org/cgi-bin/rfbproto#tight-encoding.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/Makefile b/Makefile
index 7986bf6..9deb0f7 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,8 @@ vnc-encoding-zlib.o: vnc.h
 
 vnc-encoding-hextile.o: vnc.h
 
+vnc-encoding-tight.o: vnc.h vnc-encoding-tight.h
+
 curses.o: curses.c keymaps.h curses_keys.h
 
 bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index 1a942e5..9796dcb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -105,6 +105,7 @@ common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
 common-obj-$(CONFIG_CURSES) += curses.o
 common-obj-y += vnc.o acl.o d3des.o
 common-obj-y += vnc-encoding-zlib.o vnc-encoding-hextile.o
+common-obj-y += vnc-encoding-tight.o
 common-obj-y += iov.o
 common-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
new file mode 100644
index 0000000..ce9cc49
--- /dev/null
+++ b/vnc-encoding-tight.c
@@ -0,0 +1,295 @@
+/*
+ * QEMU VNC display driver: tight encoding
+ *
+ * From libvncserver/libvncserver/tight.c
+ * Copyright (C) 2000, 2001 Const Kaplinsky.  All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * 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 <stdbool.h>
+
+#include "vnc.h"
+#include "vnc-encoding-tight.h"
+
+/* Compression level stuff. The following array contains various
+   encoder parameters for each of 10 compression levels (0..9).
+   Last three parameters correspond to JPEG quality levels (0..9). */
+
+static const struct {
+    int max_rect_size, max_rect_width;
+    int mono_min_rect_size, gradient_min_rect_size;
+    int idx_zlib_level, mono_zlib_level, raw_zlib_level, gradient_zlib_level;
+    int gradient_threshold, gradient_threshold24;
+    int idx_max_colors_divisor;
+    int jpeg_quality, jpeg_threshold, jpeg_threshold24;
+} tight_conf[] = {
+    {   512,   32,   6, 65536, 0, 0, 0, 0,   0,   0,   4,  5, 10000, 23000 },
+    {  2048,  128,   6, 65536, 1, 1, 1, 0,   0,   0,   8, 10,  8000, 18000 },
+    {  6144,  256,   8, 65536, 3, 3, 2, 0,   0,   0,  24, 15,  6500, 15000 },
+    { 10240, 1024,  12, 65536, 5, 5, 3, 0,   0,   0,  32, 25,  5000, 12000 },
+    { 16384, 2048,  12, 65536, 6, 6, 4, 0,   0,   0,  32, 37,  4000, 10000 },
+    { 32768, 2048,  12,  4096, 7, 7, 5, 4, 150, 380,  32, 50,  3000,  8000 },
+    { 65536, 2048,  16,  4096, 7, 7, 6, 4, 170, 420,  48, 60,  2000,  5000 },
+    { 65536, 2048,  16,  4096, 8, 8, 7, 5, 180, 450,  64, 70,  1000,  2500 },
+    { 65536, 2048,  32,  8192, 9, 9, 8, 6, 190, 475,  64, 75,   500,  1200 },
+    { 65536, 2048,  32,  8192, 9, 9, 9, 6, 200, 500,  96, 80,   200,   500 }
+};
+
+static int tight_init_stream(VncState *vs, int stream_id,
+                             int level, int strategy)
+{
+    z_streamp zstream = &vs->tight_stream[stream_id];
+
+    if (zstream->opaque == NULL) {
+        int err;
+
+        VNC_DEBUG("VNC: TIGHT: initializing zlib stream %d\n", stream_id);
+        VNC_DEBUG("VNC: TIGHT: opaque = %p | vs = %p\n", zstream->opaque, vs);
+        zstream->zalloc = vnc_zlib_zalloc;
+        zstream->zfree = vnc_zlib_zfree;
+
+        err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS,
+                           MAX_MEM_LEVEL, strategy);
+
+        if (err != Z_OK) {
+            fprintf(stderr, "VNC: error initializing zlib\n");
+            return -1;
+        }
+
+        vs->tight_levels[stream_id] = level;
+        zstream->opaque = vs;
+    }
+
+    if (vs->tight_levels[stream_id] != level) {
+        if (deflateParams(zstream, level, strategy) != Z_OK) {
+            return -1;
+        }
+        vs->tight_levels[stream_id] = level;
+    }
+    return 0;
+}
+
+static void tight_send_compact_size(VncState *vs, size_t len)
+{
+    int lpc = 0;
+    int bytes = 0;
+    char buf[3] = {0, 0, 0};
+
+    buf[bytes++] = len & 0x7F;
+    if (len > 0x7F) {
+        buf[bytes-1] |= 0x80;
+        buf[bytes++] = (len >> 7) & 0x7F;
+        if (len > 0x3FFF) {
+            buf[bytes-1] |= 0x80;
+            buf[bytes++] = (len >> 14) & 0xFF;
+        }
+    }
+    for(lpc = 0; lpc < bytes; lpc++) {
+        vnc_write_u8(vs, buf[lpc]);
+    }
+}
+
+static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
+                               int level, int strategy)
+{
+    z_streamp zstream = &vs->tight_stream[stream_id];
+    int previous_out;
+
+    if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) {
+        vnc_write(vs, vs->tight.buffer, vs->tight.offset);
+        return bytes;
+    }
+
+    if (tight_init_stream(vs, stream_id, level, strategy)) {
+        return -1;
+    }
+
+    /* reserve memory in output buffer */
+    buffer_reserve(&vs->tight_zlib, bytes + 64);
+
+    /* set pointers */
+    zstream->next_in = vs->tight.buffer;
+    zstream->avail_in = vs->tight.offset;
+    zstream->next_out = vs->tight_zlib.buffer + vs->tight_zlib.offset;
+    zstream->avail_out = vs->tight_zlib.capacity - vs->tight_zlib.offset;
+    zstream->data_type = Z_BINARY;
+    previous_out = zstream->total_out;
+
+    /* start encoding */
+    if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
+        fprintf(stderr, "VNC: error during tight compression\n");
+        return -1;
+    }
+
+    vs->tight_zlib.offset = vs->tight_zlib.capacity - zstream->avail_out;
+    bytes = zstream->total_out - previous_out;
+
+    tight_send_compact_size(vs, bytes);
+    vnc_write(vs, vs->tight_zlib.buffer, bytes);
+
+    buffer_reset(&vs->tight_zlib);
+
+    return bytes;
+}
+
+/*
+ * Subencoding implementations.
+ */
+static void tight_pack24(VncState *vs, size_t count)
+{
+    unsigned char *buf;
+    uint32_t *buf32;
+    uint32_t pix;
+    int rshift, gshift, bshift;
+
+    buf = vs->tight.buffer;
+    buf32 = (uint32_t *)buf;
+
+    if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
+        (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) {
+        rshift = vs->clientds.pf.rshift;
+        gshift = vs->clientds.pf.gshift;
+        bshift = vs->clientds.pf.bshift;
+    } else {
+        rshift = 24 - vs->clientds.pf.rshift;
+        gshift = 24 - vs->clientds.pf.gshift;
+        bshift = 24 - vs->clientds.pf.bshift;
+    }
+
+    vs->tight.offset = count * 3;
+
+    while (count--) {
+        pix = *buf32++;
+        *buf++ = (char)(pix >> rshift);
+        *buf++ = (char)(pix >> gshift);
+        *buf++ = (char)(pix >> bshift);
+    }
+}
+
+static int send_full_color_rect(VncState *vs, int w, int h)
+{
+    int stream = 0;
+    size_t bytes;
+
+    vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
+
+    if (vs->tight_pixel24) {
+        tight_pack24(vs, w * h);
+        bytes = 3;
+    } else {
+        bytes = vs->clientds.pf.bytes_per_pixel;
+    }
+
+    bytes = tight_compress_data(vs, stream, w * h * bytes,
+                                tight_conf[vs->tight_compression].raw_zlib_level,
+                                Z_DEFAULT_STRATEGY);
+
+    return (bytes >= 0);
+}
+
+static void vnc_tight_start(VncState *vs)
+{
+    buffer_reset(&vs->tight);
+
+    // make the output buffer be the zlib buffer, so we can compress it later
+    vs->tight_tmp = vs->output;
+    vs->output = vs->tight;
+}
+
+static void vnc_tight_stop(VncState *vs)
+{
+    // switch back to normal output/zlib buffers
+    vs->tight = vs->output;
+    vs->output = vs->tight_tmp;
+}
+
+static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
+{
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
+
+    /*
+     * Convert pixels and store them in vs->tight
+     * We will probably rework that later, probably
+     * when adding other sub-encodings
+     */
+    vnc_tight_start(vs);
+    vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+    vnc_tight_stop(vs);
+
+    return send_full_color_rect(vs, w, h);
+}
+
+static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
+{
+    int max_size, max_width;
+    int max_sub_width, max_sub_height;
+    int dx, dy;
+    int rw, rh;
+    int n = 0;
+
+    max_size = tight_conf[vs->tight_compression].max_rect_size;
+    max_width = tight_conf[vs->tight_compression].max_rect_width;
+
+    if (w > max_width || w * h > max_size) {
+        max_sub_width = (w > max_width) ? max_width : w;
+        max_sub_height = max_size / max_sub_width;
+
+        for (dy = 0; dy < h; dy += max_sub_height) {
+            for (dx = 0; dx < w; dx += max_width) {
+                rw = MIN(max_sub_width, w - dx);
+                rh = MIN(max_sub_height, h - dy);
+                n += send_sub_rect(vs, x+dx, y+dy, rw, rh);
+            }
+        }
+    } else {
+        n += send_sub_rect(vs, x, y, w, h);
+    }
+
+    return n;
+}
+
+int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
+                                      int w, int h)
+{
+    if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
+        vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
+        vs->tight_pixel24 = true;
+    } else {
+        vs->tight_pixel24 = false;
+    }
+
+    return send_rect_simple(vs, x, y, w, h);
+}
+
+void vnc_tight_clear(VncState *vs)
+{
+    int i;
+    for (i=0; i<ARRAY_SIZE(vs->tight_stream); i++) {
+        if (vs->tight_stream[i].opaque) {
+            deflateEnd(&vs->tight_stream[i]);
+        }
+    }
+
+    buffer_free(&vs->tight);
+    buffer_free(&vs->tight_zlib);
+}
diff --git a/vnc-encoding-tight.h b/vnc-encoding-tight.h
new file mode 100644
index 0000000..64d1062
--- /dev/null
+++ b/vnc-encoding-tight.h
@@ -0,0 +1,176 @@
+/*
+ * QEMU VNC display driver: tight encoding
+ *
+ * From libvncserver/rfb/rfbproto.h
+ * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
+ * Copyright (C) 2000-2002 Constantin Kaplinsky.  All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
+ *
+ *
+ * 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 VNC_ENCODING_TIGHT_H
+#define VNC_ENCODING_TIGHT_H
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Tight Encoding.
+ *
+ *-- The first byte of each Tight-encoded rectangle is a "compression control
+ *   byte". Its format is as follows (bit 0 is the least significant one):
+ *
+ *   bit 0:    if 1, then compression stream 0 should be reset;
+ *   bit 1:    if 1, then compression stream 1 should be reset;
+ *   bit 2:    if 1, then compression stream 2 should be reset;
+ *   bit 3:    if 1, then compression stream 3 should be reset;
+ *   bits 7-4: if 1000 (0x08), then the compression type is "fill",
+ *             if 1001 (0x09), then the compression type is "jpeg",
+ *             if 0xxx, then the compression type is "basic",
+ *             values greater than 1001 are not valid.
+ *
+ * If the compression type is "basic", then bits 6..4 of the
+ * compression control byte (those xxx in 0xxx) specify the following:
+ *
+ *   bits 5-4:  decimal representation is the index of a particular zlib
+ *              stream which should be used for decompressing the data;
+ *   bit 6:     if 1, then a "filter id" byte is following this byte.
+ *
+ *-- The data that follows after the compression control byte described
+ * above depends on the compression type ("fill", "jpeg" or "basic").
+ *
+ *-- If the compression type is "fill", then the only pixel value follows, in
+ * client pixel format (see NOTE 1). This value applies to all pixels of the
+ * rectangle.
+ *
+ *-- If the compression type is "jpeg", the following data stream looks like
+ * this:
+ *
+ *   1..3 bytes:  data size (N) in compact representation;
+ *   N bytes:     JPEG image.
+ *
+ * Data size is compactly represented in one, two or three bytes, according
+ * to the following scheme:
+ *
+ *  0xxxxxxx                    (for values 0..127)
+ *  1xxxxxxx 0yyyyyyy           (for values 128..16383)
+ *  1xxxxxxx 1yyyyyyy zzzzzzzz  (for values 16384..4194303)
+ *
+ * Here each character denotes one bit, xxxxxxx are the least significant 7
+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the
+ * most significant 8 bits (bits 14-21). For example, decimal value 10000
+ * should be represented as two bytes: binary 10010000 01001110, or
+ * hexadecimal 90 4E.
+ *
+ *-- If the compression type is "basic" and bit 6 of the compression control
+ * byte was set to 1, then the next (second) byte specifies "filter id" which
+ * tells the decoder what filter type was used by the encoder to pre-process
+ * pixel data before the compression. The "filter id" byte can be one of the
+ * following:
+ *
+ *   0:  no filter ("copy" filter);
+ *   1:  "palette" filter;
+ *   2:  "gradient" filter.
+ *
+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id"
+ * byte), or if the filter id is 0, then raw pixel values in the client
+ * format (see NOTE 1) will be compressed. See below details on the
+ * compression.
+ *
+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm
+ * which converts each color component to a difference between a "predicted"
+ * intensity and the actual intensity. Such a technique does not affect
+ * uncompressed data size, but helps to compress photo-like images better.
+ * Pseudo-code for converting intensities to differences is the following:
+ *
+ *   P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1];
+ *   if (P[i,j] < 0) then P[i,j] := 0;
+ *   if (P[i,j] > MAX) then P[i,j] := MAX;
+ *   D[i,j] := V[i,j] - P[i,j];
+ *
+ * Here V[i,j] is the intensity of a color component for a pixel at
+ * coordinates (i,j). MAX is the maximum value of intensity for a color
+ * component.
+ *
+ *-- The "palette" filter converts true-color pixel data to indexed colors
+ * and a palette which can consist of 2..256 colors. If the number of colors
+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to
+ * encode one pixel. 1-bit encoding is performed such way that the most
+ * significant bits correspond to the leftmost pixels, and each raw of pixels
+ * is aligned to the byte boundary. When "palette" filter is used, the
+ * palette is sent before the pixel data. The palette begins with an unsigned
+ * byte which value is the number of colors in the palette minus 1 (i.e. 1
+ * means 2 colors, 255 means 256 colors in the palette). Then follows the
+ * palette itself which consist of pixel values in client pixel format (see
+ * NOTE 1).
+ *
+ *-- The pixel data is compressed using the zlib library. But if the data
+ * size after applying the filter but before the compression is less then 12,
+ * then the data is sent as is, uncompressed. Four separate zlib streams
+ * (0..3) can be used and the decoder should read the actual stream id from
+ * the compression control byte (see NOTE 2).
+ *
+ * If the compression is not used, then the pixel data is sent as is,
+ * otherwise the data stream looks like this:
+ *
+ *   1..3 bytes:  data size (N) in compact representation;
+ *   N bytes:     zlib-compressed data.
+ *
+ * Data size is compactly represented in one, two or three bytes, just like
+ * in the "jpeg" compression method (see above).
+ *
+ *-- NOTE 1. If the color depth is 24, and all three color components are
+ * 8-bit wide, then one pixel in Tight encoding is always represented by
+ * three bytes, where the first byte is red component, the second byte is
+ * green component, and the third byte is blue component of the pixel color
+ * value. This applies to colors in palettes as well.
+ *
+ *-- NOTE 2. The decoder must reset compression streams' states before
+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control
+ * byte are set to 1. Note that the decoder must reset zlib streams even if
+ * the compression type is "fill" or "jpeg".
+ *
+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
+ * when bits-per-pixel value is either 16 or 32, not 8.
+ *
+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048
+ * pixels. If a rectangle is wider, it must be split into several rectangles
+ * and each one should be encoded separately.
+ *
+ */
+
+#define VNC_TIGHT_EXPLICIT_FILTER       0x04
+#define VNC_TIGHT_FILL                  0x08
+#define VNC_TIGHT_JPEG                  0x09
+#define VNC_TIGHT_MAX_SUBENCODING       0x09
+
+/* Filters to improve compression efficiency */
+#define VNC_TIGHT_FILTER_COPY             0x00
+#define VNC_TIGHT_FILTER_PALETTE          0x01
+#define VNC_TIGHT_FILTER_GRADIENT         0x02
+
+/* Note: The following constant should not be changed. */
+#define VNC_TIGHT_MIN_TO_COMPRESS 12
+
+/* The parameters below may be adjusted. */
+#define VNC_TIGHT_MIN_SPLIT_RECT_SIZE     4096
+#define VNC_TIGHT_MIN_SOLID_SUBRECT_SIZE  2048
+#define VNC_TIGHT_MAX_SPLIT_TILE_SIZE       16
+
+#endif /* VNC_ENCODING_TIGHT_H */
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 88ac863..a99bc38 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -28,7 +28,7 @@
 
 #define ZALLOC_ALIGNMENT 16
 
-static void *zalloc(void *x, unsigned items, unsigned size)
+void *vnc_zlib_zalloc(void *x, unsigned items, unsigned size)
 {
     void *p;
 
@@ -40,7 +40,7 @@ static void *zalloc(void *x, unsigned items, unsigned size)
     return (p);
 }
 
-static void zfree(void *x, void *addr)
+void vnc_zlib_zfree(void *x, void *addr)
 {
     qemu_free(addr);
 }
@@ -72,8 +72,8 @@ static int vnc_zlib_stop(VncState *vs)
 
         VNC_DEBUG("VNC: initializing zlib stream\n");
         VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
-        zstream->zalloc = zalloc;
-        zstream->zfree = zfree;
+        zstream->zalloc = vnc_zlib_zalloc;
+        zstream->zfree = vnc_zlib_zfree;
 
         err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS,
                            MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
diff --git a/vnc.c b/vnc.c
index 626f173..046bd38 100644
--- a/vnc.c
+++ b/vnc.c
@@ -678,6 +678,9 @@ static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
             n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
             break;
+        case VNC_ENCODING_TIGHT:
+            n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
+            break;
         default:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
             n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
@@ -982,6 +985,7 @@ static void vnc_disconnect_finish(VncState *vs)
     qobject_decref(vs->info);
 
     vnc_zlib_clear(vs);
+    vnc_tight_clear(vs);
 
 #ifdef CONFIG_VNC_TLS
     vnc_tls_client_cleanup(vs);
@@ -1677,6 +1681,10 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             vs->features |= VNC_FEATURE_HEXTILE_MASK;
             vs->vnc_encoding = enc;
             break;
+        case VNC_ENCODING_TIGHT:
+            vs->features |= VNC_FEATURE_TIGHT_MASK;
+            vs->vnc_encoding = enc;
+            break;
         case VNC_ENCODING_ZLIB:
             vs->features |= VNC_FEATURE_ZLIB_MASK;
             vs->vnc_encoding = enc;
diff --git a/vnc.h b/vnc.h
index cd6495f..51595e6 100644
--- a/vnc.h
+++ b/vnc.h
@@ -170,6 +170,12 @@ struct VncState
     /* Tight */
     uint8_t tight_quality;
     uint8_t tight_compression;
+    uint8_t tight_pixel24;
+    Buffer tight;
+    Buffer tight_tmp;
+    Buffer tight_zlib;
+    int tight_levels[4];
+    z_stream tight_stream[4];
 
     /* Hextile */
     VncSendHextileTile *send_hextile_tile;
@@ -404,7 +410,13 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
                                          int y, int w, int h);
 void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
 
+void *vnc_zlib_zalloc(void *x, unsigned items, unsigned size);
+void vnc_zlib_zfree(void *x, void *addr);
 int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
 void vnc_zlib_clear(VncState *vs);
 
+
+int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+void vnc_tight_clear(VncState *vs);
+
 #endif /* __QEMU_VNC_H */
commit a885211eed4e853c64d1419a0113c12048ecd5a1
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Wed May 19 09:24:09 2010 +0200

    vnc: return the number of rectangles
    
    Some encodings like tight supports tiling (spliting in
    multiple sub-rectangles). So we needed a way to tell
    vnc_update_client() how much rectangles are in the buffer.
    
    zlib, raw and hextile always send a full rectangle.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vnc-encoding-hextile.c b/vnc-encoding-hextile.c
index a01c5e2..728f25e 100644
--- a/vnc-encoding-hextile.c
+++ b/vnc-encoding-hextile.c
@@ -62,8 +62,8 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
 #undef BPP
 #undef GENERIC
 
-void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
-                                         int y, int w, int h)
+int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
+                                        int y, int w, int h)
 {
     int i, j;
     int has_fg, has_bg;
@@ -83,6 +83,7 @@ void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
     free(last_fg);
     free(last_bg);
 
+    return 1;
 }
 
 void vnc_hextile_set_pixel_conversion(VncState *vs, int generic)
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 1d4dd1a..88ac863 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -116,7 +116,7 @@ static int vnc_zlib_stop(VncState *vs)
     return zstream->total_out - previous_out;
 }
 
-void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     int old_offset, new_offset, bytes_written;
 
@@ -132,13 +132,15 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
     bytes_written = vnc_zlib_stop(vs);
 
     if (bytes_written == -1)
-        return;
+        return 0;
 
     // hack in the size
     new_offset = vs->output.offset;
     vs->output.offset = old_offset;
     vnc_write_u32(vs, bytes_written);
     vs->output.offset = new_offset;
+
+    return 1;
 }
 
 void vnc_zlib_clear(VncState *vs)
diff --git a/vnc.c b/vnc.c
index f48f253..626f173 100644
--- a/vnc.c
+++ b/vnc.c
@@ -652,7 +652,7 @@ static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
     }
 }
 
-void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     int i;
     uint8_t *row;
@@ -663,23 +663,27 @@ void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
         vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
         row += ds_get_linesize(vs->ds);
     }
+    return 1;
 }
 
-static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
+    int n = 0;
+
     switch(vs->vnc_encoding) {
         case VNC_ENCODING_ZLIB:
-            vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
+            n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
             break;
         case VNC_ENCODING_HEXTILE:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
-            vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
+            n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
             break;
         default:
             vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
-            vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+            n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
             break;
     }
+    return n;
 }
 
 static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
@@ -834,6 +838,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
         int y;
         int n_rectangles;
         int saved_offset;
+        int n;
 
         if (vs->output.offset && !vs->audio_cap && !vs->force_update)
             /* kernel send buffers are full -> drop frames to throttle */
@@ -866,16 +871,18 @@ static int vnc_update_client(VncState *vs, int has_dirty)
                 } else {
                     if (last_x != -1) {
                         int h = find_and_clear_dirty_height(vs, y, last_x, x);
-