[Spice-commits] 504 commits - .travis.yml MAINTAINERS Makefile.objs arch_init.c backends/rng-random.c block.c block/Makefile.objs block/blkdebug.c block/blkverify.c block/commit.c block/curl.c block/gluster.c block/iscsi.c block/mirror.c block/nbd-client.c block/nbd-client.h block/nbd.c block/qcow2.c block/raw-posix.c block/raw-win32.c block/rbd.c block/sheepdog.c block/vhdx-log.c block/vhdx.c block/vhdx.h block/vmdk.c block/vvfat.c blockdev.c configure cpu-exec.c cpus.c cputlb.c default-configs/aarch64-linux-user.mak default-configs/aarch64-softmmu.mak default-configs/arm-softmmu.mak device_tree.c exec.c fpu/softfloat.c gdb-xml/aarch64-fpu.xml hmp-commands.hx hmp.c hmp.h hw/acpi hw/alpha hw/arm hw/audio hw/block hw/char hw/core hw/cpu hw/display hw/dma hw/gpio hw/i2c hw/i386 hw/ide hw/input hw/intc hw/isa hw/microblaze hw/mips hw/misc hw/net hw/nvram hw/pci hw/pci-bridge hw/pci-host hw/ppc hw/s390x hw/scsi hw/sd hw/sh4 hw/timer hw/virtio hw/watchdog hw/xen include/block include/exec includ e/fpu include/hw include/migration include/monitor include/qapi include/qemu include/qom include/sysemu include/ui kvm-all.c libcacard/vscclient.c linux-user/aarch64 linux-user/arm linux-user/elfload.c linux-user/flatload.c linux-user/linuxload.c linux-user/main.c linux-user/qemu.h linux-user/signal.c linux-user/syscall.c linux-user/syscall_defs.h memory.c migration.c nbd.c net/net.c qapi-schema.json qdev-monitor.c qemu-char.c qemu-doc.texi qemu-file.c qemu-img.c qemu-img.texi qemu-options.hx qemu-seccomp.c qmp-commands.hx qmp.c qobject/qerror.c qom/cpu.c qom/object.c savevm.c spice-qemu-char.c target-arm/Makefile.objs target-arm/cpu-qom.h target-arm/cpu.c target-arm/cpu.h target-arm/cpu64.c target-arm/crypto_helper.c target-arm/gdbstub64.c target-arm/helper-a64.c target-arm/helper-a64.h target-arm/helper.c target-arm/helper.h target-arm/kvm-consts.h target-arm/kvm.c target-arm/kvm32.c target-arm/kvm64.c target-arm/machine.c target-arm/neon_helper.c target-arm/translate-a64.c target -arm/translate.c target-arm/translate.h target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/helper.c target-i386/kvm.c target-i386/misc_helper.c target-i386/translate.c target-microblaze/cpu.c target-microblaze/cpu.h target-mips/translate.c target-openrisc/translate.c target-ppc/cpu-models.c target-ppc/cpu-models.h target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/excp_helper.c target-ppc/helper_regs.h target-ppc/kvm.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu.h target-s390x/ioinst.c target-s390x/kvm.c target-sh4/translate.c target-sparc/translate.c tcg/i386 tests/.gitignore tests/Makefile tests/acpi-test.c tests/check-qom-interface.c tests/i440fx-test.c tests/qemu-iotests tests/qom-test.c tests/test-vmstate.c translate-all.c ui/cocoa.m ui/spice-core.c ui/spice-display.c util/bitmap.c util/error.c util/qemu-config.c util/qemu-option.c util/qemu-sockets.c vl.c vmstate.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Fri Jan 24 00:15:28 PST 2014


 .travis.yml                              |    1 
 MAINTAINERS                              |   14 
 Makefile.objs                            |    2 
 arch_init.c                              |   52 
 backends/rng-random.c                    |    4 
 block.c                                  |    5 
 block/Makefile.objs                      |    2 
 block/blkdebug.c                         |   10 
 block/blkverify.c                        |    2 
 block/commit.c                           |    8 
 block/curl.c                             |    2 
 block/gluster.c                          |    2 
 block/iscsi.c                            |   18 
 block/mirror.c                           |   78 
 block/nbd-client.c                       |  385 ++
 block/nbd-client.h                       |   50 
 block/nbd.c                              |  383 --
 block/qcow2.c                            |    2 
 block/raw-posix.c                        |    2 
 block/raw-win32.c                        |    5 
 block/rbd.c                              |    2 
 block/sheepdog.c                         |   17 
 block/vhdx-log.c                         |   13 
 block/vhdx.c                             |   22 
 block/vhdx.h                             |    5 
 block/vmdk.c                             |  173 -
 block/vvfat.c                            |   45 
 blockdev.c                               |   17 
 configure                                |  388 +-
 cpu-exec.c                               |   50 
 cpus.c                                   |    5 
 cputlb.c                                 |   32 
 default-configs/aarch64-linux-user.mak   |    3 
 default-configs/aarch64-softmmu.mak      |    6 
 default-configs/arm-softmmu.mak          |    5 
 device_tree.c                            |   64 
 exec.c                                   |  120 
 fpu/softfloat.c                          | 1055 +++++--
 gdb-xml/aarch64-fpu.xml                  |   86 
 hmp-commands.hx                          |   41 
 hmp.c                                    |   77 
 hmp.h                                    |    3 
 hw/acpi/core.c                           |   18 
 hw/acpi/ich9.c                           |   24 
 hw/acpi/piix4.c                          |   33 
 hw/alpha/typhoon.c                       |    2 
 hw/arm/Makefile.objs                     |    3 
 hw/arm/allwinner-a10.c                   |  103 
 hw/arm/boot.c                            |  217 +
 hw/arm/cubieboard.c                      |   69 
 hw/arm/digic.c                           |  115 
 hw/arm/digic_boards.c                    |  162 +
 hw/arm/highbank.c                        |   40 
 hw/arm/mainstone.c                       |   15 
 hw/arm/versatilepb.c                     |    1 
 hw/arm/vexpress.c                        |   62 
 hw/arm/virt.c                            |  106 
 hw/arm/xilinx_zynq.c                     |   38 
 hw/arm/z2.c                              |    2 
 hw/audio/intel-hda.c                     |    4 
 hw/audio/marvell_88w8618.c               |    2 
 hw/audio/pcspk.c                         |    3 
 hw/audio/pl041.c                         |    1 
 hw/block/dataplane/virtio-blk.c          |   86 
 hw/block/fdc.c                           |    1 
 hw/block/pflash_cfi01.c                  |  260 +
 hw/char/Makefile.objs                    |    1 
 hw/char/cadence_uart.c                   |  153 -
 hw/char/digic-uart.c                     |  195 +
 hw/char/exynos4210_uart.c                |    6 
 hw/core/loader.c                         |    7 
 hw/core/qdev-properties-system.c         |    8 
 hw/core/qdev-properties.c                |   40 
 hw/core/qdev.c                           |   82 
 hw/core/sysbus.c                         |    7 
 hw/cpu/icc_bus.c                         |   14 
 hw/display/pl110.c                       |    1 
 hw/display/qxl.c                         |   10 
 hw/dma/pl080.c                           |    1 
 hw/dma/sparc32_dma.c                     |    2 
 hw/dma/xilinx_axidma.c                   |   13 
 hw/gpio/omap_gpio.c                      |    4 
 hw/i2c/omap_i2c.c                        |    2 
 hw/i2c/smbus_eeprom.c                    |    2 
 hw/i2c/smbus_ich9.c                      |    6 
 hw/i386/acpi-dsdt-cpu-hotplug.dsl        |    1 
 hw/i386/kvm/apic.c                       |   14 
 hw/i386/kvm/clock.c                      |    1 
 hw/i386/kvm/ioapic.c                     |    8 
 hw/i386/kvmvapic.c                       |    9 
 hw/i386/pc.c                             |   24 
 hw/i386/pc_piix.c                        |   19 
 hw/i386/pc_sysfw.c                       |  105 
 hw/i386/q35-acpi-dsdt.dsl                |    4 
 hw/ide/piix.c                            |    3 
 hw/ide/via.c                             |    1 
 hw/input/pckbd.c                         |    1 
 hw/input/pxa2xx_keypad.c                 |    6 
 hw/input/vmmouse.c                       |    3 
 hw/intc/Makefile.objs                    |    1 
 hw/intc/allwinner-a10-pic.c              |  200 +
 hw/intc/apic.c                           |   48 
 hw/intc/apic_common.c                    |   79 
 hw/intc/arm_gic.c                        |   28 
 hw/intc/arm_gic_common.c                 |    5 
 hw/intc/arm_gic_kvm.c                    |    1 
 hw/intc/etraxfs_pic.c                    |    4 
 hw/intc/gic_internal.h                   |    7 
 hw/intc/grlib_irqmp.c                    |    2 
 hw/intc/i8259_common.c                   |    8 
 hw/intc/ioapic.c                         |   13 
 hw/intc/ioapic_common.c                  |   16 
 hw/intc/omap_intc.c                      |    4 
 hw/intc/pl190.c                          |    1 
 hw/intc/xics.c                           |   24 
 hw/isa/isa-bus.c                         |    1 
 hw/isa/lpc_ich9.c                        |    7 
 hw/isa/piix4.c                           |    6 
 hw/isa/vt82c686.c                        |    6 
 hw/microblaze/Makefile.objs              |    1 
 hw/microblaze/boot.c                     |   12 
 hw/microblaze/petalogix_ml605_mmu.c      |    9 
 hw/microblaze/petalogix_s3adsp1800_mmu.c |    9 
 hw/microblaze/pic_cpu.c                  |   47 
 hw/microblaze/pic_cpu.h                  |    8 
 hw/mips/gt64xxx_pci.c                    |    6 
 hw/misc/arm_l2x0.c                       |    1 
 hw/misc/exynos4210_pmu.c                 |    3 
 hw/misc/vmport.c                         |    3 
 hw/net/etraxfs_eth.c                     |    2 
 hw/net/lance.c                           |    2 
 hw/net/xilinx_axienet.c                  |   13 
 hw/nvram/fw_cfg.c                        |    1 
 hw/nvram/spapr_nvram.c                   |   16 
 hw/pci-bridge/dec.c                      |    6 
 hw/pci-host/apb.c                        |    6 
 hw/pci-host/bonito.c                     |    8 
 hw/pci-host/grackle.c                    |   10 
 hw/pci-host/piix.c                       |   30 
 hw/pci-host/ppce500.c                    |    5 
 hw/pci-host/prep.c                       |    7 
 hw/pci-host/q35.c                        |    5 
 hw/pci-host/uninorth.c                   |   28 
 hw/pci-host/versatile.c                  |    6 
 hw/pci/pci.c                             |   42 
 hw/pci/pci_bridge.c                      |    4 
 hw/ppc/e500.c                            |  213 -
 hw/ppc/e500plat.c                        |    6 
 hw/ppc/mpc8544ds.c                       |    6 
 hw/ppc/ppc440_bamboo.c                   |   24 
 hw/ppc/ppc4xx_pci.c                      |    5 
 hw/ppc/spapr.c                           |   49 
 hw/ppc/spapr_events.c                    |    6 
 hw/ppc/spapr_pci.c                       |   42 
 hw/ppc/spapr_rtas.c                      |   97 
 hw/ppc/spapr_vio.c                       |   14 
 hw/ppc/virtex_ml507.c                    |    2 
 hw/s390x/ipl.c                           |    1 
 hw/s390x/s390-virtio-bus.c               |    2 
 hw/s390x/virtio-ccw.c                    |    7 
 hw/scsi/scsi-disk.c                      |   20 
 hw/sd/pl181.c                            |    1 
 hw/sh4/sh_pci.c                          |    6 
 hw/timer/Makefile.objs                   |    3 
 hw/timer/allwinner-a10-pit.c             |  254 +
 hw/timer/arm_mptimer.c                   |    1 
 hw/timer/digic-timer.c                   |  163 +
 hw/timer/hpet.c                          |    1 
 hw/timer/i8254_common.c                  |    7 
 hw/timer/m48t59.c                        |    3 
 hw/timer/mc146818rtc.c                   |    3 
 hw/timer/pl031.c                         |    1 
 hw/virtio/dataplane/Makefile.objs        |    2 
 hw/virtio/dataplane/hostmem.c            |  183 -
 hw/virtio/dataplane/vring.c              |  253 +
 hw/virtio/virtio.c                       |    2 
 hw/watchdog/watchdog.c                   |    3 
 hw/xen/xen_apic.c                        |    6 
 include/block/block_int.h                |   22 
 include/exec/cpu-all.h                   |    3 
 include/exec/cpu-common.h                |    1 
 include/exec/memory-internal.h           |   90 
 include/exec/memory.h                    |   12 
 include/exec/ram_addr.h                  |  147 +
 include/fpu/softfloat.h                  |   96 
 include/hw/acpi/acpi.h                   |    8 
 include/hw/arm/allwinner-a10.h           |   35 
 include/hw/arm/digic.h                   |   43 
 include/hw/arm/pxa.h                     |    8 
 include/hw/char/digic-uart.h             |   47 
 include/hw/cpu/icc_bus.h                 |    2 
 include/hw/i386/apic_internal.h          |    2 
 include/hw/i386/ioapic_internal.h        |    3 
 include/hw/i386/pc.h                     |    1 
 include/hw/intc/allwinner-a10-pic.h      |   40 
 include/hw/intc/arm_gic_common.h         |    2 
 include/hw/pci/pci.h                     |    1 
 include/hw/ppc/spapr.h                   |    9 
 include/hw/ptimer.h                      |    4 
 include/hw/qdev-core.h                   |   30 
 include/hw/qdev-properties.h             |   17 
 include/hw/timer/allwinner-a10-pit.h     |   58 
 include/hw/timer/digic-timer.h           |   46 
 include/hw/virtio/dataplane/hostmem.h    |   58 
 include/hw/virtio/dataplane/vring.h      |   10 
 include/hw/xilinx.h                      |   14 
 include/migration/migration.h            |   11 
 include/migration/qemu-file.h            |    4 
 include/migration/vmstate.h              |   10 
 include/monitor/monitor.h                |    3 
 include/qapi/error.h                     |    6 
 include/qapi/qmp/qerror.h                |    1 
 include/qapi/visitor.h                   |    3 
 include/qemu/bitmap.h                    |   86 
 include/qemu/bitops.h                    |   14 
 include/qemu/host-utils.h                |   32 
 include/qemu/option.h                    |    1 
 include/qemu/typedefs.h                  |    2 
 include/qom/object.h                     |    4 
 include/sysemu/blockdev.h                |    2 
 include/sysemu/char.h                    |   10 
 include/sysemu/device_tree.h             |   80 
 include/ui/qemu-spice.h                  |    2 
 kvm-all.c                                |   28 
 libcacard/vscclient.c                    |   10 
 linux-user/aarch64/syscall.h             |    1 
 linux-user/aarch64/target_cpu.h          |    5 
 linux-user/arm/target_cpu.h              |    2 
 linux-user/elfload.c                     |    3 
 linux-user/flatload.c                    |    3 
 linux-user/linuxload.c                   |    4 
 linux-user/main.c                        |  154 -
 linux-user/qemu.h                        |    6 
 linux-user/signal.c                      |   24 
 linux-user/syscall.c                     |   16 
 linux-user/syscall_defs.h                |    1 
 memory.c                                 |   17 
 migration.c                              |   34 
 nbd.c                                    |    2 
 net/net.c                                |    2 
 qapi-schema.json                         |   43 
 qdev-monitor.c                           |   17 
 qemu-char.c                              |   10 
 qemu-doc.texi                            |   15 
 qemu-file.c                              |  826 +++++
 qemu-img.c                               |   28 
 qemu-img.texi                            |    4 
 qemu-options.hx                          |    2 
 qemu-seccomp.c                           |    1 
 qmp-commands.hx                          |   51 
 qmp.c                                    |   78 
 qobject/qerror.c                         |    8 
 qom/cpu.c                                |    6 
 qom/object.c                             |   61 
 savevm.c                                 | 1590 -----------
 spice-qemu-char.c                        |   11 
 target-arm/Makefile.objs                 |    5 
 target-arm/cpu-qom.h                     |    1 
 target-arm/cpu.c                         |   60 
 target-arm/cpu.h                         |  222 +
 target-arm/cpu64.c                       |   20 
 target-arm/crypto_helper.c               |  281 +
 target-arm/gdbstub64.c                   |    4 
 target-arm/helper-a64.c                  |  124 
 target-arm/helper-a64.h                  |   28 
 target-arm/helper.c                      |  512 ++-
 target-arm/helper.h                      |   47 
 target-arm/kvm-consts.h                  |   37 
 target-arm/kvm.c                         |  495 ---
 target-arm/kvm32.c                       |  515 +++
 target-arm/kvm64.c                       |  204 +
 target-arm/machine.c                     |   12 
 target-arm/neon_helper.c                 |   12 
 target-arm/translate-a64.c               | 4373 ++++++++++++++++++++++++++++++-
 target-arm/translate.c                   |  214 -
 target-arm/translate.h                   |   27 
 target-i386/cpu-qom.h                    |    6 
 target-i386/cpu.c                        |  112 
 target-i386/cpu.h                        |    4 
 target-i386/helper.c                     |   18 
 target-i386/kvm.c                        |   23 
 target-i386/misc_helper.c                |    8 
 target-i386/translate.c                  | 2645 +++++++-----------
 target-microblaze/cpu.c                  |   21 
 target-microblaze/cpu.h                  |    4 
 target-mips/translate.c                  |  119 
 target-openrisc/translate.c              |    2 
 target-ppc/cpu-models.c                  |    3 
 target-ppc/cpu-models.h                  |    7 
 target-ppc/cpu-qom.h                     |    2 
 target-ppc/cpu.h                         |    9 
 target-ppc/excp_helper.c                 |    5 
 target-ppc/helper_regs.h                 |    2 
 target-ppc/kvm.c                         |   32 
 target-ppc/translate.c                   |  624 ++++
 target-ppc/translate_init.c              |   91 
 target-s390x/cpu.h                       |    3 
 target-s390x/ioinst.c                    |    1 
 target-s390x/kvm.c                       |   98 
 target-sh4/translate.c                   |  167 -
 target-sparc/translate.c                 |    1 
 tcg/i386/tcg-target.c                    |    2 
 tests/.gitignore                         |    1 
 tests/Makefile                           |   10 
 tests/acpi-test.c                        |    5 
 tests/check-qom-interface.c              |  105 
 tests/i440fx-test.c                      |  167 +
 tests/qemu-iotests/040                   |   74 
 tests/qemu-iotests/051.out               |    1 
 tests/qemu-iotests/059                   |   14 
 tests/qemu-iotests/059.out               |    5 
 tests/qom-test.c                         |    2 
 tests/test-vmstate.c                     |  357 ++
 translate-all.c                          |    5 
 ui/cocoa.m                               |  103 
 ui/spice-core.c                          |   22 
 ui/spice-display.c                       |   17 
 util/bitmap.c                            |   60 
 util/error.c                             |   22 
 util/qemu-config.c                       |    2 
 util/qemu-option.c                       |    9 
 util/qemu-sockets.c                      |   18 
 vl.c                                     |   31 
 vmstate.c                                |  650 ++++
 324 files changed, 17428 insertions(+), 7110 deletions(-)

New commits:
commit 1cf892ca2689c84960b4ce4d2723b6bee453711c
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:   Wed Nov 27 08:50:11 2013 +0100

    SPARC: Fix LEON3 power down instruction
    
    Synchronize the program counter before the power down helper call
    otherwise interrupts will return to the wrong context.
    
    Signed-off-by: Sebastian Huber <sebastian.huber at embedded-brains.de>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Reviewed-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index dce64c3..6150b22 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3626,6 +3626,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
                                 if ((rd == 0x13) && (dc->def->features &
                                                      CPU_FEATURE_POWERDOWN)) {
                                     /* LEON3 power-down */
+                                    save_state(dc);
                                     gen_helper_power_down(cpu_env);
                                 }
                                 break;
commit d32934c84c72f57e78d430c22974677b7bcabe5d
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Tue Jan 14 19:37:09 2014 -0800

    error: Don't use error_report() for assertion msgs.
    
    Use fprintf(stderr instead. This removes dependency of libqemuutil.a
    on the monitor.
    
    We can further justify this change, in that this code path should only
    trigger under a fatal error condition. fprintf-stderr is probably the
    appropriate medium as under a fatal error conidition the monitor itself
    may be down and out for the count. So assertion failure messages should
    go lowest common denominator - straight to stderr.
    
    Fixes the build as reported by Kevin Wolf. Issue debugged and change
    suggested by Luiz Capitulino. Issue introduced by
    5d24ee70bcbcf578614193526bcd5ed30a8eb16c.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/util/error.c b/util/error.c
index f11f1d5..e5de34f 100644
--- a/util/error.c
+++ b/util/error.c
@@ -44,7 +44,7 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
     err->err_class = err_class;
 
     if (errp == &error_abort) {
-        error_report("%s", error_get_pretty(err));
+        fprintf(stderr, "%s\n", error_get_pretty(err));
         abort();
     }
 
@@ -80,7 +80,7 @@ void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
     err->err_class = err_class;
 
     if (errp == &error_abort) {
-        error_report("%s", error_get_pretty(err));
+        fprintf(stderr, "%s\n", error_get_pretty(err));
         abort();
     }
 
@@ -125,7 +125,7 @@ void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
     err->err_class = err_class;
 
     if (errp == &error_abort) {
-        error_report("%s", error_get_pretty(err));
+        fprintf(stderr, "%s\n", error_get_pretty(err));
         abort();
     }
 
@@ -171,7 +171,7 @@ void error_free(Error *err)
 void error_propagate(Error **dst_err, Error *local_err)
 {
     if (local_err && dst_err == &error_abort) {
-        error_report("%s", error_get_pretty(local_err));
+        fprintf(stderr, "%s\n", error_get_pretty(local_err));
         abort();
     } else if (dst_err && !*dst_err) {
         *dst_err = local_err;
commit 133fe77437d3a23bf1fd70a231b4f29d5fa0571c
Merge: 73c6945 c950114
Author: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
Date:   Tue Jan 14 12:09:59 2014 +1000

    Merge remote branch 'luiz/queue/qmp' into qmpq
    
    * luiz/queue/qmp:
      migration: qmp_migrate(): keep working after syntax error
      qerror: Remove assert_no_error()
      qemu-option: Remove qemu_opts_create_nofail
      target-i386: Remove assert_no_error usage
      hw: Remove assert_no_error usages
      qdev: Delete dead code
      error: Add error_abort
      monitor: add object-add (QMP) and object_add (HMP) command
      monitor: add object-del (QMP) and object_del (HMP) command
      qom: catch errors in object_property_add_child
      qom: fix leak for objects created with -object
      rng: initialize file descriptor to -1
      qemu-monitor: HMP cpu-add wrapper
      vl: add missing transition debug->finish_migrate
    
    Message-Id: 1389045795-18706-1-git-send-email-lcapitulino at redhat.com
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

commit 73c694565c6144e0c4e15041b5250a04a25107c3
Author: Alistair Francis <alistair.francis at xilinx.com>
Date:   Mon Jan 13 13:35:26 2014 +1000

    Microblaze: Convert Microblaze-pic handling to GPIOs
    
    This patch uses inbound GPIO lines (IRQ and FIR) for
    interrupts instead of using the old pic_cpu method,
    which doesn't correspond to real hardware.
    
    This creates the CPU's inbound IRQ and FIR GPIO lines and
    updates the Microblaze boards to use this new method.
    
    Signed-off-by: Alistair Francis <alistair.francis at xilinx.com>
    Suggested-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reveiwed-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/hw/microblaze/Makefile.objs b/hw/microblaze/Makefile.objs
index c65e2aa..b2517d8 100644
--- a/hw/microblaze/Makefile.objs
+++ b/hw/microblaze/Makefile.objs
@@ -1,4 +1,3 @@
 obj-y += petalogix_s3adsp1800_mmu.o
 obj-y += petalogix_ml605_mmu.o
 obj-y += boot.o
-obj-y += pic_cpu.o
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 10970e0..1a87756 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -39,7 +39,6 @@
 #include "hw/ssi.h"
 
 #include "boot.h"
-#include "pic_cpu.h"
 
 #include "hw/stream.h"
 
@@ -82,20 +81,18 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
     Object *ds, *cs;
     MicroBlazeCPU *cpu;
     SysBusDevice *busdev;
-    CPUMBState *env;
     DriveInfo *dinfo;
     int i;
     hwaddr ddr_base = MEMORY_BASEADDR;
     MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
+    qemu_irq irq[32];
 
     /* init CPUs */
     if (cpu_model == NULL) {
         cpu_model = "microblaze";
     }
     cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram",
@@ -117,8 +114,8 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
                           2, 0x89, 0x18, 0x0000, 0x0, 0);
 
 
-    cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 4);
+    dev = xilinx_intc_create(INTC_BASEADDR, qdev_get_gpio_in(DEVICE(cpu),
+                             MB_CPU_IRQ), 4);
     for (i = 0; i < 32; i++) {
         irq[i] = qdev_get_gpio_in(dev, i);
     }
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index ec6489c..f500215 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -35,7 +35,6 @@
 #include "exec/address-spaces.h"
 
 #include "boot.h"
-#include "pic_cpu.h"
 
 #define LMB_BRAM_SIZE  (128 * 1024)
 #define FLASH_SIZE     (16 * 1024 * 1024)
@@ -63,13 +62,12 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
     const char *cpu_model = args->cpu_model;
     DeviceState *dev;
     MicroBlazeCPU *cpu;
-    CPUMBState *env;
     DriveInfo *dinfo;
     int i;
     hwaddr ddr_base = MEMORY_BASEADDR;
     MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1);
     MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
-    qemu_irq irq[32], *cpu_irq;
+    qemu_irq irq[32];
     MemoryRegion *sysmem = get_system_memory();
 
     /* init CPUs */
@@ -77,7 +75,6 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
         cpu_model = "microblaze";
     }
     cpu = cpu_mb_init(cpu_model);
-    env = &cpu->env;
 
     /* Attach emulated BRAM through the LMB.  */
     memory_region_init_ram(phys_lmb_bram, NULL,
@@ -96,8 +93,8 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args)
                           FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
-    cpu_irq = microblaze_pic_init_cpu(env);
-    dev = xilinx_intc_create(INTC_BASEADDR, cpu_irq[0], 0xA);
+    dev = xilinx_intc_create(INTC_BASEADDR, qdev_get_gpio_in(DEVICE(cpu),
+                             MB_CPU_IRQ), 0xA);
     for (i = 0; i < 32; i++) {
         irq[i] = qdev_get_gpio_in(dev, i);
     }
diff --git a/hw/microblaze/pic_cpu.c b/hw/microblaze/pic_cpu.c
deleted file mode 100644
index 16902f7..0000000
--- a/hw/microblaze/pic_cpu.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * QEMU MicroBlaze CPU interrupt wrapper logic.
- *
- * Copyright (c) 2009 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/hw.h"
-#include "pic_cpu.h"
-
-#define D(x)
-
-static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
-{
-    MicroBlazeCPU *cpu = opaque;
-    CPUState *cs = CPU(cpu);
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
-
-    if (level) {
-        cpu_interrupt(cs, type);
-    } else {
-        cpu_reset_interrupt(cs, type);
-    }
-}
-
-qemu_irq *microblaze_pic_init_cpu(CPUMBState *env)
-{
-    return qemu_allocate_irqs(microblaze_pic_cpu_handler, mb_env_get_cpu(env),
-                              2);
-}
diff --git a/hw/microblaze/pic_cpu.h b/hw/microblaze/pic_cpu.h
deleted file mode 100644
index 43090a4..0000000
--- a/hw/microblaze/pic_cpu.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef MICROBLAZE_PIC_CPU_H
-#define MICROBLAZE_PIC_CPU_H
-
-#include "qemu-common.h"
-
-qemu_irq *microblaze_pic_init_cpu(CPUMBState *env);
-
-#endif /*  MICROBLAZE_PIC_CPU_H */
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 0ef9aa4..f108c0b 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -4,6 +4,7 @@
  * Copyright (c) 2009 Edgar E. Iglesias
  * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
  * Copyright (c) 2012 SUSE LINUX Products GmbH
+ * Copyright (c) 2009 Edgar E. Iglesias, Axis Communications AB.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -33,6 +34,21 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
     cpu->env.sregs[SR_PC] = value;
 }
 
+#ifndef CONFIG_USER_ONLY
+static void microblaze_cpu_set_irq(void *opaque, int irq, int level)
+{
+    MicroBlazeCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level) {
+        cpu_interrupt(cs, type);
+    } else {
+        cpu_reset_interrupt(cs, type);
+    }
+}
+#endif
+
 /* CPUClass::reset() */
 static void mb_cpu_reset(CPUState *s)
 {
@@ -111,6 +127,11 @@ static void mb_cpu_initfn(Object *obj)
 
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
 
+#ifndef CONFIG_USER_ONLY
+    /* Inbound IRQ and FIR lines */
+    qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2);
+#endif
+
     if (tcg_enabled() && !tcg_initialized) {
         tcg_initialized = true;
         mb_tcg_init();
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index e1415f0..1df014e 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -48,6 +48,10 @@ typedef struct CPUMBState CPUMBState;
 /* MicroBlaze-specific interrupt pending bits.  */
 #define CPU_INTERRUPT_NMI       CPU_INTERRUPT_TGT_EXT_3
 
+/* Meanings of the MBCPU object's two inbound GPIO lines */
+#define MB_CPU_IRQ 0
+#define MB_CPU_FIR 1
+
 /* Register aliases. R0 - R15 */
 #define R_SP     1
 #define SR_PC    0
commit 83e6813a93e38976391b8c382c3375e3e188df3e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jan 13 10:26:16 2014 +0000

    target-arm: Switch ARMCPUInfo arrays to use terminator entries
    
    Switch the ARMCPUInfo arrays in cpu.c and cpu64.c to use a terminator
    entry rather than looping based on ARRAY_SIZE. The latter causes
    compile warnings on some versions of gcc if the configure options
    happen to result in an empty array.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Tested-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 408d207..c77a16c 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -980,6 +980,7 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "any",         .initfn = arm_any_initfn },
 #endif
 #endif
+    { .name = NULL }
 };
 
 static Property arm_cpu_properties[] = {
@@ -1043,11 +1044,13 @@ static const TypeInfo arm_cpu_type_info = {
 
 static void arm_cpu_register_types(void)
 {
-    int i;
+    const ARMCPUInfo *info = arm_cpus;
 
     type_register_static(&arm_cpu_type_info);
-    for (i = 0; i < ARRAY_SIZE(arm_cpus); i++) {
-        cpu_register(&arm_cpus[i]);
+
+    while (info->name) {
+        cpu_register(info);
+        info++;
     }
 }
 
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 60acd24..a639c2e 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -58,7 +58,7 @@ static const ARMCPUInfo aarch64_cpus[] = {
 #ifdef CONFIG_USER_ONLY
     { .name = "any",         .initfn = aarch64_any_initfn },
 #endif
-    { .name = NULL } /* TODO: drop when we support more CPUs */
+    { .name = NULL }
 };
 
 static void aarch64_cpu_initfn(Object *obj)
@@ -101,11 +101,6 @@ static void aarch64_cpu_register(const ARMCPUInfo *info)
         .class_init = info->class_init,
     };
 
-    /* TODO: drop when we support more CPUs - all entries will have name set */
-    if (!info->name) {
-        return;
-    }
-
     type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
     type_register(&type_info);
     g_free((void *)type_info.name);
@@ -124,11 +119,13 @@ static const TypeInfo aarch64_cpu_type_info = {
 
 static void aarch64_cpu_register_types(void)
 {
-    int i;
+    const ARMCPUInfo *info = aarch64_cpus;
 
     type_register_static(&aarch64_cpu_type_info);
-    for (i = 0; i < ARRAY_SIZE(aarch64_cpus); i++) {
-        aarch64_cpu_register(&aarch64_cpus[i]);
+
+    while (info->name) {
+        aarch64_cpu_register(info);
+        info++;
     }
 }
 
commit b54f18ba3415c731f0b069f6df56f529997fb74e
Merge: dd089c0 aa8dc04
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Mon Jan 13 13:20:49 2014 -0800

    Merge remote-tracking branch 'quintela/tags/migration/20140113' into staging
    
    migration.next for 20140113
    
    # gpg: Signature made Mon 13 Jan 2014 09:38:27 AM PST using RSA key ID 5872D723
    # gpg: Can't check signature: public key not found
    
    * quintela/tags/migration/20140113: (49 commits)
      migration: synchronize memory bitmap 64bits at a time
      ram: split function that synchronizes a range
      memory: syncronize kvm bitmap using bitmaps operations
      memory: move bitmap synchronization to its own function
      kvm: refactor start address calculation
      kvm: use directly cpu_physical_memory_* api for tracking dirty pages
      memory: unfold memory_region_test_and_clear()
      memory: split cpu_physical_memory_* functions to its own include
      memory: cpu_physical_memory_set_dirty_tracking() should return void
      memory: make cpu_physical_memory_reset_dirty() take a length parameter
      memory: s/dirty/clean/ in cpu_physical_memory_is_dirty()
      memory: cpu_physical_memory_clear_dirty_range() now uses bitmap operations
      memory: cpu_physical_memory_set_dirty_range() now uses bitmap operations
      memory: use find_next_bit() to find dirty bits
      memory: s/mask/clear/ cpu_physical_memory_mask_dirty_range
      memory: cpu_physical_memory_get_dirty() is used as returning a bool
      memory: make cpu_physical_memory_get_dirty() the main function
      memory: unfold cpu_physical_memory_set_dirty_flag()
      memory: unfold cpu_physical_memory_set_dirty() in its only user
      memory: unfold cpu_physical_memory_clear_dirty_flag() in its only user
      ...
    
    Message-id: 1389634834-24181-1-git-send-email-quintela at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit aa8dc044772ba156cbcf2174b5673cfa11f566a7
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Nov 6 11:33:05 2013 +0100

    migration: synchronize memory bitmap 64bits at a time
    
    We use the old code if the bitmaps are not aligned
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 2cd3d00..77912e7 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -50,6 +50,7 @@
 #include "exec/cpu-all.h"
 #include "exec/ram_addr.h"
 #include "hw/acpi/acpi.h"
+#include "qemu/host-utils.h"
 
 #ifdef DEBUG_ARCH_INIT
 #define DPRINTF(fmt, ...) \
@@ -376,15 +377,34 @@ static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
 static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
 {
     ram_addr_t addr;
-
-    for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(start + addr,
-                                          TARGET_PAGE_SIZE,
-                                          DIRTY_MEMORY_MIGRATION)) {
-            cpu_physical_memory_reset_dirty(start + addr,
-                                            TARGET_PAGE_SIZE,
-                                            DIRTY_MEMORY_MIGRATION);
-            migration_bitmap_set_dirty(start + addr);
+    unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
+
+    /* start address is aligned at the start of a word? */
+    if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
+        int k;
+        int nr = BITS_TO_LONGS(length >> TARGET_PAGE_BITS);
+        unsigned long *src = ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION];
+
+        for (k = page; k < page + nr; k++) {
+            if (src[k]) {
+                unsigned long new_dirty;
+                new_dirty = ~migration_bitmap[k];
+                migration_bitmap[k] |= src[k];
+                new_dirty &= src[k];
+                migration_dirty_pages += ctpopl(new_dirty);
+                src[k] = 0;
+            }
+        }
+    } else {
+        for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
+            if (cpu_physical_memory_get_dirty(start + addr,
+                                              TARGET_PAGE_SIZE,
+                                              DIRTY_MEMORY_MIGRATION)) {
+                cpu_physical_memory_reset_dirty(start + addr,
+                                                TARGET_PAGE_SIZE,
+                                                DIRTY_MEMORY_MIGRATION);
+                migration_bitmap_set_dirty(start + addr);
+            }
         }
     }
 }
commit 791fa2a2451799232d6bc0c29c0fbb13b5293eeb
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Nov 5 16:47:20 2013 +0100

    ram: split function that synchronizes a range
    
    This function is the only bit where we care about speed.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 0e8c8b5..2cd3d00 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -360,11 +360,10 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
     return (next - base) << TARGET_PAGE_BITS;
 }
 
-static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
-                                              ram_addr_t offset)
+static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
 {
     bool ret;
-    int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;
+    int nr = addr >> TARGET_PAGE_BITS;
 
     ret = test_and_set_bit(nr, migration_bitmap);
 
@@ -374,12 +373,28 @@ static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
     return ret;
 }
 
+static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
+{
+    ram_addr_t addr;
+
+    for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
+        if (cpu_physical_memory_get_dirty(start + addr,
+                                          TARGET_PAGE_SIZE,
+                                          DIRTY_MEMORY_MIGRATION)) {
+            cpu_physical_memory_reset_dirty(start + addr,
+                                            TARGET_PAGE_SIZE,
+                                            DIRTY_MEMORY_MIGRATION);
+            migration_bitmap_set_dirty(start + addr);
+        }
+    }
+}
+
+
 /* Needs iothread lock! */
 
 static void migration_bitmap_sync(void)
 {
     RAMBlock *block;
-    ram_addr_t addr;
     uint64_t num_dirty_pages_init = migration_dirty_pages;
     MigrationState *s = migrate_get_current();
     static int64_t start_time;
@@ -400,16 +415,7 @@ static void migration_bitmap_sync(void)
     address_space_sync_dirty_bitmap(&address_space_memory);
 
     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
-        for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-            if (cpu_physical_memory_get_dirty(block->mr->ram_addr + addr,
-                                              TARGET_PAGE_SIZE,
-                                              DIRTY_MEMORY_MIGRATION)) {
-                cpu_physical_memory_reset_dirty(block->mr->ram_addr + addr,
-                                                TARGET_PAGE_SIZE,
-                                                DIRTY_MEMORY_MIGRATION);
-                migration_bitmap_set_dirty(block->mr, addr);
-            }
-        }
+        migration_bitmap_sync_range(block->mr->ram_addr, block->length);
     }
     trace_migration_bitmap_sync_end(migration_dirty_pages
                                     - num_dirty_pages_init);
commit ae2810c4bb3b383176e8e1b33931b16c01483aab
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Nov 5 16:46:26 2013 +0100

    memory: syncronize kvm bitmap using bitmaps operations
    
    If bitmaps are aligned properly, use bitmap operations.  If they are
    not, just use old bit at a time code.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index c6736ed..33c8acc 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -83,29 +83,47 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
                                                           ram_addr_t start,
                                                           ram_addr_t pages)
 {
-    unsigned int i, j;
+    unsigned long i, j;
     unsigned long page_number, c;
     hwaddr addr;
     ram_addr_t ram_addr;
-    unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
+    unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
     unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
+    unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
 
-    /*
-     * bitmap-traveling is faster than memory-traveling (for addr...)
-     * especially when most of the memory is not dirty.
-     */
-    for (i = 0; i < len; i++) {
-        if (bitmap[i] != 0) {
-            c = leul_to_cpu(bitmap[i]);
-            do {
-                j = ffsl(c) - 1;
-                c &= ~(1ul << j);
-                page_number = (i * HOST_LONG_BITS + j) * hpratio;
-                addr = page_number * TARGET_PAGE_SIZE;
-                ram_addr = start + addr;
-                cpu_physical_memory_set_dirty_range(ram_addr,
-                                                    TARGET_PAGE_SIZE * hpratio);
-            } while (c != 0);
+    /* start address is aligned at the start of a word? */
+    if (((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) {
+        long k;
+        long nr = BITS_TO_LONGS(pages);
+
+        for (k = 0; k < nr; k++) {
+            if (bitmap[k]) {
+                unsigned long temp = leul_to_cpu(bitmap[k]);
+
+                ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION][page + k] |= temp;
+                ram_list.dirty_memory[DIRTY_MEMORY_VGA][page + k] |= temp;
+                ram_list.dirty_memory[DIRTY_MEMORY_CODE][page + k] |= temp;
+            }
+        }
+        xen_modified_memory(start, pages);
+    } else {
+        /*
+         * bitmap-traveling is faster than memory-traveling (for addr...)
+         * especially when most of the memory is not dirty.
+         */
+        for (i = 0; i < len; i++) {
+            if (bitmap[i] != 0) {
+                c = leul_to_cpu(bitmap[i]);
+                do {
+                    j = ffsl(c) - 1;
+                    c &= ~(1ul << j);
+                    page_number = (i * HOST_LONG_BITS + j) * hpratio;
+                    addr = page_number * TARGET_PAGE_SIZE;
+                    ram_addr = start + addr;
+                    cpu_physical_memory_set_dirty_range(ram_addr,
+                                       TARGET_PAGE_SIZE * hpratio);
+                } while (c != 0);
+            }
         }
     }
 }
commit 5ff7fb77b3cee8e26648e4fdccb23a77c2a6d3c6
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Nov 5 15:52:54 2013 +0100

    memory: move bitmap synchronization to its own function
    
    We want to have all the functions that handle directly the dirty
    bitmap near.  We will change it later.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index db977fb..c6736ed 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -79,6 +79,37 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
     xen_modified_memory(start, length);
 }
 
+static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
+                                                          ram_addr_t start,
+                                                          ram_addr_t pages)
+{
+    unsigned int i, j;
+    unsigned long page_number, c;
+    hwaddr addr;
+    ram_addr_t ram_addr;
+    unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
+    unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
+
+    /*
+     * bitmap-traveling is faster than memory-traveling (for addr...)
+     * especially when most of the memory is not dirty.
+     */
+    for (i = 0; i < len; i++) {
+        if (bitmap[i] != 0) {
+            c = leul_to_cpu(bitmap[i]);
+            do {
+                j = ffsl(c) - 1;
+                c &= ~(1ul << j);
+                page_number = (i * HOST_LONG_BITS + j) * hpratio;
+                addr = page_number * TARGET_PAGE_SIZE;
+                ram_addr = start + addr;
+                cpu_physical_memory_set_dirty_range(ram_addr,
+                                                    TARGET_PAGE_SIZE * hpratio);
+            } while (c != 0);
+        }
+    }
+}
+
 static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
                                                          ram_addr_t length,
                                                          unsigned client)
diff --git a/kvm-all.c b/kvm-all.c
index cb62ba4..0bfb060 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -380,33 +380,10 @@ static int kvm_set_migration_log(int enable)
 static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
                                          unsigned long *bitmap)
 {
-    unsigned int i, j;
-    unsigned long page_number, c;
-    hwaddr addr;
     ram_addr_t start = section->offset_within_region + section->mr->ram_addr;
-    ram_addr_t ram_addr;
-    unsigned int pages = int128_get64(section->size) / getpagesize();
-    unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
-    unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
+    ram_addr_t pages = int128_get64(section->size) / getpagesize();
 
-    /*
-     * bitmap-traveling is faster than memory-traveling (for addr...)
-     * especially when most of the memory is not dirty.
-     */
-    for (i = 0; i < len; i++) {
-        if (bitmap[i] != 0) {
-            c = leul_to_cpu(bitmap[i]);
-            do {
-                j = ffsl(c) - 1;
-                c &= ~(1ul << j);
-                page_number = (i * HOST_LONG_BITS + j) * hpratio;
-                addr = page_number * TARGET_PAGE_SIZE;
-                ram_addr = start + addr;
-                cpu_physical_memory_set_dirty_range(ram_addr,
-                                                    TARGET_PAGE_SIZE * hpratio);
-            } while (c != 0);
-        }
-    }
+    cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages);
     return 0;
 }
 
commit c9dd46fc0d64d9f314aa3c220d4aff9d01ab778e
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Nov 5 15:45:46 2013 +0100

    kvm: refactor start address calculation
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 308dfba..cb62ba4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -382,7 +382,8 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
 {
     unsigned int i, j;
     unsigned long page_number, c;
-    hwaddr addr, addr1;
+    hwaddr addr;
+    ram_addr_t start = section->offset_within_region + section->mr->ram_addr;
     ram_addr_t ram_addr;
     unsigned int pages = int128_get64(section->size) / getpagesize();
     unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
@@ -399,9 +400,8 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
                 j = ffsl(c) - 1;
                 c &= ~(1ul << j);
                 page_number = (i * HOST_LONG_BITS + j) * hpratio;
-                addr1 = page_number * TARGET_PAGE_SIZE;
-                addr = section->offset_within_region + addr1;
-                ram_addr = section->mr->ram_addr + addr;
+                addr = page_number * TARGET_PAGE_SIZE;
+                ram_addr = start + addr;
                 cpu_physical_memory_set_dirty_range(ram_addr,
                                                     TARGET_PAGE_SIZE * hpratio);
             } while (c != 0);
commit 747afd5bcdc90f608c75d95f8a629a9cfc838c57
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Nov 4 12:59:02 2013 +0100

    kvm: use directly cpu_physical_memory_* api for tracking dirty pages
    
    Performance is important in this function, and we want to optimize even further.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 3937754..308dfba 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -31,6 +31,7 @@
 #include "sysemu/kvm.h"
 #include "qemu/bswap.h"
 #include "exec/memory.h"
+#include "exec/ram_addr.h"
 #include "exec/address-spaces.h"
 #include "qemu/event_notifier.h"
 #include "trace.h"
@@ -382,6 +383,7 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
     unsigned int i, j;
     unsigned long page_number, c;
     hwaddr addr, addr1;
+    ram_addr_t ram_addr;
     unsigned int pages = int128_get64(section->size) / getpagesize();
     unsigned int len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
     unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
@@ -399,8 +401,9 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
                 page_number = (i * HOST_LONG_BITS + j) * hpratio;
                 addr1 = page_number * TARGET_PAGE_SIZE;
                 addr = section->offset_within_region + addr1;
-                memory_region_set_dirty(section->mr, addr,
-                                        TARGET_PAGE_SIZE * hpratio);
+                ram_addr = section->mr->ram_addr + addr;
+                cpu_physical_memory_set_dirty_range(ram_addr,
+                                                    TARGET_PAGE_SIZE * hpratio);
             } while (c != 0);
         }
     }
commit 12291ec18fdce3c1973c172f5a942a1bd26b9a5f
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Oct 14 17:14:47 2013 +0200

    memory: unfold memory_region_test_and_clear()
    
    We are going to update the bitmap directly
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e0acbc5..0e8c8b5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -48,6 +48,7 @@
 #include "qmp-commands.h"
 #include "trace.h"
 #include "exec/cpu-all.h"
+#include "exec/ram_addr.h"
 #include "hw/acpi/acpi.h"
 
 #ifdef DEBUG_ARCH_INIT
@@ -400,9 +401,12 @@ static void migration_bitmap_sync(void)
 
     QTAILQ_FOREACH(block, &ram_list.blocks, next) {
         for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
-            if (memory_region_test_and_clear_dirty(block->mr,
-                                                   addr, TARGET_PAGE_SIZE,
-                                                   DIRTY_MEMORY_MIGRATION)) {
+            if (cpu_physical_memory_get_dirty(block->mr->ram_addr + addr,
+                                              TARGET_PAGE_SIZE,
+                                              DIRTY_MEMORY_MIGRATION)) {
+                cpu_physical_memory_reset_dirty(block->mr->ram_addr + addr,
+                                                TARGET_PAGE_SIZE,
+                                                DIRTY_MEMORY_MIGRATION);
                 migration_bitmap_set_dirty(block->mr, addr);
             }
         }
commit 220c3ebddbd1ac289ae7fc64733c9501b3921d94
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Oct 14 17:13:59 2013 +0200

    memory: split cpu_physical_memory_* functions to its own include
    
    All the functions that use ram_addr_t should be here.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/cputlb.c b/cputlb.c
index 0ac8d90..b533f3f 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -26,6 +26,7 @@
 #include "exec/cputlb.h"
 
 #include "exec/memory-internal.h"
+#include "exec/ram_addr.h"
 
 //#define DEBUG_TLB
 //#define DEBUG_TLB_CHECK
diff --git a/exec.c b/exec.c
index 514d6a0..b387d28 100644
--- a/exec.c
+++ b/exec.c
@@ -50,6 +50,7 @@
 #include "translate-all.h"
 
 #include "exec/memory-internal.h"
+#include "exec/ram_addr.h"
 #include "qemu/cache-utils.h"
 
 #include "qemu/range.h"
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index cb2249f..25c43c0 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -20,9 +20,6 @@
 #define MEMORY_INTERNAL_H
 
 #ifndef CONFIG_USER_ONLY
-#include "hw/xen/xen.h"
-
-
 typedef struct AddressSpaceDispatch AddressSpaceDispatch;
 
 void address_space_init_dispatch(AddressSpace *as);
@@ -33,78 +30,5 @@ extern const MemoryRegionOps unassigned_mem_ops;
 bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                 unsigned size, bool is_write);
 
-ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
-                                   MemoryRegion *mr);
-ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
-void *qemu_get_ram_ptr(ram_addr_t addr);
-void qemu_ram_free(ram_addr_t addr);
-void qemu_ram_free_from_ptr(ram_addr_t addr);
-
-static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
-                                                 ram_addr_t length,
-                                                 unsigned client)
-{
-    unsigned long end, page, next;
-
-    assert(client < DIRTY_MEMORY_NUM);
-
-    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
-    page = start >> TARGET_PAGE_BITS;
-    next = find_next_bit(ram_list.dirty_memory[client], end, page);
-
-    return next < end;
-}
-
-static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
-                                                      unsigned client)
-{
-    return cpu_physical_memory_get_dirty(addr, 1, client);
-}
-
-static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
-{
-    bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA);
-    bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE);
-    bool migration =
-        cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
-    return !(vga && code && migration);
-}
-
-static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
-                                                      unsigned client)
-{
-    assert(client < DIRTY_MEMORY_NUM);
-    set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
-}
-
-static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
-                                                       ram_addr_t length)
-{
-    unsigned long end, page;
-
-    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
-    page = start >> TARGET_PAGE_BITS;
-    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page);
-    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page);
-    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page);
-    xen_modified_memory(start, length);
-}
-
-static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
-                                                         ram_addr_t length,
-                                                         unsigned client)
-{
-    unsigned long end, page;
-
-    assert(client < DIRTY_MEMORY_NUM);
-    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
-    page = start >> TARGET_PAGE_BITS;
-    bitmap_clear(ram_list.dirty_memory[client], page, end - page);
-}
-
-void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
-                                     unsigned client);
-
 #endif
-
 #endif
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
new file mode 100644
index 0000000..db977fb
--- /dev/null
+++ b/include/exec/ram_addr.h
@@ -0,0 +1,98 @@
+/*
+ * Declarations for cpu physical memory functions
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ *
+ */
+
+/*
+ * This header is for use by exec.c and memory.c ONLY.  Do not include it.
+ * The functions declared here will be removed soon.
+ */
+
+#ifndef RAM_ADDR_H
+#define RAM_ADDR_H
+
+#ifndef CONFIG_USER_ONLY
+#include "hw/xen/xen.h"
+
+ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
+                                   MemoryRegion *mr);
+ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr);
+void *qemu_get_ram_ptr(ram_addr_t addr);
+void qemu_ram_free(ram_addr_t addr);
+void qemu_ram_free_from_ptr(ram_addr_t addr);
+
+static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
+                                                 ram_addr_t length,
+                                                 unsigned client)
+{
+    unsigned long end, page, next;
+
+    assert(client < DIRTY_MEMORY_NUM);
+
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    next = find_next_bit(ram_list.dirty_memory[client], end, page);
+
+    return next < end;
+}
+
+static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
+                                                      unsigned client)
+{
+    return cpu_physical_memory_get_dirty(addr, 1, client);
+}
+
+static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
+{
+    bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA);
+    bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE);
+    bool migration =
+        cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
+    return !(vga && code && migration);
+}
+
+static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
+                                                      unsigned client)
+{
+    assert(client < DIRTY_MEMORY_NUM);
+    set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
+}
+
+static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
+                                                       ram_addr_t length)
+{
+    unsigned long end, page;
+
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page);
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page);
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page);
+    xen_modified_memory(start, length);
+}
+
+static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
+                                                         ram_addr_t length,
+                                                         unsigned client)
+{
+    unsigned long end, page;
+
+    assert(client < DIRTY_MEMORY_NUM);
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    bitmap_clear(ram_list.dirty_memory[client], page, end - page);
+}
+
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
+                                     unsigned client);
+
+#endif
+#endif
diff --git a/memory.c b/memory.c
index c010296..59ecc28 100644
--- a/memory.c
+++ b/memory.c
@@ -22,6 +22,7 @@
 #include <assert.h>
 
 #include "exec/memory-internal.h"
+#include "exec/ram_addr.h"
 
 //#define DEBUG_UNASSIGNED
 
commit 981fdf2353d5e708adbe5227260d5e46eececc05
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Oct 10 11:54:09 2013 +0200

    memory: cpu_physical_memory_set_dirty_tracking() should return void
    
    Result was always 0, and not used anywhere.  Once there, use bool type
    for the parameter.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index c71f2d5..514d6a0 100644
--- a/exec.c
+++ b/exec.c
@@ -57,7 +57,7 @@
 //#define DEBUG_SUBPAGE
 
 #if !defined(CONFIG_USER_ONLY)
-static int in_migration;
+static bool in_migration;
 
 RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
 
@@ -752,11 +752,9 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
     }
 }
 
-static int cpu_physical_memory_set_dirty_tracking(int enable)
+static void cpu_physical_memory_set_dirty_tracking(bool enable)
 {
-    int ret = 0;
     in_migration = enable;
-    return ret;
 }
 
 hwaddr memory_region_section_get_iotlb(CPUArchState *env,
@@ -1798,12 +1796,12 @@ static void tcg_commit(MemoryListener *listener)
 
 static void core_log_global_start(MemoryListener *listener)
 {
-    cpu_physical_memory_set_dirty_tracking(1);
+    cpu_physical_memory_set_dirty_tracking(true);
 }
 
 static void core_log_global_stop(MemoryListener *listener)
 {
-    cpu_physical_memory_set_dirty_tracking(0);
+    cpu_physical_memory_set_dirty_tracking(false);
 }
 
 static MemoryListener core_memory_listener = {
commit a2f4d5bef2cfde557d76fc45a40d2c89b6bed4e4
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Oct 10 11:49:53 2013 +0200

    memory: make cpu_physical_memory_reset_dirty() take a length parameter
    
    We have an end parameter in all the callers, and this make it coherent
    with the rest of cpu_physical_memory_* functions, that also take a
    length parameter.
    
    Once here, move the start/end calculation to
    tlb_reset_dirty_range_all() as we don't need it here anymore.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/cputlb.c b/cputlb.c
index eab91d7..0ac8d90 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -112,8 +112,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr)
    can be detected */
 void tlb_protect_code(ram_addr_t ram_addr)
 {
-    cpu_physical_memory_reset_dirty(ram_addr,
-                                    ram_addr + TARGET_PAGE_SIZE,
+    cpu_physical_memory_reset_dirty(ram_addr, TARGET_PAGE_SIZE,
                                     DIRTY_MEMORY_CODE);
 }
 
diff --git a/exec.c b/exec.c
index 47add21..c71f2d5 100644
--- a/exec.c
+++ b/exec.c
@@ -724,11 +724,14 @@ found:
     return block;
 }
 
-static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
-                                      uintptr_t length)
+static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length)
 {
-    RAMBlock *block;
     ram_addr_t start1;
+    RAMBlock *block;
+    ram_addr_t end;
+
+    end = TARGET_PAGE_ALIGN(start + length);
+    start &= TARGET_PAGE_MASK;
 
     block = qemu_get_ram_block(start);
     assert(block == qemu_get_ram_block(end - 1));
@@ -737,21 +740,15 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
 }
 
 /* Note: start and end must be within the same ram block.  */
-void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
                                      unsigned client)
 {
-    uintptr_t length;
-
-    start &= TARGET_PAGE_MASK;
-    end = TARGET_PAGE_ALIGN(end);
-
-    length = end - start;
     if (length == 0)
         return;
     cpu_physical_memory_clear_dirty_range(start, length, client);
 
     if (tcg_enabled()) {
-        tlb_reset_dirty_range_all(start, end, length);
+        tlb_reset_dirty_range_all(start, length);
     }
 }
 
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 771b23f..cb2249f 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -102,7 +102,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
     bitmap_clear(ram_list.dirty_memory[client], page, end - page);
 }
 
-void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
+void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length,
                                      unsigned client);
 
 #endif
diff --git a/memory.c b/memory.c
index a490cbd..c010296 100644
--- a/memory.c
+++ b/memory.c
@@ -1191,9 +1191,7 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
     assert(mr->terminates);
     ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client);
     if (ret) {
-        cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
-                                        mr->ram_addr + addr + size,
-                                        client);
+        cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client);
     }
     return ret;
 }
@@ -1239,9 +1237,7 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
                                hwaddr size, unsigned client)
 {
     assert(mr->terminates);
-    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
-                                    mr->ram_addr + addr + size,
-                                    client);
+    cpu_physical_memory_reset_dirty(mr->ram_addr + addr, size, client);
 }
 
 void *memory_region_get_ram_ptr(MemoryRegion *mr)
commit a2cd8c852d2d8c2a084b68b2470f214d6726f6d2
Author: Juan Quintela <quintela at redhat.com>
Date:   Thu Oct 10 11:20:22 2013 +0200

    memory: s/dirty/clean/ in cpu_physical_memory_is_dirty()
    
    All uses except one really want the other meaning.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/cputlb.c b/cputlb.c
index ec21405..eab91d7 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -284,7 +284,8 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr,
             /* Write access calls the I/O callback.  */
             te->addr_write = address | TLB_MMIO;
         } else if (memory_region_is_ram(section->mr)
-                   && !cpu_physical_memory_is_dirty(section->mr->ram_addr + xlat)) {
+                   && cpu_physical_memory_is_clean(section->mr->ram_addr
+                                                   + xlat)) {
             te->addr_write = address | TLB_NOTDIRTY;
         } else {
             te->addr_write = address;
diff --git a/exec.c b/exec.c
index 9267596..47add21 100644
--- a/exec.c
+++ b/exec.c
@@ -1514,7 +1514,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
     cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_VGA);
     /* we remove the notdirty callback only if the code has been
        flushed */
-    if (cpu_physical_memory_is_dirty(ram_addr)) {
+    if (!cpu_physical_memory_is_clean(ram_addr)) {
         CPUArchState *env = current_cpu->env_ptr;
         tlb_set_dirty(env, env->mem_io_vaddr);
     }
@@ -1917,7 +1917,7 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
 static void invalidate_and_set_dirty(hwaddr addr,
                                      hwaddr length)
 {
-    if (!cpu_physical_memory_is_dirty(addr)) {
+    if (cpu_physical_memory_is_clean(addr)) {
         /* invalidate code */
         tb_invalidate_phys_page_range(addr, addr + length, 0);
         /* set dirty bit */
@@ -2533,7 +2533,7 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
         stl_p(ptr, val);
 
         if (unlikely(in_migration)) {
-            if (!cpu_physical_memory_is_dirty(addr1)) {
+            if (cpu_physical_memory_is_clean(addr1)) {
                 /* invalidate code */
                 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
                 /* set dirty bit */
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index e2f55ea..771b23f 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -61,14 +61,13 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
     return cpu_physical_memory_get_dirty(addr, 1, client);
 }
 
-/* read dirty bit (return 0 or 1) */
-static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr)
+static inline bool cpu_physical_memory_is_clean(ram_addr_t addr)
 {
     bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA);
     bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE);
     bool migration =
         cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
-    return vga && code && migration;
+    return !(vga && code && migration);
 }
 
 static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
commit a461e389f489e72cdc770ff887512c2c9109bc43
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 9 12:30:35 2013 +0200

    memory: cpu_physical_memory_clear_dirty_range() now uses bitmap operations
    
    We were clearing a range of bits, so use bitmap_clear().
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 4906cdf..e2f55ea 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -95,14 +95,12 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
                                                          ram_addr_t length,
                                                          unsigned client)
 {
-    ram_addr_t addr, end;
+    unsigned long end, page;
 
     assert(client < DIRTY_MEMORY_NUM);
-    end = TARGET_PAGE_ALIGN(start + length);
-    start &= TARGET_PAGE_MASK;
-    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
-    }
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    bitmap_clear(ram_list.dirty_memory[client], page, end - page);
 }
 
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
commit 5b9a3a5f77e3458af6c1bb0654ee0f32936a5594
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 9 12:26:23 2013 +0200

    memory: cpu_physical_memory_set_dirty_range() now uses bitmap operations
    
    We were setting a range of bits, so use bitmap_set().
    
    Note: xen has always been wrong, and should have used start instead
    of addr from the beginning.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index b017c2e..4906cdf 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -81,19 +81,14 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
                                                        ram_addr_t length)
 {
-    ram_addr_t addr, end;
+    unsigned long end, page;
 
-    end = TARGET_PAGE_ALIGN(start + length);
-    start &= TARGET_PAGE_MASK;
-    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        set_bit(addr >> TARGET_PAGE_BITS,
-                ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]);
-        set_bit(addr >> TARGET_PAGE_BITS,
-                ram_list.dirty_memory[DIRTY_MEMORY_VGA]);
-        set_bit(addr >> TARGET_PAGE_BITS,
-                ram_list.dirty_memory[DIRTY_MEMORY_CODE]);
-    }
-    xen_modified_memory(addr, length);
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page);
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page);
+    bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page);
+    xen_modified_memory(start, length);
 }
 
 static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
commit 1bafff0c7cb99972fd243464632eca0780c6a8f1
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 9 12:15:06 2013 +0200

    memory: use find_next_bit() to find dirty bits
    
    This operation is way faster than doing it bit by bit.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index c04a92a..b017c2e 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -44,19 +44,15 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
                                                  ram_addr_t length,
                                                  unsigned client)
 {
-    ram_addr_t addr, end;
+    unsigned long end, page, next;
 
     assert(client < DIRTY_MEMORY_NUM);
 
-    end = TARGET_PAGE_ALIGN(start + length);
-    start &= TARGET_PAGE_MASK;
-    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        if (test_bit(addr >> TARGET_PAGE_BITS,
-                     ram_list.dirty_memory[client])) {
-            return true;
-        }
-    }
-    return false;
+    end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
+    page = start >> TARGET_PAGE_BITS;
+    next = find_next_bit(ram_list.dirty_memory[client], end, page);
+
+    return next < end;
 }
 
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
commit ace694cccccf343852d9f0b34171ad475e248bbf
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 9 10:36:56 2013 +0200

    memory: s/mask/clear/ cpu_physical_memory_mask_dirty_range
    
    Now all functions use the same wording that bitops/bitmap operations
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index 028eee4..9267596 100644
--- a/exec.c
+++ b/exec.c
@@ -748,7 +748,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
     length = end - start;
     if (length == 0)
         return;
-    cpu_physical_memory_mask_dirty_range(start, length, client);
+    cpu_physical_memory_clear_dirty_range(start, length, client);
 
     if (tcg_enabled()) {
         tlb_reset_dirty_range_all(start, end, length);
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index fa28fc6..c04a92a 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -100,9 +100,9 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
     xen_modified_memory(addr, length);
 }
 
-static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
-                                                        ram_addr_t length,
-                                                        unsigned client)
+static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
+                                                         ram_addr_t length,
+                                                         unsigned client)
 {
     ram_addr_t addr, end;
 
commit 94833c896d2d339571a66542f2715b1897d70fa7
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 20:40:55 2013 +0200

    memory: cpu_physical_memory_get_dirty() is used as returning a bool
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index edca8a8..fa28fc6 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -40,11 +40,10 @@ void *qemu_get_ram_ptr(ram_addr_t addr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
-static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
-                                                ram_addr_t length,
-                                                unsigned client)
+static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
+                                                 ram_addr_t length,
+                                                 unsigned client)
 {
-    int ret = 0;
     ram_addr_t addr, end;
 
     assert(client < DIRTY_MEMORY_NUM);
@@ -52,10 +51,12 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        ret |= test_bit(addr >> TARGET_PAGE_BITS,
-                        ram_list.dirty_memory[client]);
+        if (test_bit(addr >> TARGET_PAGE_BITS,
+                     ram_list.dirty_memory[client])) {
+            return true;
+        }
     }
-    return ret;
+    return false;
 }
 
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
commit 9f2c43e41a13605d3ab1e37ba433aa669652fb6b
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 20:35:39 2013 +0200

    memory: make cpu_physical_memory_get_dirty() the main function
    
    And make cpu_physical_memory_get_dirty_flag() to use it.  It used to
    be the other way around.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index b99617a..edca8a8 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -40,11 +40,28 @@ void *qemu_get_ram_ptr(ram_addr_t addr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
+static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
+                                                ram_addr_t length,
+                                                unsigned client)
+{
+    int ret = 0;
+    ram_addr_t addr, end;
+
+    assert(client < DIRTY_MEMORY_NUM);
+
+    end = TARGET_PAGE_ALIGN(start + length);
+    start &= TARGET_PAGE_MASK;
+    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+        ret |= test_bit(addr >> TARGET_PAGE_BITS,
+                        ram_list.dirty_memory[client]);
+    }
+    return ret;
+}
+
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
-    assert(client < DIRTY_MEMORY_NUM);
-    return test_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
+    return cpu_physical_memory_get_dirty(addr, 1, client);
 }
 
 /* read dirty bit (return 0 or 1) */
@@ -57,21 +74,6 @@ static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr)
     return vga && code && migration;
 }
 
-static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
-                                                ram_addr_t length,
-                                                unsigned client)
-{
-    int ret = 0;
-    ram_addr_t addr, end;
-
-    end = TARGET_PAGE_ALIGN(start + length);
-    start &= TARGET_PAGE_MASK;
-    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        ret |= cpu_physical_memory_get_dirty_flag(addr, client);
-    }
-    return ret;
-}
-
 static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
commit c1427a3f84c42d5159d10927700eafc9b653d68f
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 20:27:58 2013 +0200

    memory: unfold cpu_physical_memory_set_dirty_flag()
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 9d34434..b99617a 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -87,9 +87,12 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
-        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA);
-        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
+        set_bit(addr >> TARGET_PAGE_BITS,
+                ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]);
+        set_bit(addr >> TARGET_PAGE_BITS,
+                ram_list.dirty_memory[DIRTY_MEMORY_VGA]);
+        set_bit(addr >> TARGET_PAGE_BITS,
+                ram_list.dirty_memory[DIRTY_MEMORY_CODE]);
     }
     xen_modified_memory(addr, length);
 }
commit 4f13bb80a2dc1bb851b43da6dd9117473772b197
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 20:25:16 2013 +0200

    memory: unfold cpu_physical_memory_set_dirty() in its only user
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 2f6610a..9d34434 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -79,13 +79,6 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
     set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
 }
 
-static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
-{
-    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
-    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA);
-    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
-}
-
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
                                                        ram_addr_t length)
 {
@@ -94,7 +87,9 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty(addr);
+        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
+        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA);
+        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
     }
     xen_modified_memory(addr, length);
 }
commit 86a49582dbe66d59a9366d2f002f0d6af965ecb8
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 20:21:10 2013 +0200

    memory: unfold cpu_physical_memory_clear_dirty_flag() in its only user
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 6fb1b64..2f6610a 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -86,13 +86,6 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
     cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
 }
 
-static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
-                                                       unsigned client)
-{
-    assert(client < DIRTY_MEMORY_NUM);
-    clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
-}
-
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
                                                        ram_addr_t length)
 {
@@ -112,10 +105,11 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
 {
     ram_addr_t addr, end;
 
+    assert(client < DIRTY_MEMORY_NUM);
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_clear_dirty_flag(addr, client);
+        clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
     }
 }
 
commit 1ab4c8ceaa5ec55af9bb25e88e46d461a8550280
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 16:14:39 2013 +0200

    memory: split dirty bitmap into three
    
    After all the previous patches, spliting the bitmap gets direct.
    
    Note: For some reason, I have to move DIRTY_MEMORY_* definitions to
    the beginning of memory.h to make compilation work.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index db369dc..028eee4 100644
--- a/exec.c
+++ b/exec.c
@@ -1277,9 +1277,12 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
     new_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
 
     if (new_ram_size > old_ram_size) {
-        ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, new_ram_size);
-        memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
-           0, size >> TARGET_PAGE_BITS);
+        int i;
+        for (i = 0; i < DIRTY_MEMORY_NUM; i++) {
+            ram_list.dirty_memory[i] =
+                bitmap_zero_extend(ram_list.dirty_memory[i],
+                                   old_ram_size, new_ram_size);
+       }
     }
     cpu_physical_memory_set_dirty_range(new_block->offset, size);
 
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index b6998f0..4cb4b4a 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -21,6 +21,7 @@
 
 #include "qemu-common.h"
 #include "exec/cpu-common.h"
+#include "exec/memory.h"
 #include "qemu/thread.h"
 #include "qom/cpu.h"
 
@@ -459,7 +460,7 @@ typedef struct RAMBlock {
 typedef struct RAMList {
     QemuMutex mutex;
     /* Protected by the iothread lock.  */
-    uint8_t *phys_dirty;
+    unsigned long *dirty_memory[DIRTY_MEMORY_NUM];
     RAMBlock *mru_block;
     /* Protected by the ramlist lock.  */
     QTAILQ_HEAD(, RAMBlock) blocks;
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 666490c..6fb1b64 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -44,7 +44,7 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
     assert(client < DIRTY_MEMORY_NUM);
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client);
+    return test_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
 }
 
 /* read dirty bit (return 0 or 1) */
@@ -76,7 +76,7 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
     assert(client < DIRTY_MEMORY_NUM);
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client);
+    set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
@@ -89,11 +89,8 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
                                                        unsigned client)
 {
-    int mask = ~(1 << client);
-
     assert(client < DIRTY_MEMORY_NUM);
-
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
+    clear_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]);
 }
 
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
diff --git a/include/exec/memory.h b/include/exec/memory.h
index d5e9d58..296d6ab 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -16,6 +16,11 @@
 
 #ifndef CONFIG_USER_ONLY
 
+#define DIRTY_MEMORY_VGA       0
+#define DIRTY_MEMORY_CODE      1
+#define DIRTY_MEMORY_MIGRATION 2
+#define DIRTY_MEMORY_NUM       3        /* num of dirty bits */
+
 #include <stdint.h>
 #include <stdbool.h>
 #include "qemu-common.h"
@@ -33,11 +38,6 @@
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
 
-#define DIRTY_MEMORY_VGA       0
-#define DIRTY_MEMORY_CODE      1
-#define DIRTY_MEMORY_MIGRATION 2
-#define DIRTY_MEMORY_NUM       3        /* num of dirty bits */
-
 struct MemoryRegionMmio {
     CPUReadMemoryFunc *read[3];
     CPUWriteMemoryFunc *write[3];
commit 164590a60fd685399da259ac41b338d9a0b9d6c0
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 16:12:17 2013 +0200

    bitmap: Add bitmap_zero_extend operation
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
index afdd257..1babd5d 100644
--- a/include/qemu/bitmap.h
+++ b/include/qemu/bitmap.h
@@ -220,4 +220,13 @@ unsigned long bitmap_find_next_zero_area(unsigned long *map,
                                          unsigned long nr,
                                          unsigned long align_mask);
 
+static inline unsigned long *bitmap_zero_extend(unsigned long *old,
+                                                long old_nbits, long new_nbits)
+{
+    long new_len = BITS_TO_LONGS(new_nbits) * sizeof(unsigned long);
+    unsigned long *new = g_realloc(old, new_len);
+    bitmap_clear(new, old_nbits, new_nbits - old_nbits);
+    return new;
+}
+
 #endif /* BITMAP_H */
commit e8a97cafc4108fa964807eb9cbce7eda698f99bb
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 15:50:55 2013 +0200

    memory: cpu_physical_memory_clear_dirty_flag() result is never used
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index d09d6d8..666490c 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -86,14 +86,14 @@ static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
     cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
 }
 
-static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
+static inline void cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
                                                        unsigned client)
 {
     int mask = ~(1 << client);
 
     assert(client < DIRTY_MEMORY_NUM);
 
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
 }
 
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
commit 2152f5ca782e51a4d05a1f7d9bfa83286323cbc9
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 13:52:02 2013 +0200

    memory: only resize dirty bitmap when memory size increases
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index 82aca4a..db369dc 100644
--- a/exec.c
+++ b/exec.c
@@ -1211,6 +1211,9 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                    MemoryRegion *mr)
 {
     RAMBlock *block, *new_block;
+    ram_addr_t old_ram_size, new_ram_size;
+
+    old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
 
     size = TARGET_PAGE_ALIGN(size);
     new_block = g_malloc0(sizeof(*new_block));
@@ -1271,10 +1274,13 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
     ram_list.version++;
     qemu_mutex_unlock_ramlist();
 
-    ram_list.phys_dirty = g_realloc(ram_list.phys_dirty,
-                                       last_ram_offset() >> TARGET_PAGE_BITS);
-    memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
+    new_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
+
+    if (new_ram_size > old_ram_size) {
+        ram_list.phys_dirty = g_realloc(ram_list.phys_dirty, new_ram_size);
+        memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0, size >> TARGET_PAGE_BITS);
+    }
     cpu_physical_memory_set_dirty_range(new_block->offset, size);
 
     qemu_ram_setup_dump(new_block->host, size);
commit 7a5b558c9d061814f34d9b95d70d17ef75037937
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 13:29:11 2013 +0200

    memory: make sure that client is always inside range
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index b58010f..d09d6d8 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -43,6 +43,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
+    assert(client < DIRTY_MEMORY_NUM);
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client);
 }
 
@@ -74,6 +75,7 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
 static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
                                                       unsigned client)
 {
+    assert(client < DIRTY_MEMORY_NUM);
     ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client);
 }
 
@@ -89,6 +91,8 @@ static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
 {
     int mask = ~(1 << client);
 
+    assert(client < DIRTY_MEMORY_NUM);
+
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
 }
 
commit 5adca7ace9b80bf594e4c52c0d5b23573cba3639
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 13:26:29 2013 +0200

    memory: use bit 2 for migration
    
    For historical reasons it was bit 3.  Once there, create a constant to
    know the number of clients.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory.h b/include/exec/memory.h
index b8e76f4..d5e9d58 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -35,7 +35,8 @@ typedef struct MemoryRegionMmio MemoryRegionMmio;
 
 #define DIRTY_MEMORY_VGA       0
 #define DIRTY_MEMORY_CODE      1
-#define DIRTY_MEMORY_MIGRATION 3
+#define DIRTY_MEMORY_MIGRATION 2
+#define DIRTY_MEMORY_NUM       3        /* num of dirty bits */
 
 struct MemoryRegionMmio {
     CPUReadMemoryFunc *read[3];
commit 52159192919469b424b54c167312e53d5a62d233
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 12:44:04 2013 +0200

    memory: cpu_physical_memory_mask_dirty_range() always clears a single flag
    
    Document it
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/cputlb.c b/cputlb.c
index c545e4c..ec21405 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -114,7 +114,7 @@ void tlb_protect_code(ram_addr_t ram_addr)
 {
     cpu_physical_memory_reset_dirty(ram_addr,
                                     ram_addr + TARGET_PAGE_SIZE,
-                                    CODE_DIRTY_FLAG);
+                                    DIRTY_MEMORY_CODE);
 }
 
 /* update the TLB so that writes in physical page 'phys_addr' are no longer
@@ -122,7 +122,7 @@ void tlb_protect_code(ram_addr_t ram_addr)
 void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
                              target_ulong vaddr)
 {
-    cpu_physical_memory_set_dirty_flag(ram_addr, CODE_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_CODE);
 }
 
 static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
diff --git a/exec.c b/exec.c
index f215960..82aca4a 100644
--- a/exec.c
+++ b/exec.c
@@ -738,7 +738,7 @@ static void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t end,
 
 /* Note: start and end must be within the same ram block.  */
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
-                                     int dirty_flags)
+                                     unsigned client)
 {
     uintptr_t length;
 
@@ -748,7 +748,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
     length = end - start;
     if (length == 0)
         return;
-    cpu_physical_memory_mask_dirty_range(start, length, dirty_flags);
+    cpu_physical_memory_mask_dirty_range(start, length, client);
 
     if (tcg_enabled()) {
         tlb_reset_dirty_range_all(start, end, length);
@@ -1485,7 +1485,7 @@ found:
 static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
                                uint64_t val, unsigned size)
 {
-    if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) {
+    if (!cpu_physical_memory_get_dirty_flag(ram_addr, DIRTY_MEMORY_CODE)) {
         tb_invalidate_phys_page_fast(ram_addr, size);
     }
     switch (size) {
@@ -1501,8 +1501,8 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
     default:
         abort();
     }
-    cpu_physical_memory_set_dirty_flag(ram_addr, MIGRATION_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flag(ram_addr, VGA_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_MIGRATION);
+    cpu_physical_memory_set_dirty_flag(ram_addr, DIRTY_MEMORY_VGA);
     /* we remove the notdirty callback only if the code has been
        flushed */
     if (cpu_physical_memory_is_dirty(ram_addr)) {
@@ -1912,8 +1912,8 @@ static void invalidate_and_set_dirty(hwaddr addr,
         /* invalidate code */
         tb_invalidate_phys_page_range(addr, addr + length, 0);
         /* set dirty bit */
-        cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG);
-        cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
+        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA);
+        cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
     }
     xen_modified_memory(addr, length);
 }
@@ -2528,8 +2528,9 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
                 /* invalidate code */
                 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
                 /* set dirty bit */
-                cpu_physical_memory_set_dirty_flag(addr1, MIGRATION_DIRTY_FLAG);
-                cpu_physical_memory_set_dirty_flag(addr1, VGA_DIRTY_FLAG);
+                cpu_physical_memory_set_dirty_flag(addr1,
+                                                   DIRTY_MEMORY_MIGRATION);
+                cpu_physical_memory_set_dirty_flag(addr1, DIRTY_MEMORY_VGA);
             }
         }
     }
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 681d63b..b58010f 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -40,29 +40,25 @@ void *qemu_get_ram_ptr(ram_addr_t addr);
 void qemu_ram_free(ram_addr_t addr);
 void qemu_ram_free_from_ptr(ram_addr_t addr);
 
-#define VGA_DIRTY_FLAG       0x01
-#define CODE_DIRTY_FLAG      0x02
-#define MIGRATION_DIRTY_FLAG 0x08
-
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
-                                                      int dirty_flag)
+                                                      unsigned client)
 {
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flag;
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & (1 << client);
 }
 
 /* read dirty bit (return 0 or 1) */
 static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
-    bool vga = cpu_physical_memory_get_dirty_flag(addr, VGA_DIRTY_FLAG);
-    bool code = cpu_physical_memory_get_dirty_flag(addr, CODE_DIRTY_FLAG);
+    bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA);
+    bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE);
     bool migration =
-        cpu_physical_memory_get_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
+        cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
     return vga && code && migration;
 }
 
 static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
                                                 ram_addr_t length,
-                                                int dirty_flag)
+                                                unsigned client)
 {
     int ret = 0;
     ram_addr_t addr, end;
@@ -70,28 +66,28 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        ret |= cpu_physical_memory_get_dirty_flag(addr, dirty_flag);
+        ret |= cpu_physical_memory_get_dirty_flag(addr, client);
     }
     return ret;
 }
 
 static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
-                                                      int dirty_flag)
+                                                      unsigned client)
 {
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flag;
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= (1 << client);
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
-    cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flag(addr, CODE_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_MIGRATION);
+    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_VGA);
+    cpu_physical_memory_set_dirty_flag(addr, DIRTY_MEMORY_CODE);
 }
 
-static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr,
-                                                        int dirty_flags)
+static inline int cpu_physical_memory_clear_dirty_flag(ram_addr_t addr,
+                                                       unsigned client)
 {
-    int mask = ~dirty_flags;
+    int mask = ~(1 << client);
 
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
 }
@@ -111,19 +107,19 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
 
 static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
                                                         ram_addr_t length,
-                                                        int dirty_flags)
+                                                        unsigned client)
 {
     ram_addr_t addr, end;
 
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_clear_dirty_flags(addr, dirty_flags);
+        cpu_physical_memory_clear_dirty_flag(addr, client);
     }
 }
 
 void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
-                                     int dirty_flags);
+                                     unsigned client);
 
 #endif
 
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 480dfbf..b8e76f4 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -33,9 +33,6 @@
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
 
-/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
- * registration.
- */
 #define DIRTY_MEMORY_VGA       0
 #define DIRTY_MEMORY_CODE      1
 #define DIRTY_MEMORY_MIGRATION 3
diff --git a/memory.c b/memory.c
index fb52e1c..a490cbd 100644
--- a/memory.c
+++ b/memory.c
@@ -1174,8 +1174,7 @@ bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
                              hwaddr size, unsigned client)
 {
     assert(mr->terminates);
-    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
-                                         1 << client);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
@@ -1190,12 +1189,11 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
 {
     bool ret;
     assert(mr->terminates);
-    ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
-                                        1 << client);
+    ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client);
     if (ret) {
         cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
                                         mr->ram_addr + addr + size,
-                                        1 << client);
+                                        client);
     }
     return ret;
 }
@@ -1243,7 +1241,7 @@ void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
     assert(mr->terminates);
     cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
                                     mr->ram_addr + addr + size,
-                                    1 << client);
+                                    client);
 }
 
 void *memory_region_get_ram_ptr(MemoryRegion *mr)
commit 75218e7f2b7f052c6f44489afaf45b3ea4369f45
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 12:31:54 2013 +0200

    memory: cpu_physical_memory_set_dirty_range() always dirty all flags
    
    So remove the flag argument and do it directly.  After this change,
    there is nothing else using cpu_physical_memory_set_dirty_flags() so
    remove it.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index ffda8be..f215960 100644
--- a/exec.c
+++ b/exec.c
@@ -1275,7 +1275,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                                        last_ram_offset() >> TARGET_PAGE_BITS);
     memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
            0, size >> TARGET_PAGE_BITS);
-    cpu_physical_memory_set_dirty_range(new_block->offset, size, 0xff);
+    cpu_physical_memory_set_dirty_range(new_block->offset, size);
 
     qemu_ram_setup_dump(new_block->host, size);
     qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE);
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 9f4ad69..681d63b 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -75,12 +75,6 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
     return ret;
 }
 
-static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
-                                                      int dirty_flags)
-{
-    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
-}
-
 static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
                                                       int dirty_flag)
 {
@@ -103,15 +97,14 @@ static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr,
 }
 
 static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start,
-                                                       ram_addr_t length,
-                                                       int dirty_flags)
+                                                       ram_addr_t length)
 {
     ram_addr_t addr, end;
 
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        cpu_physical_memory_set_dirty_flags(addr, dirty_flags);
+        cpu_physical_memory_set_dirty(addr);
     }
     xen_modified_memory(addr, length);
 }
diff --git a/memory.c b/memory.c
index e497f99..fb52e1c 100644
--- a/memory.c
+++ b/memory.c
@@ -1182,7 +1182,7 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
                              hwaddr size)
 {
     assert(mr->terminates);
-    cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1);
+    cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size);
 }
 
 bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
commit 63995cebfaa283586682ea6236c9686b2a49ece7
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 12:25:25 2013 +0200

    memory: set single dirty flags when possible
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index a8c79e5..ffda8be 100644
--- a/exec.c
+++ b/exec.c
@@ -1912,7 +1912,8 @@ static void invalidate_and_set_dirty(hwaddr addr,
         /* invalidate code */
         tb_invalidate_phys_page_range(addr, addr + length, 0);
         /* set dirty bit */
-        cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG));
+        cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG);
+        cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
     }
     xen_modified_memory(addr, length);
 }
@@ -2527,8 +2528,8 @@ void stl_phys_notdirty(hwaddr addr, uint32_t val)
                 /* invalidate code */
                 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
                 /* set dirty bit */
-                cpu_physical_memory_set_dirty_flags(
-                    addr1, (0xff & ~CODE_DIRTY_FLAG));
+                cpu_physical_memory_set_dirty_flag(addr1, MIGRATION_DIRTY_FLAG);
+                cpu_physical_memory_set_dirty_flag(addr1, VGA_DIRTY_FLAG);
             }
         }
     }
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 53cfe83..9f4ad69 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -89,7 +89,9 @@ static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
-    cpu_physical_memory_set_dirty_flags(addr, 0xff);
+    cpu_physical_memory_set_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(addr, VGA_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(addr, CODE_DIRTY_FLAG);
 }
 
 static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr,
commit 36187e2ca0295364dcb9a3f256a6fcd77e983c02
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 12:17:12 2013 +0200

    memory: all users of cpu_physical_memory_get_dirty used only one flag
    
    So cpu_physical_memory_get_dirty_flags is not needed anymore
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 0b25c3f..53cfe83 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -44,11 +44,6 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
 #define CODE_DIRTY_FLAG      0x02
 #define MIGRATION_DIRTY_FLAG 0x08
 
-static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
-{
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
-}
-
 static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
                                                       int dirty_flag)
 {
@@ -67,7 +62,7 @@ static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr)
 
 static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
                                                 ram_addr_t length,
-                                                int dirty_flags)
+                                                int dirty_flag)
 {
     int ret = 0;
     ram_addr_t addr, end;
@@ -75,7 +70,7 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
     end = TARGET_PAGE_ALIGN(start + length);
     start &= TARGET_PAGE_MASK;
     for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
-        ret |= cpu_physical_memory_get_dirty_flags(addr) & dirty_flags;
+        ret |= cpu_physical_memory_get_dirty_flag(addr, dirty_flag);
     }
     return ret;
 }
commit 4f08cabe9e6efe8a50abc30cfa59e8470ad434d7
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 12:01:01 2013 +0200

    memory: make cpu_physical_memory_is_dirty return bool
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index ea78d82..a8c79e5 100644
--- a/exec.c
+++ b/exec.c
@@ -1485,11 +1485,8 @@ found:
 static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
                                uint64_t val, unsigned size)
 {
-    int dirty_flags;
-    dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
     if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) {
         tb_invalidate_phys_page_fast(ram_addr, size);
-        dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
     }
     switch (size) {
     case 1:
@@ -1504,8 +1501,8 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
     default:
         abort();
     }
-    dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
-    cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
+    cpu_physical_memory_set_dirty_flag(ram_addr, MIGRATION_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(ram_addr, VGA_DIRTY_FLAG);
     /* we remove the notdirty callback only if the code has been
        flushed */
     if (cpu_physical_memory_is_dirty(ram_addr)) {
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 136198c..0b25c3f 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -56,9 +56,13 @@ static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
 }
 
 /* read dirty bit (return 0 or 1) */
-static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
+static inline bool cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
-    return cpu_physical_memory_get_dirty_flags(addr) == 0xff;
+    bool vga = cpu_physical_memory_get_dirty_flag(addr, VGA_DIRTY_FLAG);
+    bool code = cpu_physical_memory_get_dirty_flag(addr, CODE_DIRTY_FLAG);
+    bool migration =
+        cpu_physical_memory_get_dirty_flag(addr, MIGRATION_DIRTY_FLAG);
+    return vga && code && migration;
 }
 
 static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
commit 7e5609a85e3f35965af5e4c7b1480254642cf2dd
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 11:57:21 2013 +0200

    exec: create function to get a single dirty bit
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/exec.c b/exec.c
index c42a2f9..ea78d82 100644
--- a/exec.c
+++ b/exec.c
@@ -1487,7 +1487,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
 {
     int dirty_flags;
     dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
-    if (!(dirty_flags & CODE_DIRTY_FLAG)) {
+    if (!cpu_physical_memory_get_dirty_flag(ram_addr, CODE_DIRTY_FLAG)) {
         tb_invalidate_phys_page_fast(ram_addr, size);
         dirty_flags = cpu_physical_memory_get_dirty_flags(ram_addr);
     }
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index 4ebab80..136198c 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -49,6 +49,12 @@ static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
 }
 
+static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr,
+                                                      int dirty_flag)
+{
+    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flag;
+}
+
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
 {
commit a1390db4df32ad95bf7854944180d2343f7f6368
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 11:53:46 2013 +0200

    memory: create function to set a single dirty bit
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/cputlb.c b/cputlb.c
index 9270055..c545e4c 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -122,7 +122,7 @@ void tlb_protect_code(ram_addr_t ram_addr)
 void tlb_unprotect_code_phys(CPUArchState *env, ram_addr_t ram_addr,
                              target_ulong vaddr)
 {
-    cpu_physical_memory_set_dirty_flags(ram_addr, CODE_DIRTY_FLAG);
+    cpu_physical_memory_set_dirty_flag(ram_addr, CODE_DIRTY_FLAG);
 }
 
 static bool tlb_is_dirty_ram(CPUTLBEntry *tlbe)
diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index c71a5e6..4ebab80 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -76,6 +76,12 @@ static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
     ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
 }
 
+static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr,
+                                                      int dirty_flag)
+{
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flag;
+}
+
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
     cpu_physical_memory_set_dirty_flags(addr, 0xff);
commit 06567942e5e92cc649b608205d5d31ff3ac21c58
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Oct 8 11:50:04 2013 +0200

    exec: use accessor function to know if memory is dirty
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/exec.c b/exec.c
index 7e49e8e..c42a2f9 100644
--- a/exec.c
+++ b/exec.c
@@ -1508,7 +1508,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
     cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags);
     /* we remove the notdirty callback only if the code has been
        flushed */
-    if (dirty_flags == 0xff) {
+    if (cpu_physical_memory_is_dirty(ram_addr)) {
         CPUArchState *env = current_cpu->env_ptr;
         tlb_set_dirty(env, env->mem_io_vaddr);
     }
commit 78d0042642a415b56b3c53a6044f30eff47bf69c
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 2 14:30:02 2013 +0200

    memory: cpu_physical_memory_set_dirty_range() return void
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/memory.c b/memory.c
index 7764314..e497f99 100644
--- a/memory.c
+++ b/memory.c
@@ -1182,7 +1182,7 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
                              hwaddr size)
 {
     assert(mr->terminates);
-    return cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1);
+    cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1);
 }
 
 bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
commit e2da99d582300bb8deecb25d26a179ef5b92e066
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 2 14:04:19 2013 +0200

    memory: cpu_physical_memory_set_dirty_flags() result is never used
    
    So return void.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h
index d0e0633..c71a5e6 100644
--- a/include/exec/memory-internal.h
+++ b/include/exec/memory-internal.h
@@ -70,10 +70,10 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
     return ret;
 }
 
-static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
+static inline void cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
                                                       int dirty_flags)
 {
-    return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
+    ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
 }
 
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
commit 9c22687ea8c1a2644a41a683ff0a291adc9a657c
Author: Juan Quintela <quintela at redhat.com>
Date:   Tue Dec 17 12:12:24 2013 +0100

    bitmap: use long as index
    
    Move index and size fields from int to long.  We need that for
    migration.  long is 64 bits on sane architectures, and 32bits should
    be enough on all the 32bits architectures.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>

diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h
index 308bbb7..afdd257 100644
--- a/include/qemu/bitmap.h
+++ b/include/qemu/bitmap.h
@@ -31,7 +31,7 @@
  * bitmap_andnot(dst, src1, src2, nbits)	*dst = *src1 & ~(*src2)
  * bitmap_complement(dst, src, nbits)		*dst = ~(*src)
  * bitmap_equal(src1, src2, nbits)		Are *src1 and *src2 equal?
- * bitmap_intersects(src1, src2, nbits) 	Do *src1 and *src2 overlap?
+ * bitmap_intersects(src1, src2, nbits)         Do *src1 and *src2 overlap?
  * bitmap_empty(src, nbits)			Are all bits zero in *src?
  * bitmap_full(src, nbits)			Are all bits set in *src?
  * bitmap_set(dst, pos, nbits)			Set specified bit area
@@ -62,71 +62,71 @@
         )
 
 #define DECLARE_BITMAP(name,bits)                  \
-	unsigned long name[BITS_TO_LONGS(bits)]
+        unsigned long name[BITS_TO_LONGS(bits)]
 
 #define small_nbits(nbits)                      \
-	((nbits) <= BITS_PER_LONG)
+        ((nbits) <= BITS_PER_LONG)
 
-int slow_bitmap_empty(const unsigned long *bitmap, int bits);
-int slow_bitmap_full(const unsigned long *bitmap, int bits);
+int slow_bitmap_empty(const unsigned long *bitmap, long bits);
+int slow_bitmap_full(const unsigned long *bitmap, long bits);
 int slow_bitmap_equal(const unsigned long *bitmap1,
-                   const unsigned long *bitmap2, int bits);
+                      const unsigned long *bitmap2, long bits);
 void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
-                         int bits);
+                            long bits);
 void slow_bitmap_shift_right(unsigned long *dst,
-                          const unsigned long *src, int shift, int bits);
+                             const unsigned long *src, int shift, long bits);
 void slow_bitmap_shift_left(unsigned long *dst,
-                         const unsigned long *src, int shift, int bits);
+                            const unsigned long *src, int shift, long bits);
 int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
-                 const unsigned long *bitmap2, int bits);
+                    const unsigned long *bitmap2, long bits);
 void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
-                 const unsigned long *bitmap2, int bits);
+                    const unsigned long *bitmap2, long bits);
 void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
-                  const unsigned long *bitmap2, int bits);
+                     const unsigned long *bitmap2, long bits);
 int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
-                    const unsigned long *bitmap2, int bits);
+                       const unsigned long *bitmap2, long bits);
 int slow_bitmap_intersects(const unsigned long *bitmap1,
-			const unsigned long *bitmap2, int bits);
+                           const unsigned long *bitmap2, long bits);
 
-static inline unsigned long *bitmap_new(int nbits)
+static inline unsigned long *bitmap_new(long nbits)
 {
-    int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+    long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
     return g_malloc0(len);
 }
 
-static inline void bitmap_zero(unsigned long *dst, int nbits)
+static inline void bitmap_zero(unsigned long *dst, long nbits)
 {
     if (small_nbits(nbits)) {
         *dst = 0UL;
     } else {
-        int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+        long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
         memset(dst, 0, len);
     }
 }
 
-static inline void bitmap_fill(unsigned long *dst, int nbits)
+static inline void bitmap_fill(unsigned long *dst, long nbits)
 {
     size_t nlongs = BITS_TO_LONGS(nbits);
     if (!small_nbits(nbits)) {
-        int len = (nlongs - 1) * sizeof(unsigned long);
+        long len = (nlongs - 1) * sizeof(unsigned long);
         memset(dst, 0xff,  len);
     }
     dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
 }
 
 static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
-                               int nbits)
+                               long nbits)
 {
     if (small_nbits(nbits)) {
         *dst = *src;
     } else {
-        int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+        long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
         memcpy(dst, src, len);
     }
 }
 
 static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
-                             const unsigned long *src2, int nbits)
+                             const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         return (*dst = *src1 & *src2) != 0;
@@ -135,7 +135,7 @@ static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
 }
 
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
-			const unsigned long *src2, int nbits)
+                             const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         *dst = *src1 | *src2;
@@ -145,7 +145,7 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 }
 
 static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
-			const unsigned long *src2, int nbits)
+                              const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         *dst = *src1 ^ *src2;
@@ -155,7 +155,7 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
 }
 
 static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
-			const unsigned long *src2, int nbits)
+                                const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         return (*dst = *src1 & ~(*src2)) != 0;
@@ -163,8 +163,9 @@ static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
     return slow_bitmap_andnot(dst, src1, src2, nbits);
 }
 
-static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
-			int nbits)
+static inline void bitmap_complement(unsigned long *dst,
+                                     const unsigned long *src,
+                                     long nbits)
 {
     if (small_nbits(nbits)) {
         *dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
@@ -174,7 +175,7 @@ static inline void bitmap_complement(unsigned long *dst, const unsigned long *sr
 }
 
 static inline int bitmap_equal(const unsigned long *src1,
-			const unsigned long *src2, int nbits)
+                               const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
@@ -183,7 +184,7 @@ static inline int bitmap_equal(const unsigned long *src1,
     }
 }
 
-static inline int bitmap_empty(const unsigned long *src, int nbits)
+static inline int bitmap_empty(const unsigned long *src, long nbits)
 {
     if (small_nbits(nbits)) {
         return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
@@ -192,7 +193,7 @@ static inline int bitmap_empty(const unsigned long *src, int nbits)
     }
 }
 
-static inline int bitmap_full(const unsigned long *src, int nbits)
+static inline int bitmap_full(const unsigned long *src, long nbits)
 {
     if (small_nbits(nbits)) {
         return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
@@ -202,7 +203,7 @@ static inline int bitmap_full(const unsigned long *src, int nbits)
 }
 
 static inline int bitmap_intersects(const unsigned long *src1,
-			const unsigned long *src2, int nbits)
+                                    const unsigned long *src2, long nbits)
 {
     if (small_nbits(nbits)) {
         return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
@@ -211,12 +212,12 @@ static inline int bitmap_intersects(const unsigned long *src1,
     }
 }
 
-void bitmap_set(unsigned long *map, int i, int len);
-void bitmap_clear(unsigned long *map, int start, int nr);
+void bitmap_set(unsigned long *map, long i, long len);
+void bitmap_clear(unsigned long *map, long start, long nr);
 unsigned long bitmap_find_next_zero_area(unsigned long *map,
-					 unsigned long size,
-					 unsigned long start,
-					 unsigned int nr,
-					 unsigned long align_mask);
+                                         unsigned long size,
+                                         unsigned long start,
+                                         unsigned long nr,
+                                         unsigned long align_mask);
 
 #endif /* BITMAP_H */
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index 304c90c..340b1e7 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -28,7 +28,7 @@
  * @nr: the bit to set
  * @addr: the address to start counting from
  */
-static inline void set_bit(int nr, unsigned long *addr)
+static inline void set_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -41,7 +41,7 @@ static inline void set_bit(int nr, unsigned long *addr)
  * @nr: Bit to clear
  * @addr: Address to start counting from
  */
-static inline void clear_bit(int nr, unsigned long *addr)
+static inline void clear_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -54,7 +54,7 @@ static inline void clear_bit(int nr, unsigned long *addr)
  * @nr: Bit to change
  * @addr: Address to start counting from
  */
-static inline void change_bit(int nr, unsigned long *addr)
+static inline void change_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -67,7 +67,7 @@ static inline void change_bit(int nr, unsigned long *addr)
  * @nr: Bit to set
  * @addr: Address to count from
  */
-static inline int test_and_set_bit(int nr, unsigned long *addr)
+static inline int test_and_set_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -82,7 +82,7 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
  * @nr: Bit to clear
  * @addr: Address to count from
  */
-static inline int test_and_clear_bit(int nr, unsigned long *addr)
+static inline int test_and_clear_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -97,7 +97,7 @@ static inline int test_and_clear_bit(int nr, unsigned long *addr)
  * @nr: Bit to change
  * @addr: Address to count from
  */
-static inline int test_and_change_bit(int nr, unsigned long *addr)
+static inline int test_and_change_bit(long nr, unsigned long *addr)
 {
 	unsigned long mask = BIT_MASK(nr);
         unsigned long *p = addr + BIT_WORD(nr);
@@ -112,7 +112,7 @@ static inline int test_and_change_bit(int nr, unsigned long *addr)
  * @nr: bit number to test
  * @addr: Address to start counting from
  */
-static inline int test_bit(int nr, const unsigned long *addr)
+static inline int test_bit(long nr, const unsigned long *addr)
 {
 	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
 }
diff --git a/util/bitmap.c b/util/bitmap.c
index 687841d..9c6bb52 100644
--- a/util/bitmap.c
+++ b/util/bitmap.c
@@ -36,9 +36,9 @@
  * endian architectures.
  */
 
-int slow_bitmap_empty(const unsigned long *bitmap, int bits)
+int slow_bitmap_empty(const unsigned long *bitmap, long bits)
 {
-    int k, lim = bits/BITS_PER_LONG;
+    long k, lim = bits/BITS_PER_LONG;
 
     for (k = 0; k < lim; ++k) {
         if (bitmap[k]) {
@@ -54,9 +54,9 @@ int slow_bitmap_empty(const unsigned long *bitmap, int bits)
     return 1;
 }
 
-int slow_bitmap_full(const unsigned long *bitmap, int bits)
+int slow_bitmap_full(const unsigned long *bitmap, long bits)
 {
-    int k, lim = bits/BITS_PER_LONG;
+    long k, lim = bits/BITS_PER_LONG;
 
     for (k = 0; k < lim; ++k) {
         if (~bitmap[k]) {
@@ -74,9 +74,9 @@ int slow_bitmap_full(const unsigned long *bitmap, int bits)
 }
 
 int slow_bitmap_equal(const unsigned long *bitmap1,
-                      const unsigned long *bitmap2, int bits)
+                      const unsigned long *bitmap2, long bits)
 {
-    int k, lim = bits/BITS_PER_LONG;
+    long k, lim = bits/BITS_PER_LONG;
 
     for (k = 0; k < lim; ++k) {
         if (bitmap1[k] != bitmap2[k]) {
@@ -94,9 +94,9 @@ int slow_bitmap_equal(const unsigned long *bitmap1,
 }
 
 void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
-                            int bits)
+                            long bits)
 {
-    int k, lim = bits/BITS_PER_LONG;
+    long k, lim = bits/BITS_PER_LONG;
 
     for (k = 0; k < lim; ++k) {
         dst[k] = ~src[k];
@@ -108,10 +108,10 @@ void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
 }
 
 int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
-                    const unsigned long *bitmap2, int bits)
+                    const unsigned long *bitmap2, long bits)
 {
-    int k;
-    int nr = BITS_TO_LONGS(bits);
+    long k;
+    long nr = BITS_TO_LONGS(bits);
     unsigned long result = 0;
 
     for (k = 0; k < nr; k++) {
@@ -121,10 +121,10 @@ int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
 }
 
 void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
-                    const unsigned long *bitmap2, int bits)
+                    const unsigned long *bitmap2, long bits)
 {
-    int k;
-    int nr = BITS_TO_LONGS(bits);
+    long k;
+    long nr = BITS_TO_LONGS(bits);
 
     for (k = 0; k < nr; k++) {
         dst[k] = bitmap1[k] | bitmap2[k];
@@ -132,10 +132,10 @@ void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 }
 
 void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
-                     const unsigned long *bitmap2, int bits)
+                     const unsigned long *bitmap2, long bits)
 {
-    int k;
-    int nr = BITS_TO_LONGS(bits);
+    long k;
+    long nr = BITS_TO_LONGS(bits);
 
     for (k = 0; k < nr; k++) {
         dst[k] = bitmap1[k] ^ bitmap2[k];
@@ -143,10 +143,10 @@ void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
 }
 
 int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
-                       const unsigned long *bitmap2, int bits)
+                       const unsigned long *bitmap2, long bits)
 {
-    int k;
-    int nr = BITS_TO_LONGS(bits);
+    long k;
+    long nr = BITS_TO_LONGS(bits);
     unsigned long result = 0;
 
     for (k = 0; k < nr; k++) {
@@ -157,10 +157,10 @@ int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
 
-void bitmap_set(unsigned long *map, int start, int nr)
+void bitmap_set(unsigned long *map, long start, long nr)
 {
     unsigned long *p = map + BIT_WORD(start);
-    const int size = start + nr;
+    const long size = start + nr;
     int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
     unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
 
@@ -177,10 +177,10 @@ void bitmap_set(unsigned long *map, int start, int nr)
     }
 }
 
-void bitmap_clear(unsigned long *map, int start, int nr)
+void bitmap_clear(unsigned long *map, long start, long nr)
 {
     unsigned long *p = map + BIT_WORD(start);
-    const int size = start + nr;
+    const long size = start + nr;
     int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
     unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
 
@@ -212,10 +212,10 @@ void bitmap_clear(unsigned long *map, int start, int nr)
  * power of 2. A @align_mask of 0 means no alignment is required.
  */
 unsigned long bitmap_find_next_zero_area(unsigned long *map,
-					 unsigned long size,
-					 unsigned long start,
-					 unsigned int nr,
-					 unsigned long align_mask)
+                                         unsigned long size,
+                                         unsigned long start,
+                                         unsigned long nr,
+                                         unsigned long align_mask)
 {
     unsigned long index, end, i;
 again:
@@ -237,9 +237,9 @@ again:
 }
 
 int slow_bitmap_intersects(const unsigned long *bitmap1,
-                           const unsigned long *bitmap2, int bits)
+                           const unsigned long *bitmap2, long bits)
 {
-    int k, lim = bits/BITS_PER_LONG;
+    long k, lim = bits/BITS_PER_LONG;
 
     for (k = 0; k < lim; ++k) {
         if (bitmap1[k] & bitmap2[k]) {
commit 2668b4bff484a8428947c10a0efb9758658f4b1a
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:18 2013 -0200

    tests: Some unit tests for vmstate.c
    
     * Basic load/save tests
     * Tests for loading older versions
     * Tests for .field_exists() handling
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/tests/.gitignore b/tests/.gitignore
index 425757c..1aed224 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -20,6 +20,7 @@ test-qmp-commands
 test-qmp-input-strict
 test-qmp-marshal.c
 test-thread-pool
+test-vmstate
 test-x86-cpuid
 test-xbzrle
 *-test
diff --git a/tests/Makefile b/tests/Makefile
index 0b85a34..0aaf657 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -54,6 +54,7 @@ check-unit-y += tests/test-bitops$(EXESUF)
 check-unit-y += tests/test-qdev-global-props$(EXESUF)
 check-unit-y += tests/check-qom-interface$(EXESUF)
 gcov-files-check-qom-interface-y = qom/object.c
+check-unit-y += tests/test-vmstate$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -167,6 +168,9 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
 	$(qom-core-obj) \
 	$(test-qapi-obj-y) \
 	libqemuutil.a libqemustub.a
+tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
+	vmstate.o qemu-file.o \
+	libqemuutil.a
 
 tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c
new file mode 100644
index 0000000..75cd1a1
--- /dev/null
+++ b/tests/test-vmstate.c
@@ -0,0 +1,357 @@
+/*
+ *  Test code for VMState
+ *
+ *  Copyright (c) 2013 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 <glib.h>
+
+#include "qemu-common.h"
+#include "migration/migration.h"
+#include "migration/vmstate.h"
+#include "block/coroutine.h"
+
+char temp_file[] = "/tmp/vmst.test.XXXXXX";
+int temp_fd;
+
+/* Fake yield_until_fd_readable() implementation so we don't have to pull the
+ * coroutine code as dependency.
+ */
+void yield_until_fd_readable(int fd)
+{
+    fd_set fds;
+    FD_ZERO(&fds);
+    FD_SET(fd, &fds);
+    select(fd + 1, &fds, NULL, NULL, NULL);
+}
+
+/* Duplicate temp_fd and seek to the beginning of the file */
+static int dup_temp_fd(bool truncate)
+{
+    int fd = dup(temp_fd);
+    lseek(fd, 0, SEEK_SET);
+    if (truncate) {
+        g_assert_cmpint(ftruncate(fd, 0), ==, 0);
+    }
+    return fd;
+}
+
+typedef struct TestSruct {
+    uint32_t a, b, c, e;
+    uint64_t d, f;
+    bool skip_c_e;
+} TestStruct;
+
+
+static const VMStateDescription vmstate_simple = {
+    .name = "test",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(a, TestStruct),
+        VMSTATE_UINT32(b, TestStruct),
+        VMSTATE_UINT32(c, TestStruct),
+        VMSTATE_UINT64(d, TestStruct),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void test_simple_save(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4 };
+    vmstate_save_state(fsave, &vmstate_simple, &obj);
+    g_assert(!qemu_file_get_error(fsave));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    uint8_t expected[] = {
+        0, 0, 0, 1, /* a */
+        0, 0, 0, 2, /* b */
+        0, 0, 0, 3, /* c */
+        0, 0, 0, 0, 0, 0, 0, 4, /* d */
+    };
+    uint8_t result[sizeof(expected)];
+    g_assert_cmpint(qemu_get_buffer(loading, result, sizeof(result)), ==,
+                    sizeof(result));
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(memcmp(result, expected, sizeof(result)), ==, 0);
+
+    /* Must reach EOF */
+    qemu_get_byte(loading);
+    g_assert_cmpint(qemu_file_get_error(loading), ==, -EIO);
+
+    qemu_fclose(loading);
+}
+
+static void test_simple_load(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    uint8_t buf[] = {
+        0, 0, 0, 10,             /* a */
+        0, 0, 0, 20,             /* b */
+        0, 0, 0, 30,             /* c */
+        0, 0, 0, 0, 0, 0, 0, 40, /* d */
+        QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+    };
+    qemu_put_buffer(fsave, buf, sizeof(buf));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    TestStruct obj;
+    vmstate_load_state(loading, &vmstate_simple, &obj, 1);
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(obj.a, ==, 10);
+    g_assert_cmpint(obj.b, ==, 20);
+    g_assert_cmpint(obj.c, ==, 30);
+    g_assert_cmpint(obj.d, ==, 40);
+    qemu_fclose(loading);
+}
+
+static const VMStateDescription vmstate_versioned = {
+    .name = "test",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32(a, TestStruct),
+        VMSTATE_UINT32_V(b, TestStruct, 2), /* Versioned field in the middle, so
+                                             * we catch bugs more easily.
+                                             */
+        VMSTATE_UINT32(c, TestStruct),
+        VMSTATE_UINT64(d, TestStruct),
+        VMSTATE_UINT32_V(e, TestStruct, 2),
+        VMSTATE_UINT64_V(f, TestStruct, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void test_load_v1(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    uint8_t buf[] = {
+        0, 0, 0, 10,             /* a */
+        0, 0, 0, 30,             /* c */
+        0, 0, 0, 0, 0, 0, 0, 40, /* d */
+        QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+    };
+    qemu_put_buffer(fsave, buf, sizeof(buf));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    TestStruct obj = { .b = 200, .e = 500, .f = 600 };
+    vmstate_load_state(loading, &vmstate_versioned, &obj, 1);
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(obj.a, ==, 10);
+    g_assert_cmpint(obj.b, ==, 200);
+    g_assert_cmpint(obj.c, ==, 30);
+    g_assert_cmpint(obj.d, ==, 40);
+    g_assert_cmpint(obj.e, ==, 500);
+    g_assert_cmpint(obj.f, ==, 600);
+    qemu_fclose(loading);
+}
+
+static void test_load_v2(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    uint8_t buf[] = {
+        0, 0, 0, 10,             /* a */
+        0, 0, 0, 20,             /* b */
+        0, 0, 0, 30,             /* c */
+        0, 0, 0, 0, 0, 0, 0, 40, /* d */
+        0, 0, 0, 50,             /* e */
+        0, 0, 0, 0, 0, 0, 0, 60, /* f */
+        QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+    };
+    qemu_put_buffer(fsave, buf, sizeof(buf));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    TestStruct obj;
+    vmstate_load_state(loading, &vmstate_versioned, &obj, 2);
+    g_assert_cmpint(obj.a, ==, 10);
+    g_assert_cmpint(obj.b, ==, 20);
+    g_assert_cmpint(obj.c, ==, 30);
+    g_assert_cmpint(obj.d, ==, 40);
+    g_assert_cmpint(obj.e, ==, 50);
+    g_assert_cmpint(obj.f, ==, 60);
+    qemu_fclose(loading);
+}
+
+static bool test_skip(void *opaque, int version_id)
+{
+    TestStruct *t = (TestStruct *)opaque;
+    return !t->skip_c_e;
+}
+
+static const VMStateDescription vmstate_skipping = {
+    .name = "test",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32(a, TestStruct),
+        VMSTATE_UINT32(b, TestStruct),
+        VMSTATE_UINT32_TEST(c, TestStruct, test_skip),
+        VMSTATE_UINT64(d, TestStruct),
+        VMSTATE_UINT32_TEST(e, TestStruct, test_skip),
+        VMSTATE_UINT64_V(f, TestStruct, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+static void test_save_noskip(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
+                       .skip_c_e = false };
+    vmstate_save_state(fsave, &vmstate_skipping, &obj);
+    g_assert(!qemu_file_get_error(fsave));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    uint8_t expected[] = {
+        0, 0, 0, 1,             /* a */
+        0, 0, 0, 2,             /* b */
+        0, 0, 0, 3,             /* c */
+        0, 0, 0, 0, 0, 0, 0, 4, /* d */
+        0, 0, 0, 5,             /* e */
+        0, 0, 0, 0, 0, 0, 0, 6, /* f */
+    };
+    uint8_t result[sizeof(expected)];
+    g_assert_cmpint(qemu_get_buffer(loading, result, sizeof(result)), ==,
+                    sizeof(result));
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(memcmp(result, expected, sizeof(result)), ==, 0);
+
+    /* Must reach EOF */
+    qemu_get_byte(loading);
+    g_assert_cmpint(qemu_file_get_error(loading), ==, -EIO);
+
+    qemu_fclose(loading);
+}
+
+static void test_save_skip(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
+                       .skip_c_e = true };
+    vmstate_save_state(fsave, &vmstate_skipping, &obj);
+    g_assert(!qemu_file_get_error(fsave));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    uint8_t expected[] = {
+        0, 0, 0, 1,             /* a */
+        0, 0, 0, 2,             /* b */
+        0, 0, 0, 0, 0, 0, 0, 4, /* d */
+        0, 0, 0, 0, 0, 0, 0, 6, /* f */
+    };
+    uint8_t result[sizeof(expected)];
+    g_assert_cmpint(qemu_get_buffer(loading, result, sizeof(result)), ==,
+                    sizeof(result));
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(memcmp(result, expected, sizeof(result)), ==, 0);
+
+
+    /* Must reach EOF */
+    qemu_get_byte(loading);
+    g_assert_cmpint(qemu_file_get_error(loading), ==, -EIO);
+
+    qemu_fclose(loading);
+}
+
+static void test_load_noskip(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    uint8_t buf[] = {
+        0, 0, 0, 10,             /* a */
+        0, 0, 0, 20,             /* b */
+        0, 0, 0, 30,             /* c */
+        0, 0, 0, 0, 0, 0, 0, 40, /* d */
+        0, 0, 0, 50,             /* e */
+        0, 0, 0, 0, 0, 0, 0, 60, /* f */
+        QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+    };
+    qemu_put_buffer(fsave, buf, sizeof(buf));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    TestStruct obj = { .skip_c_e = false };
+    vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(obj.a, ==, 10);
+    g_assert_cmpint(obj.b, ==, 20);
+    g_assert_cmpint(obj.c, ==, 30);
+    g_assert_cmpint(obj.d, ==, 40);
+    g_assert_cmpint(obj.e, ==, 50);
+    g_assert_cmpint(obj.f, ==, 60);
+    qemu_fclose(loading);
+}
+
+static void test_load_skip(void)
+{
+    QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+    uint8_t buf[] = {
+        0, 0, 0, 10,             /* a */
+        0, 0, 0, 20,             /* b */
+        0, 0, 0, 0, 0, 0, 0, 40, /* d */
+        0, 0, 0, 0, 0, 0, 0, 60, /* f */
+        QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+    };
+    qemu_put_buffer(fsave, buf, sizeof(buf));
+    qemu_fclose(fsave);
+
+    QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+    TestStruct obj = { .skip_c_e = true, .c = 300, .e = 500 };
+    vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
+    g_assert(!qemu_file_get_error(loading));
+    g_assert_cmpint(obj.a, ==, 10);
+    g_assert_cmpint(obj.b, ==, 20);
+    g_assert_cmpint(obj.c, ==, 300);
+    g_assert_cmpint(obj.d, ==, 40);
+    g_assert_cmpint(obj.e, ==, 500);
+    g_assert_cmpint(obj.f, ==, 60);
+    qemu_fclose(loading);
+}
+
+int main(int argc, char **argv)
+{
+    temp_fd = mkstemp(temp_file);
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/vmstate/simple/save", test_simple_save);
+    g_test_add_func("/vmstate/simple/load", test_simple_load);
+    g_test_add_func("/vmstate/versioned/load/v1", test_load_v1);
+    g_test_add_func("/vmstate/versioned/load/v2", test_load_v2);
+    g_test_add_func("/vmstate/field_exists/load/noskip", test_load_noskip);
+    g_test_add_func("/vmstate/field_exists/load/skip", test_load_skip);
+    g_test_add_func("/vmstate/field_exists/save/noskip", test_save_noskip);
+    g_test_add_func("/vmstate/field_exists/save/skip", test_save_skip);
+    g_test_run();
+
+    close(temp_fd);
+    unlink(temp_file);
+
+    return 0;
+}
commit bb1a6d8c57217188f33d8e59d71fc62dbee9e4f8
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Fri Nov 29 12:26:02 2013 -0200

    savevm: Small comment about why timer QEMUFile/VMState code is in savevm.c
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 8eeb5ef..a7dbe18 100644
--- a/savevm.c
+++ b/savevm.c
@@ -166,7 +166,9 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
 }
 
 
-/* timer */
+/* QEMUFile timer support.
+ * Not in qemu-file.c to not add qemu-timer.c as dependency to qemu-file.c
+ */
 
 void timer_put(QEMUFile *f, QEMUTimer *ts)
 {
@@ -189,7 +191,9 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
 }
 
 
-/* timers  */
+/* VMState timer support.
+ * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
+ */
 
 static int get_timer(QEMUFile *f, void *pv, size_t size)
 {
commit 093c455a8c6d8f715eabd8c8d346f08f17d686ec
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:16 2013 -0200

    qemu-file: Move QEMUFile code to qemu-file.c
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 23eda2b..857bb53 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -52,6 +52,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
 
 common-obj-y += migration.o migration-tcp.o
 common-obj-y += vmstate.o
+common-obj-y += qemu-file.o
 common-obj-$(CONFIG_RDMA) += migration-rdma.o
 common-obj-y += qemu-char.o #aio.o
 common-obj-y += block-migration.o
diff --git a/qemu-file.c b/qemu-file.c
new file mode 100644
index 0000000..9473b67
--- /dev/null
+++ b/qemu-file.c
@@ -0,0 +1,826 @@
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+#include "block/coroutine.h"
+#include "migration/migration.h"
+#include "migration/qemu-file.h"
+
+#define IO_BUF_SIZE 32768
+#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
+
+struct QEMUFile {
+    const QEMUFileOps *ops;
+    void *opaque;
+
+    int64_t bytes_xfer;
+    int64_t xfer_limit;
+
+    int64_t pos; /* start of buffer when writing, end of buffer
+                    when reading */
+    int buf_index;
+    int buf_size; /* 0 when writing */
+    uint8_t buf[IO_BUF_SIZE];
+
+    struct iovec iov[MAX_IOV_SIZE];
+    unsigned int iovcnt;
+
+    int last_error;
+};
+
+typedef struct QEMUFileStdio {
+    FILE *stdio_file;
+    QEMUFile *file;
+} QEMUFileStdio;
+
+typedef struct QEMUFileSocket {
+    int fd;
+    QEMUFile *file;
+} QEMUFileSocket;
+
+static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
+                                    int64_t pos)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+    ssize_t size = iov_size(iov, iovcnt);
+
+    len = iov_send(s->fd, iov, iovcnt, 0, size);
+    if (len < size) {
+        len = -socket_error();
+    }
+    return len;
+}
+
+static int socket_get_fd(void *opaque)
+{
+    QEMUFileSocket *s = opaque;
+
+    return s->fd;
+}
+
+static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+
+    for (;;) {
+        len = qemu_recv(s->fd, buf, size, 0);
+        if (len != -1) {
+            break;
+        }
+        if (socket_error() == EAGAIN) {
+            yield_until_fd_readable(s->fd);
+        } else if (socket_error() != EINTR) {
+            break;
+        }
+    }
+
+    if (len == -1) {
+        len = -socket_error();
+    }
+    return len;
+}
+
+static int socket_close(void *opaque)
+{
+    QEMUFileSocket *s = opaque;
+    closesocket(s->fd);
+    g_free(s);
+    return 0;
+}
+
+static int stdio_get_fd(void *opaque)
+{
+    QEMUFileStdio *s = opaque;
+
+    return fileno(s->stdio_file);
+}
+
+static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos,
+                            int size)
+{
+    QEMUFileStdio *s = opaque;
+    return fwrite(buf, 1, size, s->stdio_file);
+}
+
+static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+{
+    QEMUFileStdio *s = opaque;
+    FILE *fp = s->stdio_file;
+    int bytes;
+
+    for (;;) {
+        clearerr(fp);
+        bytes = fread(buf, 1, size, fp);
+        if (bytes != 0 || !ferror(fp)) {
+            break;
+        }
+        if (errno == EAGAIN) {
+            yield_until_fd_readable(fileno(fp));
+        } else if (errno != EINTR) {
+            break;
+        }
+    }
+    return bytes;
+}
+
+static int stdio_pclose(void *opaque)
+{
+    QEMUFileStdio *s = opaque;
+    int ret;
+    ret = pclose(s->stdio_file);
+    if (ret == -1) {
+        ret = -errno;
+    } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
+        /* close succeeded, but non-zero exit code: */
+        ret = -EIO; /* fake errno value */
+    }
+    g_free(s);
+    return ret;
+}
+
+static int stdio_fclose(void *opaque)
+{
+    QEMUFileStdio *s = opaque;
+    int ret = 0;
+
+    if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
+        int fd = fileno(s->stdio_file);
+        struct stat st;
+
+        ret = fstat(fd, &st);
+        if (ret == 0 && S_ISREG(st.st_mode)) {
+            /*
+             * If the file handle is a regular file make sure the
+             * data is flushed to disk before signaling success.
+             */
+            ret = fsync(fd);
+            if (ret != 0) {
+                ret = -errno;
+                return ret;
+            }
+        }
+    }
+    if (fclose(s->stdio_file) == EOF) {
+        ret = -errno;
+    }
+    g_free(s);
+    return ret;
+}
+
+static const QEMUFileOps stdio_pipe_read_ops = {
+    .get_fd =     stdio_get_fd,
+    .get_buffer = stdio_get_buffer,
+    .close =      stdio_pclose
+};
+
+static const QEMUFileOps stdio_pipe_write_ops = {
+    .get_fd =     stdio_get_fd,
+    .put_buffer = stdio_put_buffer,
+    .close =      stdio_pclose
+};
+
+QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
+{
+    FILE *stdio_file;
+    QEMUFileStdio *s;
+
+    if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
+        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
+        return NULL;
+    }
+
+    stdio_file = popen(command, mode);
+    if (stdio_file == NULL) {
+        return NULL;
+    }
+
+    s = g_malloc0(sizeof(QEMUFileStdio));
+
+    s->stdio_file = stdio_file;
+
+    if (mode[0] == 'r') {
+        s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
+    } else {
+        s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
+    }
+    return s->file;
+}
+
+static const QEMUFileOps stdio_file_read_ops = {
+    .get_fd =     stdio_get_fd,
+    .get_buffer = stdio_get_buffer,
+    .close =      stdio_fclose
+};
+
+static const QEMUFileOps stdio_file_write_ops = {
+    .get_fd =     stdio_get_fd,
+    .put_buffer = stdio_put_buffer,
+    .close =      stdio_fclose
+};
+
+static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
+                                  int64_t pos)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len, offset;
+    ssize_t size = iov_size(iov, iovcnt);
+    ssize_t total = 0;
+
+    assert(iovcnt > 0);
+    offset = 0;
+    while (size > 0) {
+        /* Find the next start position; skip all full-sized vector elements  */
+        while (offset >= iov[0].iov_len) {
+            offset -= iov[0].iov_len;
+            iov++, iovcnt--;
+        }
+
+        /* skip `offset' bytes from the (now) first element, undo it on exit */
+        assert(iovcnt > 0);
+        iov[0].iov_base += offset;
+        iov[0].iov_len -= offset;
+
+        do {
+            len = writev(s->fd, iov, iovcnt);
+        } while (len == -1 && errno == EINTR);
+        if (len == -1) {
+            return -errno;
+        }
+
+        /* Undo the changes above */
+        iov[0].iov_base -= offset;
+        iov[0].iov_len += offset;
+
+        /* Prepare for the next iteration */
+        offset += len;
+        total += len;
+        size -= len;
+    }
+
+    return total;
+}
+
+static int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+
+    for (;;) {
+        len = read(s->fd, buf, size);
+        if (len != -1) {
+            break;
+        }
+        if (errno == EAGAIN) {
+            yield_until_fd_readable(s->fd);
+        } else if (errno != EINTR) {
+            break;
+        }
+    }
+
+    if (len == -1) {
+        len = -errno;
+    }
+    return len;
+}
+
+static int unix_close(void *opaque)
+{
+    QEMUFileSocket *s = opaque;
+    close(s->fd);
+    g_free(s);
+    return 0;
+}
+
+static const QEMUFileOps unix_read_ops = {
+    .get_fd =     socket_get_fd,
+    .get_buffer = unix_get_buffer,
+    .close =      unix_close
+};
+
+static const QEMUFileOps unix_write_ops = {
+    .get_fd =     socket_get_fd,
+    .writev_buffer = unix_writev_buffer,
+    .close =      unix_close
+};
+
+QEMUFile *qemu_fdopen(int fd, const char *mode)
+{
+    QEMUFileSocket *s;
+
+    if (mode == NULL ||
+        (mode[0] != 'r' && mode[0] != 'w') ||
+        mode[1] != 'b' || mode[2] != 0) {
+        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
+        return NULL;
+    }
+
+    s = g_malloc0(sizeof(QEMUFileSocket));
+    s->fd = fd;
+
+    if (mode[0] == 'r') {
+        s->file = qemu_fopen_ops(s, &unix_read_ops);
+    } else {
+        s->file = qemu_fopen_ops(s, &unix_write_ops);
+    }
+    return s->file;
+}
+
+static const QEMUFileOps socket_read_ops = {
+    .get_fd =     socket_get_fd,
+    .get_buffer = socket_get_buffer,
+    .close =      socket_close
+};
+
+static const QEMUFileOps socket_write_ops = {
+    .get_fd =     socket_get_fd,
+    .writev_buffer = socket_writev_buffer,
+    .close =      socket_close
+};
+
+bool qemu_file_mode_is_not_valid(const char *mode)
+{
+    if (mode == NULL ||
+        (mode[0] != 'r' && mode[0] != 'w') ||
+        mode[1] != 'b' || mode[2] != 0) {
+        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
+        return true;
+    }
+
+    return false;
+}
+
+QEMUFile *qemu_fopen_socket(int fd, const char *mode)
+{
+    QEMUFileSocket *s;
+
+    if (qemu_file_mode_is_not_valid(mode)) {
+        return NULL;
+    }
+
+    s = g_malloc0(sizeof(QEMUFileSocket));
+    s->fd = fd;
+    if (mode[0] == 'w') {
+        qemu_set_block(s->fd);
+        s->file = qemu_fopen_ops(s, &socket_write_ops);
+    } else {
+        s->file = qemu_fopen_ops(s, &socket_read_ops);
+    }
+    return s->file;
+}
+
+QEMUFile *qemu_fopen(const char *filename, const char *mode)
+{
+    QEMUFileStdio *s;
+
+    if (qemu_file_mode_is_not_valid(mode)) {
+        return NULL;
+    }
+
+    s = g_malloc0(sizeof(QEMUFileStdio));
+
+    s->stdio_file = fopen(filename, mode);
+    if (!s->stdio_file) {
+        goto fail;
+    }
+
+    if (mode[0] == 'w') {
+        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
+    } else {
+        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
+    }
+    return s->file;
+fail:
+    g_free(s);
+    return NULL;
+}
+
+QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
+{
+    QEMUFile *f;
+
+    f = g_malloc0(sizeof(QEMUFile));
+
+    f->opaque = opaque;
+    f->ops = ops;
+    return f;
+}
+
+/*
+ * Get last error for stream f
+ *
+ * Return negative error value if there has been an error on previous
+ * operations, return 0 if no error happened.
+ *
+ */
+int qemu_file_get_error(QEMUFile *f)
+{
+    return f->last_error;
+}
+
+void qemu_file_set_error(QEMUFile *f, int ret)
+{
+    if (f->last_error == 0) {
+        f->last_error = ret;
+    }
+}
+
+static inline bool qemu_file_is_writable(QEMUFile *f)
+{
+    return f->ops->writev_buffer || f->ops->put_buffer;
+}
+
+/**
+ * Flushes QEMUFile buffer
+ *
+ * If there is writev_buffer QEMUFileOps it uses it otherwise uses
+ * put_buffer ops.
+ */
+void qemu_fflush(QEMUFile *f)
+{
+    ssize_t ret = 0;
+
+    if (!qemu_file_is_writable(f)) {
+        return;
+    }
+
+    if (f->ops->writev_buffer) {
+        if (f->iovcnt > 0) {
+            ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
+        }
+    } else {
+        if (f->buf_index > 0) {
+            ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
+        }
+    }
+    if (ret >= 0) {
+        f->pos += ret;
+    }
+    f->buf_index = 0;
+    f->iovcnt = 0;
+    if (ret < 0) {
+        qemu_file_set_error(f, ret);
+    }
+}
+
+void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
+{
+    int ret = 0;
+
+    if (f->ops->before_ram_iterate) {
+        ret = f->ops->before_ram_iterate(f, f->opaque, flags);
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+        }
+    }
+}
+
+void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
+{
+    int ret = 0;
+
+    if (f->ops->after_ram_iterate) {
+        ret = f->ops->after_ram_iterate(f, f->opaque, flags);
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+        }
+    }
+}
+
+void ram_control_load_hook(QEMUFile *f, uint64_t flags)
+{
+    int ret = -EINVAL;
+
+    if (f->ops->hook_ram_load) {
+        ret = f->ops->hook_ram_load(f, f->opaque, flags);
+        if (ret < 0) {
+            qemu_file_set_error(f, ret);
+        }
+    } else {
+        qemu_file_set_error(f, ret);
+    }
+}
+
+size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
+                         ram_addr_t offset, size_t size, int *bytes_sent)
+{
+    if (f->ops->save_page) {
+        int ret = f->ops->save_page(f, f->opaque, block_offset,
+                                    offset, size, bytes_sent);
+
+        if (ret != RAM_SAVE_CONTROL_DELAYED) {
+            if (bytes_sent && *bytes_sent > 0) {
+                qemu_update_position(f, *bytes_sent);
+            } else if (ret < 0) {
+                qemu_file_set_error(f, ret);
+            }
+        }
+
+        return ret;
+    }
+
+    return RAM_SAVE_CONTROL_NOT_SUPP;
+}
+
+static void qemu_fill_buffer(QEMUFile *f)
+{
+    int len;
+    int pending;
+
+    assert(!qemu_file_is_writable(f));
+
+    pending = f->buf_size - f->buf_index;
+    if (pending > 0) {
+        memmove(f->buf, f->buf + f->buf_index, pending);
+    }
+    f->buf_index = 0;
+    f->buf_size = pending;
+
+    len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
+                        IO_BUF_SIZE - pending);
+    if (len > 0) {
+        f->buf_size += len;
+        f->pos += len;
+    } else if (len == 0) {
+        qemu_file_set_error(f, -EIO);
+    } else if (len != -EAGAIN) {
+        qemu_file_set_error(f, len);
+    }
+}
+
+int qemu_get_fd(QEMUFile *f)
+{
+    if (f->ops->get_fd) {
+        return f->ops->get_fd(f->opaque);
+    }
+    return -1;
+}
+
+void qemu_update_position(QEMUFile *f, size_t size)
+{
+    f->pos += size;
+}
+
+/** Closes the file
+ *
+ * Returns negative error value if any error happened on previous operations or
+ * while closing the file. Returns 0 or positive number on success.
+ *
+ * The meaning of return value on success depends on the specific backend
+ * being used.
+ */
+int qemu_fclose(QEMUFile *f)
+{
+    int ret;
+    qemu_fflush(f);
+    ret = qemu_file_get_error(f);
+
+    if (f->ops->close) {
+        int ret2 = f->ops->close(f->opaque);
+        if (ret >= 0) {
+            ret = ret2;
+        }
+    }
+    /* If any error was spotted before closing, we should report it
+     * instead of the close() return value.
+     */
+    if (f->last_error) {
+        ret = f->last_error;
+    }
+    g_free(f);
+    return ret;
+}
+
+static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
+{
+    /* check for adjacent buffer and coalesce them */
+    if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
+        f->iov[f->iovcnt - 1].iov_len) {
+        f->iov[f->iovcnt - 1].iov_len += size;
+    } else {
+        f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
+        f->iov[f->iovcnt++].iov_len = size;
+    }
+
+    if (f->iovcnt >= MAX_IOV_SIZE) {
+        qemu_fflush(f);
+    }
+}
+
+void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
+{
+    if (!f->ops->writev_buffer) {
+        qemu_put_buffer(f, buf, size);
+        return;
+    }
+
+    if (f->last_error) {
+        return;
+    }
+
+    f->bytes_xfer += size;
+    add_to_iovec(f, buf, size);
+}
+
+void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
+{
+    int l;
+
+    if (f->last_error) {
+        return;
+    }
+
+    while (size > 0) {
+        l = IO_BUF_SIZE - f->buf_index;
+        if (l > size) {
+            l = size;
+        }
+        memcpy(f->buf + f->buf_index, buf, l);
+        f->bytes_xfer += l;
+        if (f->ops->writev_buffer) {
+            add_to_iovec(f, f->buf + f->buf_index, l);
+        }
+        f->buf_index += l;
+        if (f->buf_index == IO_BUF_SIZE) {
+            qemu_fflush(f);
+        }
+        if (qemu_file_get_error(f)) {
+            break;
+        }
+        buf += l;
+        size -= l;
+    }
+}
+
+void qemu_put_byte(QEMUFile *f, int v)
+{
+    if (f->last_error) {
+        return;
+    }
+
+    f->buf[f->buf_index] = v;
+    f->bytes_xfer++;
+    if (f->ops->writev_buffer) {
+        add_to_iovec(f, f->buf + f->buf_index, 1);
+    }
+    f->buf_index++;
+    if (f->buf_index == IO_BUF_SIZE) {
+        qemu_fflush(f);
+    }
+}
+
+void qemu_file_skip(QEMUFile *f, int size)
+{
+    if (f->buf_index + size <= f->buf_size) {
+        f->buf_index += size;
+    }
+}
+
+int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
+{
+    int pending;
+    int index;
+
+    assert(!qemu_file_is_writable(f));
+
+    index = f->buf_index + offset;
+    pending = f->buf_size - index;
+    if (pending < size) {
+        qemu_fill_buffer(f);
+        index = f->buf_index + offset;
+        pending = f->buf_size - index;
+    }
+
+    if (pending <= 0) {
+        return 0;
+    }
+    if (size > pending) {
+        size = pending;
+    }
+
+    memcpy(buf, f->buf + index, size);
+    return size;
+}
+
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
+{
+    int pending = size;
+    int done = 0;
+
+    while (pending > 0) {
+        int res;
+
+        res = qemu_peek_buffer(f, buf, pending, 0);
+        if (res == 0) {
+            return done;
+        }
+        qemu_file_skip(f, res);
+        buf += res;
+        pending -= res;
+        done += res;
+    }
+    return done;
+}
+
+int qemu_peek_byte(QEMUFile *f, int offset)
+{
+    int index = f->buf_index + offset;
+
+    assert(!qemu_file_is_writable(f));
+
+    if (index >= f->buf_size) {
+        qemu_fill_buffer(f);
+        index = f->buf_index + offset;
+        if (index >= f->buf_size) {
+            return 0;
+        }
+    }
+    return f->buf[index];
+}
+
+int qemu_get_byte(QEMUFile *f)
+{
+    int result;
+
+    result = qemu_peek_byte(f, 0);
+    qemu_file_skip(f, 1);
+    return result;
+}
+
+int64_t qemu_ftell(QEMUFile *f)
+{
+    qemu_fflush(f);
+    return f->pos;
+}
+
+int qemu_file_rate_limit(QEMUFile *f)
+{
+    if (qemu_file_get_error(f)) {
+        return 1;
+    }
+    if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
+        return 1;
+    }
+    return 0;
+}
+
+int64_t qemu_file_get_rate_limit(QEMUFile *f)
+{
+    return f->xfer_limit;
+}
+
+void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
+{
+    f->xfer_limit = limit;
+}
+
+void qemu_file_reset_rate_limit(QEMUFile *f)
+{
+    f->bytes_xfer = 0;
+}
+
+void qemu_put_be16(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, v >> 8);
+    qemu_put_byte(f, v);
+}
+
+void qemu_put_be32(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, v >> 24);
+    qemu_put_byte(f, v >> 16);
+    qemu_put_byte(f, v >> 8);
+    qemu_put_byte(f, v);
+}
+
+void qemu_put_be64(QEMUFile *f, uint64_t v)
+{
+    qemu_put_be32(f, v >> 32);
+    qemu_put_be32(f, v);
+}
+
+unsigned int qemu_get_be16(QEMUFile *f)
+{
+    unsigned int v;
+    v = qemu_get_byte(f) << 8;
+    v |= qemu_get_byte(f);
+    return v;
+}
+
+unsigned int qemu_get_be32(QEMUFile *f)
+{
+    unsigned int v;
+    v = qemu_get_byte(f) << 24;
+    v |= qemu_get_byte(f) << 16;
+    v |= qemu_get_byte(f) << 8;
+    v |= qemu_get_byte(f);
+    return v;
+}
+
+uint64_t qemu_get_be64(QEMUFile *f)
+{
+    uint64_t v;
+    v = (uint64_t)qemu_get_be32(f) << 32;
+    v |= qemu_get_be32(f);
+    return v;
+}
diff --git a/savevm.c b/savevm.c
index 3f13a6a..8eeb5ef 100644
--- a/savevm.c
+++ b/savevm.c
@@ -114,396 +114,6 @@ void qemu_announce_self(void)
 /***********************************************************/
 /* savevm/loadvm support */
 
-#define IO_BUF_SIZE 32768
-#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
-
-struct QEMUFile {
-    const QEMUFileOps *ops;
-    void *opaque;
-
-    int64_t bytes_xfer;
-    int64_t xfer_limit;
-
-    int64_t pos; /* start of buffer when writing, end of buffer
-                    when reading */
-    int buf_index;
-    int buf_size; /* 0 when writing */
-    uint8_t buf[IO_BUF_SIZE];
-
-    struct iovec iov[MAX_IOV_SIZE];
-    unsigned int iovcnt;
-
-    int last_error;
-};
-
-typedef struct QEMUFileStdio {
-    FILE *stdio_file;
-    QEMUFile *file;
-} QEMUFileStdio;
-
-typedef struct QEMUFileSocket {
-    int fd;
-    QEMUFile *file;
-} QEMUFileSocket;
-
-static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
-                                    int64_t pos)
-{
-    QEMUFileSocket *s = opaque;
-    ssize_t len;
-    ssize_t size = iov_size(iov, iovcnt);
-
-    len = iov_send(s->fd, iov, iovcnt, 0, size);
-    if (len < size) {
-        len = -socket_error();
-    }
-    return len;
-}
-
-static int socket_get_fd(void *opaque)
-{
-    QEMUFileSocket *s = opaque;
-
-    return s->fd;
-}
-
-static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
-{
-    QEMUFileSocket *s = opaque;
-    ssize_t len;
-
-    for (;;) {
-        len = qemu_recv(s->fd, buf, size, 0);
-        if (len != -1) {
-            break;
-        }
-        if (socket_error() == EAGAIN) {
-            yield_until_fd_readable(s->fd);
-        } else if (socket_error() != EINTR) {
-            break;
-        }
-    }
-
-    if (len == -1) {
-        len = -socket_error();
-    }
-    return len;
-}
-
-static int socket_close(void *opaque)
-{
-    QEMUFileSocket *s = opaque;
-    closesocket(s->fd);
-    g_free(s);
-    return 0;
-}
-
-static int stdio_get_fd(void *opaque)
-{
-    QEMUFileStdio *s = opaque;
-
-    return fileno(s->stdio_file);
-}
-
-static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos,
-                            int size)
-{
-    QEMUFileStdio *s = opaque;
-    return fwrite(buf, 1, size, s->stdio_file);
-}
-
-static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
-{
-    QEMUFileStdio *s = opaque;
-    FILE *fp = s->stdio_file;
-    int bytes;
-
-    for (;;) {
-        clearerr(fp);
-        bytes = fread(buf, 1, size, fp);
-        if (bytes != 0 || !ferror(fp)) {
-            break;
-        }
-        if (errno == EAGAIN) {
-            yield_until_fd_readable(fileno(fp));
-        } else if (errno != EINTR) {
-            break;
-        }
-    }
-    return bytes;
-}
-
-static int stdio_pclose(void *opaque)
-{
-    QEMUFileStdio *s = opaque;
-    int ret;
-    ret = pclose(s->stdio_file);
-    if (ret == -1) {
-        ret = -errno;
-    } else if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
-        /* close succeeded, but non-zero exit code: */
-        ret = -EIO; /* fake errno value */
-    }
-    g_free(s);
-    return ret;
-}
-
-static int stdio_fclose(void *opaque)
-{
-    QEMUFileStdio *s = opaque;
-    int ret = 0;
-
-    if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
-        int fd = fileno(s->stdio_file);
-        struct stat st;
-
-        ret = fstat(fd, &st);
-        if (ret == 0 && S_ISREG(st.st_mode)) {
-            /*
-             * If the file handle is a regular file make sure the
-             * data is flushed to disk before signaling success.
-             */
-            ret = fsync(fd);
-            if (ret != 0) {
-                ret = -errno;
-                return ret;
-            }
-        }
-    }
-    if (fclose(s->stdio_file) == EOF) {
-        ret = -errno;
-    }
-    g_free(s);
-    return ret;
-}
-
-static const QEMUFileOps stdio_pipe_read_ops = {
-    .get_fd =     stdio_get_fd,
-    .get_buffer = stdio_get_buffer,
-    .close =      stdio_pclose
-};
-
-static const QEMUFileOps stdio_pipe_write_ops = {
-    .get_fd =     stdio_get_fd,
-    .put_buffer = stdio_put_buffer,
-    .close =      stdio_pclose
-};
-
-QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
-{
-    FILE *stdio_file;
-    QEMUFileStdio *s;
-
-    if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
-        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
-        return NULL;
-    }
-
-    stdio_file = popen(command, mode);
-    if (stdio_file == NULL) {
-        return NULL;
-    }
-
-    s = g_malloc0(sizeof(QEMUFileStdio));
-
-    s->stdio_file = stdio_file;
-
-    if (mode[0] == 'r') {
-        s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
-    } else {
-        s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
-    }
-    return s->file;
-}
-
-static const QEMUFileOps stdio_file_read_ops = {
-    .get_fd =     stdio_get_fd,
-    .get_buffer = stdio_get_buffer,
-    .close =      stdio_fclose
-};
-
-static const QEMUFileOps stdio_file_write_ops = {
-    .get_fd =     stdio_get_fd,
-    .put_buffer = stdio_put_buffer,
-    .close =      stdio_fclose
-};
-
-static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
-                                  int64_t pos)
-{
-    QEMUFileSocket *s = opaque;
-    ssize_t len, offset;
-    ssize_t size = iov_size(iov, iovcnt);
-    ssize_t total = 0;
-
-    assert(iovcnt > 0);
-    offset = 0;
-    while (size > 0) {
-        /* Find the next start position; skip all full-sized vector elements  */
-        while (offset >= iov[0].iov_len) {
-            offset -= iov[0].iov_len;
-            iov++, iovcnt--;
-        }
-
-        /* skip `offset' bytes from the (now) first element, undo it on exit */
-        assert(iovcnt > 0);
-        iov[0].iov_base += offset;
-        iov[0].iov_len -= offset;
-
-        do {
-            len = writev(s->fd, iov, iovcnt);
-        } while (len == -1 && errno == EINTR);
-        if (len == -1) {
-            return -errno;
-        }
-
-        /* Undo the changes above */
-        iov[0].iov_base -= offset;
-        iov[0].iov_len += offset;
-
-        /* Prepare for the next iteration */
-        offset += len;
-        total += len;
-        size -= len;
-    }
-
-    return total;
-}
-
-static int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
-{
-    QEMUFileSocket *s = opaque;
-    ssize_t len;
-
-    for (;;) {
-        len = read(s->fd, buf, size);
-        if (len != -1) {
-            break;
-        }
-        if (errno == EAGAIN) {
-            yield_until_fd_readable(s->fd);
-        } else if (errno != EINTR) {
-            break;
-        }
-    }
-
-    if (len == -1) {
-        len = -errno;
-    }
-    return len;
-}
-
-static int unix_close(void *opaque)
-{
-    QEMUFileSocket *s = opaque;
-    close(s->fd);
-    g_free(s);
-    return 0;
-}
-
-static const QEMUFileOps unix_read_ops = {
-    .get_fd =     socket_get_fd,
-    .get_buffer = unix_get_buffer,
-    .close =      unix_close
-};
-
-static const QEMUFileOps unix_write_ops = {
-    .get_fd =     socket_get_fd,
-    .writev_buffer = unix_writev_buffer,
-    .close =      unix_close
-};
-
-QEMUFile *qemu_fdopen(int fd, const char *mode)
-{
-    QEMUFileSocket *s;
-
-    if (mode == NULL ||
-        (mode[0] != 'r' && mode[0] != 'w') ||
-        mode[1] != 'b' || mode[2] != 0) {
-        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
-        return NULL;
-    }
-
-    s = g_malloc0(sizeof(QEMUFileSocket));
-    s->fd = fd;
-
-    if (mode[0] == 'r') {
-        s->file = qemu_fopen_ops(s, &unix_read_ops);
-    } else {
-        s->file = qemu_fopen_ops(s, &unix_write_ops);
-    }
-    return s->file;
-}
-
-static const QEMUFileOps socket_read_ops = {
-    .get_fd =     socket_get_fd,
-    .get_buffer = socket_get_buffer,
-    .close =      socket_close
-};
-
-static const QEMUFileOps socket_write_ops = {
-    .get_fd =     socket_get_fd,
-    .writev_buffer = socket_writev_buffer,
-    .close =      socket_close
-};
-
-bool qemu_file_mode_is_not_valid(const char *mode)
-{
-    if (mode == NULL ||
-        (mode[0] != 'r' && mode[0] != 'w') ||
-        mode[1] != 'b' || mode[2] != 0) {
-        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
-        return true;
-    }
-
-    return false;
-}
-
-QEMUFile *qemu_fopen_socket(int fd, const char *mode)
-{
-    QEMUFileSocket *s;
-
-    if (qemu_file_mode_is_not_valid(mode)) {
-        return NULL;
-    }
-
-    s = g_malloc0(sizeof(QEMUFileSocket));
-    s->fd = fd;
-    if (mode[0] == 'w') {
-        qemu_set_block(s->fd);
-        s->file = qemu_fopen_ops(s, &socket_write_ops);
-    } else {
-        s->file = qemu_fopen_ops(s, &socket_read_ops);
-    }
-    return s->file;
-}
-
-QEMUFile *qemu_fopen(const char *filename, const char *mode)
-{
-    QEMUFileStdio *s;
-
-    if (qemu_file_mode_is_not_valid(mode)) {
-        return NULL;
-    }
-
-    s = g_malloc0(sizeof(QEMUFileStdio));
-
-    s->stdio_file = fopen(filename, mode);
-    if (!s->stdio_file) {
-        goto fail;
-    }
-
-    if (mode[0] == 'w') {
-        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
-    } else {
-        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
-    }
-    return s->file;
-fail:
-    g_free(s);
-    return NULL;
-}
-
 static ssize_t block_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
                                    int64_t pos)
 {
@@ -555,436 +165,6 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
     return qemu_fopen_ops(bs, &bdrv_read_ops);
 }
 
-QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops)
-{
-    QEMUFile *f;
-
-    f = g_malloc0(sizeof(QEMUFile));
-
-    f->opaque = opaque;
-    f->ops = ops;
-    return f;
-}
-
-/*
- * Get last error for stream f
- *
- * Return negative error value if there has been an error on previous
- * operations, return 0 if no error happened.
- *
- */
-int qemu_file_get_error(QEMUFile *f)
-{
-    return f->last_error;
-}
-
-void qemu_file_set_error(QEMUFile *f, int ret)
-{
-    if (f->last_error == 0) {
-        f->last_error = ret;
-    }
-}
-
-static inline bool qemu_file_is_writable(QEMUFile *f)
-{
-    return f->ops->writev_buffer || f->ops->put_buffer;
-}
-
-/**
- * Flushes QEMUFile buffer
- *
- * If there is writev_buffer QEMUFileOps it uses it otherwise uses
- * put_buffer ops.
- */
-void qemu_fflush(QEMUFile *f)
-{
-    ssize_t ret = 0;
-
-    if (!qemu_file_is_writable(f)) {
-        return;
-    }
-
-    if (f->ops->writev_buffer) {
-        if (f->iovcnt > 0) {
-            ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos);
-        }
-    } else {
-        if (f->buf_index > 0) {
-            ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
-        }
-    }
-    if (ret >= 0) {
-        f->pos += ret;
-    }
-    f->buf_index = 0;
-    f->iovcnt = 0;
-    if (ret < 0) {
-        qemu_file_set_error(f, ret);
-    }
-}
-
-void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
-{
-    int ret = 0;
-
-    if (f->ops->before_ram_iterate) {
-        ret = f->ops->before_ram_iterate(f, f->opaque, flags);
-        if (ret < 0) {
-            qemu_file_set_error(f, ret);
-        }
-    }
-}
-
-void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
-{
-    int ret = 0;
-
-    if (f->ops->after_ram_iterate) {
-        ret = f->ops->after_ram_iterate(f, f->opaque, flags);
-        if (ret < 0) {
-            qemu_file_set_error(f, ret);
-        }
-    }
-}
-
-void ram_control_load_hook(QEMUFile *f, uint64_t flags)
-{
-    int ret = -EINVAL;
-
-    if (f->ops->hook_ram_load) {
-        ret = f->ops->hook_ram_load(f, f->opaque, flags);
-        if (ret < 0) {
-            qemu_file_set_error(f, ret);
-        }
-    } else {
-        qemu_file_set_error(f, ret);
-    }
-}
-
-size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
-                         ram_addr_t offset, size_t size, int *bytes_sent)
-{
-    if (f->ops->save_page) {
-        int ret = f->ops->save_page(f, f->opaque, block_offset,
-                                    offset, size, bytes_sent);
-
-        if (ret != RAM_SAVE_CONTROL_DELAYED) {
-            if (bytes_sent && *bytes_sent > 0) {
-                qemu_update_position(f, *bytes_sent);
-            } else if (ret < 0) {
-                qemu_file_set_error(f, ret);
-            }
-        }
-
-        return ret;
-    }
-
-    return RAM_SAVE_CONTROL_NOT_SUPP;
-}
-
-static void qemu_fill_buffer(QEMUFile *f)
-{
-    int len;
-    int pending;
-
-    assert(!qemu_file_is_writable(f));
-
-    pending = f->buf_size - f->buf_index;
-    if (pending > 0) {
-        memmove(f->buf, f->buf + f->buf_index, pending);
-    }
-    f->buf_index = 0;
-    f->buf_size = pending;
-
-    len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos,
-                        IO_BUF_SIZE - pending);
-    if (len > 0) {
-        f->buf_size += len;
-        f->pos += len;
-    } else if (len == 0) {
-        qemu_file_set_error(f, -EIO);
-    } else if (len != -EAGAIN) {
-        qemu_file_set_error(f, len);
-    }
-}
-
-int qemu_get_fd(QEMUFile *f)
-{
-    if (f->ops->get_fd) {
-        return f->ops->get_fd(f->opaque);
-    }
-    return -1;
-}
-
-void qemu_update_position(QEMUFile *f, size_t size)
-{
-    f->pos += size;
-}
-
-/** Closes the file
- *
- * Returns negative error value if any error happened on previous operations or
- * while closing the file. Returns 0 or positive number on success.
- *
- * The meaning of return value on success depends on the specific backend
- * being used.
- */
-int qemu_fclose(QEMUFile *f)
-{
-    int ret;
-    qemu_fflush(f);
-    ret = qemu_file_get_error(f);
-
-    if (f->ops->close) {
-        int ret2 = f->ops->close(f->opaque);
-        if (ret >= 0) {
-            ret = ret2;
-        }
-    }
-    /* If any error was spotted before closing, we should report it
-     * instead of the close() return value.
-     */
-    if (f->last_error) {
-        ret = f->last_error;
-    }
-    g_free(f);
-    return ret;
-}
-
-static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
-{
-    /* check for adjacent buffer and coalesce them */
-    if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
-        f->iov[f->iovcnt - 1].iov_len) {
-        f->iov[f->iovcnt - 1].iov_len += size;
-    } else {
-        f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
-        f->iov[f->iovcnt++].iov_len = size;
-    }
-
-    if (f->iovcnt >= MAX_IOV_SIZE) {
-        qemu_fflush(f);
-    }
-}
-
-void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
-{
-    if (!f->ops->writev_buffer) {
-        qemu_put_buffer(f, buf, size);
-        return;
-    }
-
-    if (f->last_error) {
-        return;
-    }
-
-    f->bytes_xfer += size;
-    add_to_iovec(f, buf, size);
-}
-
-void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
-{
-    int l;
-
-    if (f->last_error) {
-        return;
-    }
-
-    while (size > 0) {
-        l = IO_BUF_SIZE - f->buf_index;
-        if (l > size) {
-            l = size;
-        }
-        memcpy(f->buf + f->buf_index, buf, l);
-        f->bytes_xfer += l;
-        if (f->ops->writev_buffer) {
-            add_to_iovec(f, f->buf + f->buf_index, l);
-        }
-        f->buf_index += l;
-        if (f->buf_index == IO_BUF_SIZE) {
-            qemu_fflush(f);
-        }
-        if (qemu_file_get_error(f)) {
-            break;
-        }
-        buf += l;
-        size -= l;
-    }
-}
-
-void qemu_put_byte(QEMUFile *f, int v)
-{
-    if (f->last_error) {
-        return;
-    }
-
-    f->buf[f->buf_index] = v;
-    f->bytes_xfer++;
-    if (f->ops->writev_buffer) {
-        add_to_iovec(f, f->buf + f->buf_index, 1);
-    }
-    f->buf_index++;
-    if (f->buf_index == IO_BUF_SIZE) {
-        qemu_fflush(f);
-    }
-}
-
-void qemu_file_skip(QEMUFile *f, int size)
-{
-    if (f->buf_index + size <= f->buf_size) {
-        f->buf_index += size;
-    }
-}
-
-int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
-{
-    int pending;
-    int index;
-
-    assert(!qemu_file_is_writable(f));
-
-    index = f->buf_index + offset;
-    pending = f->buf_size - index;
-    if (pending < size) {
-        qemu_fill_buffer(f);
-        index = f->buf_index + offset;
-        pending = f->buf_size - index;
-    }
-
-    if (pending <= 0) {
-        return 0;
-    }
-    if (size > pending) {
-        size = pending;
-    }
-
-    memcpy(buf, f->buf + index, size);
-    return size;
-}
-
-int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
-{
-    int pending = size;
-    int done = 0;
-
-    while (pending > 0) {
-        int res;
-
-        res = qemu_peek_buffer(f, buf, pending, 0);
-        if (res == 0) {
-            return done;
-        }
-        qemu_file_skip(f, res);
-        buf += res;
-        pending -= res;
-        done += res;
-    }
-    return done;
-}
-
-int qemu_peek_byte(QEMUFile *f, int offset)
-{
-    int index = f->buf_index + offset;
-
-    assert(!qemu_file_is_writable(f));
-
-    if (index >= f->buf_size) {
-        qemu_fill_buffer(f);
-        index = f->buf_index + offset;
-        if (index >= f->buf_size) {
-            return 0;
-        }
-    }
-    return f->buf[index];
-}
-
-int qemu_get_byte(QEMUFile *f)
-{
-    int result;
-
-    result = qemu_peek_byte(f, 0);
-    qemu_file_skip(f, 1);
-    return result;
-}
-
-int64_t qemu_ftell(QEMUFile *f)
-{
-    qemu_fflush(f);
-    return f->pos;
-}
-
-int qemu_file_rate_limit(QEMUFile *f)
-{
-    if (qemu_file_get_error(f)) {
-        return 1;
-    }
-    if (f->xfer_limit > 0 && f->bytes_xfer > f->xfer_limit) {
-        return 1;
-    }
-    return 0;
-}
-
-int64_t qemu_file_get_rate_limit(QEMUFile *f)
-{
-    return f->xfer_limit;
-}
-
-void qemu_file_set_rate_limit(QEMUFile *f, int64_t limit)
-{
-    f->xfer_limit = limit;
-}
-
-void qemu_file_reset_rate_limit(QEMUFile *f)
-{
-    f->bytes_xfer = 0;
-}
-
-void qemu_put_be16(QEMUFile *f, unsigned int v)
-{
-    qemu_put_byte(f, v >> 8);
-    qemu_put_byte(f, v);
-}
-
-void qemu_put_be32(QEMUFile *f, unsigned int v)
-{
-    qemu_put_byte(f, v >> 24);
-    qemu_put_byte(f, v >> 16);
-    qemu_put_byte(f, v >> 8);
-    qemu_put_byte(f, v);
-}
-
-void qemu_put_be64(QEMUFile *f, uint64_t v)
-{
-    qemu_put_be32(f, v >> 32);
-    qemu_put_be32(f, v);
-}
-
-unsigned int qemu_get_be16(QEMUFile *f)
-{
-    unsigned int v;
-    v = qemu_get_byte(f) << 8;
-    v |= qemu_get_byte(f);
-    return v;
-}
-
-unsigned int qemu_get_be32(QEMUFile *f)
-{
-    unsigned int v;
-    v = qemu_get_byte(f) << 24;
-    v |= qemu_get_byte(f) << 16;
-    v |= qemu_get_byte(f) << 8;
-    v |= qemu_get_byte(f);
-    return v;
-}
-
-uint64_t qemu_get_be64(QEMUFile *f)
-{
-    uint64_t v;
-    v = (uint64_t)qemu_get_be32(f) << 32;
-    v |= qemu_get_be32(f);
-    return v;
-}
-
 
 /* timer */
 
commit b6fcfa59fa6ad6d61603e701e006d4ec8f4c9d11
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:15 2013 -0200

    vmstate: Move VMState code to vmstate.c
    
    This will allow unit tests to be written for VMState code without
    pulling dependencies from the savevm code.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index 2b6c1fe..23eda2b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,6 +51,7 @@ common-obj-$(CONFIG_POSIX) += os-posix.o
 common-obj-$(CONFIG_LINUX) += fsdev/
 
 common-obj-y += migration.o migration-tcp.o
+common-obj-y += vmstate.o
 common-obj-$(CONFIG_RDMA) += migration-rdma.o
 common-obj-y += qemu-char.o #aio.o
 common-obj-y += block-migration.o
diff --git a/savevm.c b/savevm.c
index bdb90ef..3f13a6a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -38,7 +38,6 @@
 #include "exec/memory.h"
 #include "qmp-commands.h"
 #include "trace.h"
-#include "qemu/bitops.h"
 #include "qemu/iov.h"
 #include "block/snapshot.h"
 #include "block/qapi.h"
@@ -1010,344 +1009,6 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
 }
 
 
-/* bool */
-
-static int get_bool(QEMUFile *f, void *pv, size_t size)
-{
-    bool *v = pv;
-    *v = qemu_get_byte(f);
-    return 0;
-}
-
-static void put_bool(QEMUFile *f, void *pv, size_t size)
-{
-    bool *v = pv;
-    qemu_put_byte(f, *v);
-}
-
-const VMStateInfo vmstate_info_bool = {
-    .name = "bool",
-    .get  = get_bool,
-    .put  = put_bool,
-};
-
-/* 8 bit int */
-
-static int get_int8(QEMUFile *f, void *pv, size_t size)
-{
-    int8_t *v = pv;
-    qemu_get_s8s(f, v);
-    return 0;
-}
-
-static void put_int8(QEMUFile *f, void *pv, size_t size)
-{
-    int8_t *v = pv;
-    qemu_put_s8s(f, v);
-}
-
-const VMStateInfo vmstate_info_int8 = {
-    .name = "int8",
-    .get  = get_int8,
-    .put  = put_int8,
-};
-
-/* 16 bit int */
-
-static int get_int16(QEMUFile *f, void *pv, size_t size)
-{
-    int16_t *v = pv;
-    qemu_get_sbe16s(f, v);
-    return 0;
-}
-
-static void put_int16(QEMUFile *f, void *pv, size_t size)
-{
-    int16_t *v = pv;
-    qemu_put_sbe16s(f, v);
-}
-
-const VMStateInfo vmstate_info_int16 = {
-    .name = "int16",
-    .get  = get_int16,
-    .put  = put_int16,
-};
-
-/* 32 bit int */
-
-static int get_int32(QEMUFile *f, void *pv, size_t size)
-{
-    int32_t *v = pv;
-    qemu_get_sbe32s(f, v);
-    return 0;
-}
-
-static void put_int32(QEMUFile *f, void *pv, size_t size)
-{
-    int32_t *v = pv;
-    qemu_put_sbe32s(f, v);
-}
-
-const VMStateInfo vmstate_info_int32 = {
-    .name = "int32",
-    .get  = get_int32,
-    .put  = put_int32,
-};
-
-/* 32 bit int. See that the received value is the same than the one
-   in the field */
-
-static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
-{
-    int32_t *v = pv;
-    int32_t v2;
-    qemu_get_sbe32s(f, &v2);
-
-    if (*v == v2) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_int32_equal = {
-    .name = "int32 equal",
-    .get  = get_int32_equal,
-    .put  = put_int32,
-};
-
-/* 32 bit int. See that the received value is the less or the same
-   than the one in the field */
-
-static int get_int32_le(QEMUFile *f, void *pv, size_t size)
-{
-    int32_t *old = pv;
-    int32_t new;
-    qemu_get_sbe32s(f, &new);
-
-    if (*old <= new) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_int32_le = {
-    .name = "int32 equal",
-    .get  = get_int32_le,
-    .put  = put_int32,
-};
-
-/* 64 bit int */
-
-static int get_int64(QEMUFile *f, void *pv, size_t size)
-{
-    int64_t *v = pv;
-    qemu_get_sbe64s(f, v);
-    return 0;
-}
-
-static void put_int64(QEMUFile *f, void *pv, size_t size)
-{
-    int64_t *v = pv;
-    qemu_put_sbe64s(f, v);
-}
-
-const VMStateInfo vmstate_info_int64 = {
-    .name = "int64",
-    .get  = get_int64,
-    .put  = put_int64,
-};
-
-/* 8 bit unsigned int */
-
-static int get_uint8(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t *v = pv;
-    qemu_get_8s(f, v);
-    return 0;
-}
-
-static void put_uint8(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t *v = pv;
-    qemu_put_8s(f, v);
-}
-
-const VMStateInfo vmstate_info_uint8 = {
-    .name = "uint8",
-    .get  = get_uint8,
-    .put  = put_uint8,
-};
-
-/* 16 bit unsigned int */
-
-static int get_uint16(QEMUFile *f, void *pv, size_t size)
-{
-    uint16_t *v = pv;
-    qemu_get_be16s(f, v);
-    return 0;
-}
-
-static void put_uint16(QEMUFile *f, void *pv, size_t size)
-{
-    uint16_t *v = pv;
-    qemu_put_be16s(f, v);
-}
-
-const VMStateInfo vmstate_info_uint16 = {
-    .name = "uint16",
-    .get  = get_uint16,
-    .put  = put_uint16,
-};
-
-/* 32 bit unsigned int */
-
-static int get_uint32(QEMUFile *f, void *pv, size_t size)
-{
-    uint32_t *v = pv;
-    qemu_get_be32s(f, v);
-    return 0;
-}
-
-static void put_uint32(QEMUFile *f, void *pv, size_t size)
-{
-    uint32_t *v = pv;
-    qemu_put_be32s(f, v);
-}
-
-const VMStateInfo vmstate_info_uint32 = {
-    .name = "uint32",
-    .get  = get_uint32,
-    .put  = put_uint32,
-};
-
-/* 32 bit uint. See that the received value is the same than the one
-   in the field */
-
-static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
-{
-    uint32_t *v = pv;
-    uint32_t v2;
-    qemu_get_be32s(f, &v2);
-
-    if (*v == v2) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_uint32_equal = {
-    .name = "uint32 equal",
-    .get  = get_uint32_equal,
-    .put  = put_uint32,
-};
-
-/* 64 bit unsigned int */
-
-static int get_uint64(QEMUFile *f, void *pv, size_t size)
-{
-    uint64_t *v = pv;
-    qemu_get_be64s(f, v);
-    return 0;
-}
-
-static void put_uint64(QEMUFile *f, void *pv, size_t size)
-{
-    uint64_t *v = pv;
-    qemu_put_be64s(f, v);
-}
-
-const VMStateInfo vmstate_info_uint64 = {
-    .name = "uint64",
-    .get  = get_uint64,
-    .put  = put_uint64,
-};
-
-/* 64 bit unsigned int. See that the received value is the same than the one
-   in the field */
-
-static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
-{
-    uint64_t *v = pv;
-    uint64_t v2;
-    qemu_get_be64s(f, &v2);
-
-    if (*v == v2) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_uint64_equal = {
-    .name = "int64 equal",
-    .get  = get_uint64_equal,
-    .put  = put_uint64,
-};
-
-/* 8 bit int. See that the received value is the same than the one
-   in the field */
-
-static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t *v = pv;
-    uint8_t v2;
-    qemu_get_8s(f, &v2);
-
-    if (*v == v2) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_uint8_equal = {
-    .name = "uint8 equal",
-    .get  = get_uint8_equal,
-    .put  = put_uint8,
-};
-
-/* 16 bit unsigned int int. See that the received value is the same than the one
-   in the field */
-
-static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
-{
-    uint16_t *v = pv;
-    uint16_t v2;
-    qemu_get_be16s(f, &v2);
-
-    if (*v == v2) {
-        return 0;
-    }
-    return -EINVAL;
-}
-
-const VMStateInfo vmstate_info_uint16_equal = {
-    .name = "uint16 equal",
-    .get  = get_uint16_equal,
-    .put  = put_uint16,
-};
-
-/* floating point */
-
-static int get_float64(QEMUFile *f, void *pv, size_t size)
-{
-    float64 *v = pv;
-
-    *v = make_float64(qemu_get_be64(f));
-    return 0;
-}
-
-static void put_float64(QEMUFile *f, void *pv, size_t size)
-{
-    uint64_t *v = pv;
-
-    qemu_put_be64(f, float64_val(*v));
-}
-
-const VMStateInfo vmstate_info_float64 = {
-    .name = "float64",
-    .get  = get_float64,
-    .put  = put_float64,
-};
-
 /* timers  */
 
 static int get_timer(QEMUFile *f, void *pv, size_t size)
@@ -1369,100 +1030,6 @@ const VMStateInfo vmstate_info_timer = {
     .put  = put_timer,
 };
 
-/* uint8_t buffers */
-
-static int get_buffer(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t *v = pv;
-    qemu_get_buffer(f, v, size);
-    return 0;
-}
-
-static void put_buffer(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t *v = pv;
-    qemu_put_buffer(f, v, size);
-}
-
-const VMStateInfo vmstate_info_buffer = {
-    .name = "buffer",
-    .get  = get_buffer,
-    .put  = put_buffer,
-};
-
-/* unused buffers: space that was used for some fields that are
-   not useful anymore */
-
-static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
-{
-    uint8_t buf[1024];
-    int block_len;
-
-    while (size > 0) {
-        block_len = MIN(sizeof(buf), size);
-        size -= block_len;
-        qemu_get_buffer(f, buf, block_len);
-    }
-   return 0;
-}
-
-static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
-{
-    static const uint8_t buf[1024];
-    int block_len;
-
-    while (size > 0) {
-        block_len = MIN(sizeof(buf), size);
-        size -= block_len;
-        qemu_put_buffer(f, buf, block_len);
-    }
-}
-
-const VMStateInfo vmstate_info_unused_buffer = {
-    .name = "unused_buffer",
-    .get  = get_unused_buffer,
-    .put  = put_unused_buffer,
-};
-
-/* bitmaps (as defined by bitmap.h). Note that size here is the size
- * of the bitmap in bits. The on-the-wire format of a bitmap is 64
- * bit words with the bits in big endian order. The in-memory format
- * is an array of 'unsigned long', which may be either 32 or 64 bits.
- */
-/* This is the number of 64 bit words sent over the wire */
-#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
-static int get_bitmap(QEMUFile *f, void *pv, size_t size)
-{
-    unsigned long *bmp = pv;
-    int i, idx = 0;
-    for (i = 0; i < BITS_TO_U64S(size); i++) {
-        uint64_t w = qemu_get_be64(f);
-        bmp[idx++] = w;
-        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
-            bmp[idx++] = w >> 32;
-        }
-    }
-    return 0;
-}
-
-static void put_bitmap(QEMUFile *f, void *pv, size_t size)
-{
-    unsigned long *bmp = pv;
-    int i, idx = 0;
-    for (i = 0; i < BITS_TO_U64S(size); i++) {
-        uint64_t w = bmp[idx++];
-        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
-            w |= ((uint64_t)bmp[idx++]) << 32;
-        }
-        qemu_put_be64(f, w);
-    }
-}
-
-const VMStateInfo vmstate_info_bitmap = {
-    .name = "bitmap",
-    .get = get_bitmap,
-    .put = put_bitmap,
-};
 
 typedef struct CompatEntry {
     char idstr[256];
@@ -1676,144 +1243,6 @@ void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
     }
 }
 
-static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
-                                    void *opaque);
-static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
-                                   void *opaque);
-
-int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
-                       void *opaque, int version_id)
-{
-    VMStateField *field = vmsd->fields;
-    int ret;
-
-    if (version_id > vmsd->version_id) {
-        return -EINVAL;
-    }
-    if (version_id < vmsd->minimum_version_id_old) {
-        return -EINVAL;
-    }
-    if  (version_id < vmsd->minimum_version_id) {
-        return vmsd->load_state_old(f, opaque, version_id);
-    }
-    if (vmsd->pre_load) {
-        int ret = vmsd->pre_load(opaque);
-        if (ret) {
-            return ret;
-        }
-    }
-    while (field->name) {
-        if ((field->field_exists &&
-             field->field_exists(opaque, version_id)) ||
-            (!field->field_exists &&
-             field->version_id <= version_id)) {
-            void *base_addr = opaque + field->offset;
-            int i, n_elems = 1;
-            int size = field->size;
-
-            if (field->flags & VMS_VBUFFER) {
-                size = *(int32_t *)(opaque+field->size_offset);
-                if (field->flags & VMS_MULTIPLY) {
-                    size *= field->size;
-                }
-            }
-            if (field->flags & VMS_ARRAY) {
-                n_elems = field->num;
-            } else if (field->flags & VMS_VARRAY_INT32) {
-                n_elems = *(int32_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT32) {
-                n_elems = *(uint32_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT16) {
-                n_elems = *(uint16_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT8) {
-                n_elems = *(uint8_t *)(opaque+field->num_offset);
-            }
-            if (field->flags & VMS_POINTER) {
-                base_addr = *(void **)base_addr + field->start;
-            }
-            for (i = 0; i < n_elems; i++) {
-                void *addr = base_addr + size * i;
-
-                if (field->flags & VMS_ARRAY_OF_POINTER) {
-                    addr = *(void **)addr;
-                }
-                if (field->flags & VMS_STRUCT) {
-                    ret = vmstate_load_state(f, field->vmsd, addr,
-                                             field->vmsd->version_id);
-                } else {
-                    ret = field->info->get(f, addr, size);
-
-                }
-                if (ret < 0) {
-                    return ret;
-                }
-            }
-        }
-        field++;
-    }
-    ret = vmstate_subsection_load(f, vmsd, opaque);
-    if (ret != 0) {
-        return ret;
-    }
-    if (vmsd->post_load) {
-        return vmsd->post_load(opaque, version_id);
-    }
-    return 0;
-}
-
-void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
-                        void *opaque)
-{
-    VMStateField *field = vmsd->fields;
-
-    if (vmsd->pre_save) {
-        vmsd->pre_save(opaque);
-    }
-    while (field->name) {
-        if (!field->field_exists ||
-            field->field_exists(opaque, vmsd->version_id)) {
-            void *base_addr = opaque + field->offset;
-            int i, n_elems = 1;
-            int size = field->size;
-
-            if (field->flags & VMS_VBUFFER) {
-                size = *(int32_t *)(opaque+field->size_offset);
-                if (field->flags & VMS_MULTIPLY) {
-                    size *= field->size;
-                }
-            }
-            if (field->flags & VMS_ARRAY) {
-                n_elems = field->num;
-            } else if (field->flags & VMS_VARRAY_INT32) {
-                n_elems = *(int32_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT32) {
-                n_elems = *(uint32_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT16) {
-                n_elems = *(uint16_t *)(opaque+field->num_offset);
-            } else if (field->flags & VMS_VARRAY_UINT8) {
-                n_elems = *(uint8_t *)(opaque+field->num_offset);
-            }
-            if (field->flags & VMS_POINTER) {
-                base_addr = *(void **)base_addr + field->start;
-            }
-            for (i = 0; i < n_elems; i++) {
-                void *addr = base_addr + size * i;
-
-                if (field->flags & VMS_ARRAY_OF_POINTER) {
-                    addr = *(void **)addr;
-                }
-                if (field->flags & VMS_STRUCT) {
-                    vmstate_save_state(f, field->vmsd, addr);
-                } else {
-                    field->info->put(f, addr, size);
-                }
-            }
-        }
-        field++;
-    }
-    vmstate_subsection_save(f, vmsd, opaque);
-}
-
 static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
 {
     if (!se->vmsd) {         /* Old style */
@@ -2114,80 +1543,6 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
     return NULL;
 }
 
-static const VMStateDescription *
-    vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
-{
-    while (sub && sub->needed) {
-        if (strcmp(idstr, sub->vmsd->name) == 0) {
-            return sub->vmsd;
-        }
-        sub++;
-    }
-    return NULL;
-}
-
-static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
-                                   void *opaque)
-{
-    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
-        char idstr[256];
-        int ret;
-        uint8_t version_id, len, size;
-        const VMStateDescription *sub_vmsd;
-
-        len = qemu_peek_byte(f, 1);
-        if (len < strlen(vmsd->name) + 1) {
-            /* subsection name has be be "section_name/a" */
-            return 0;
-        }
-        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
-        if (size != len) {
-            return 0;
-        }
-        idstr[size] = 0;
-
-        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
-            /* it don't have a valid subsection name */
-            return 0;
-        }
-        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
-        if (sub_vmsd == NULL) {
-            return -ENOENT;
-        }
-        qemu_file_skip(f, 1); /* subsection */
-        qemu_file_skip(f, 1); /* len */
-        qemu_file_skip(f, len); /* idstr */
-        version_id = qemu_get_be32(f);
-
-        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
-        if (ret) {
-            return ret;
-        }
-    }
-    return 0;
-}
-
-static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
-                                    void *opaque)
-{
-    const VMStateSubsection *sub = vmsd->subsections;
-
-    while (sub && sub->needed) {
-        if (sub->needed(opaque)) {
-            const VMStateDescription *vmsd = sub->vmsd;
-            uint8_t len;
-
-            qemu_put_byte(f, QEMU_VM_SUBSECTION);
-            len = strlen(vmsd->name);
-            qemu_put_byte(f, len);
-            qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
-            qemu_put_be32(f, vmsd->version_id);
-            vmstate_save_state(f, vmsd, opaque);
-        }
-        sub++;
-    }
-}
-
 typedef struct LoadStateEntry {
     QLIST_ENTRY(LoadStateEntry) entry;
     SaveStateEntry *se;
diff --git a/vmstate.c b/vmstate.c
new file mode 100644
index 0000000..284b080
--- /dev/null
+++ b/vmstate.c
@@ -0,0 +1,650 @@
+#include "qemu-common.h"
+#include "migration/migration.h"
+#include "migration/qemu-file.h"
+#include "migration/vmstate.h"
+#include "qemu/bitops.h"
+
+static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
+                                    void *opaque);
+static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
+                                   void *opaque);
+
+int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
+                       void *opaque, int version_id)
+{
+    VMStateField *field = vmsd->fields;
+    int ret;
+
+    if (version_id > vmsd->version_id) {
+        return -EINVAL;
+    }
+    if (version_id < vmsd->minimum_version_id_old) {
+        return -EINVAL;
+    }
+    if  (version_id < vmsd->minimum_version_id) {
+        return vmsd->load_state_old(f, opaque, version_id);
+    }
+    if (vmsd->pre_load) {
+        int ret = vmsd->pre_load(opaque);
+        if (ret) {
+            return ret;
+        }
+    }
+    while (field->name) {
+        if ((field->field_exists &&
+             field->field_exists(opaque, version_id)) ||
+            (!field->field_exists &&
+             field->version_id <= version_id)) {
+            void *base_addr = opaque + field->offset;
+            int i, n_elems = 1;
+            int size = field->size;
+
+            if (field->flags & VMS_VBUFFER) {
+                size = *(int32_t *)(opaque+field->size_offset);
+                if (field->flags & VMS_MULTIPLY) {
+                    size *= field->size;
+                }
+            }
+            if (field->flags & VMS_ARRAY) {
+                n_elems = field->num;
+            } else if (field->flags & VMS_VARRAY_INT32) {
+                n_elems = *(int32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT32) {
+                n_elems = *(uint32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT16) {
+                n_elems = *(uint16_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT8) {
+                n_elems = *(uint8_t *)(opaque+field->num_offset);
+            }
+            if (field->flags & VMS_POINTER) {
+                base_addr = *(void **)base_addr + field->start;
+            }
+            for (i = 0; i < n_elems; i++) {
+                void *addr = base_addr + size * i;
+
+                if (field->flags & VMS_ARRAY_OF_POINTER) {
+                    addr = *(void **)addr;
+                }
+                if (field->flags & VMS_STRUCT) {
+                    ret = vmstate_load_state(f, field->vmsd, addr,
+                                             field->vmsd->version_id);
+                } else {
+                    ret = field->info->get(f, addr, size);
+
+                }
+                if (ret < 0) {
+                    return ret;
+                }
+            }
+        }
+        field++;
+    }
+    ret = vmstate_subsection_load(f, vmsd, opaque);
+    if (ret != 0) {
+        return ret;
+    }
+    if (vmsd->post_load) {
+        return vmsd->post_load(opaque, version_id);
+    }
+    return 0;
+}
+
+void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
+                        void *opaque)
+{
+    VMStateField *field = vmsd->fields;
+
+    if (vmsd->pre_save) {
+        vmsd->pre_save(opaque);
+    }
+    while (field->name) {
+        if (!field->field_exists ||
+            field->field_exists(opaque, vmsd->version_id)) {
+            void *base_addr = opaque + field->offset;
+            int i, n_elems = 1;
+            int size = field->size;
+
+            if (field->flags & VMS_VBUFFER) {
+                size = *(int32_t *)(opaque+field->size_offset);
+                if (field->flags & VMS_MULTIPLY) {
+                    size *= field->size;
+                }
+            }
+            if (field->flags & VMS_ARRAY) {
+                n_elems = field->num;
+            } else if (field->flags & VMS_VARRAY_INT32) {
+                n_elems = *(int32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT32) {
+                n_elems = *(uint32_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT16) {
+                n_elems = *(uint16_t *)(opaque+field->num_offset);
+            } else if (field->flags & VMS_VARRAY_UINT8) {
+                n_elems = *(uint8_t *)(opaque+field->num_offset);
+            }
+            if (field->flags & VMS_POINTER) {
+                base_addr = *(void **)base_addr + field->start;
+            }
+            for (i = 0; i < n_elems; i++) {
+                void *addr = base_addr + size * i;
+
+                if (field->flags & VMS_ARRAY_OF_POINTER) {
+                    addr = *(void **)addr;
+                }
+                if (field->flags & VMS_STRUCT) {
+                    vmstate_save_state(f, field->vmsd, addr);
+                } else {
+                    field->info->put(f, addr, size);
+                }
+            }
+        }
+        field++;
+    }
+    vmstate_subsection_save(f, vmsd, opaque);
+}
+
+static const VMStateDescription *
+    vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
+{
+    while (sub && sub->needed) {
+        if (strcmp(idstr, sub->vmsd->name) == 0) {
+            return sub->vmsd;
+        }
+        sub++;
+    }
+    return NULL;
+}
+
+static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
+                                   void *opaque)
+{
+    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
+        char idstr[256];
+        int ret;
+        uint8_t version_id, len, size;
+        const VMStateDescription *sub_vmsd;
+
+        len = qemu_peek_byte(f, 1);
+        if (len < strlen(vmsd->name) + 1) {
+            /* subsection name has be be "section_name/a" */
+            return 0;
+        }
+        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
+        if (size != len) {
+            return 0;
+        }
+        idstr[size] = 0;
+
+        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
+            /* it don't have a valid subsection name */
+            return 0;
+        }
+        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
+        if (sub_vmsd == NULL) {
+            return -ENOENT;
+        }
+        qemu_file_skip(f, 1); /* subsection */
+        qemu_file_skip(f, 1); /* len */
+        qemu_file_skip(f, len); /* idstr */
+        version_id = qemu_get_be32(f);
+
+        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
+        if (ret) {
+            return ret;
+        }
+    }
+    return 0;
+}
+
+static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
+                                    void *opaque)
+{
+    const VMStateSubsection *sub = vmsd->subsections;
+
+    while (sub && sub->needed) {
+        if (sub->needed(opaque)) {
+            const VMStateDescription *vmsd = sub->vmsd;
+            uint8_t len;
+
+            qemu_put_byte(f, QEMU_VM_SUBSECTION);
+            len = strlen(vmsd->name);
+            qemu_put_byte(f, len);
+            qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
+            qemu_put_be32(f, vmsd->version_id);
+            vmstate_save_state(f, vmsd, opaque);
+        }
+        sub++;
+    }
+}
+
+/* bool */
+
+static int get_bool(QEMUFile *f, void *pv, size_t size)
+{
+    bool *v = pv;
+    *v = qemu_get_byte(f);
+    return 0;
+}
+
+static void put_bool(QEMUFile *f, void *pv, size_t size)
+{
+    bool *v = pv;
+    qemu_put_byte(f, *v);
+}
+
+const VMStateInfo vmstate_info_bool = {
+    .name = "bool",
+    .get  = get_bool,
+    .put  = put_bool,
+};
+
+/* 8 bit int */
+
+static int get_int8(QEMUFile *f, void *pv, size_t size)
+{
+    int8_t *v = pv;
+    qemu_get_s8s(f, v);
+    return 0;
+}
+
+static void put_int8(QEMUFile *f, void *pv, size_t size)
+{
+    int8_t *v = pv;
+    qemu_put_s8s(f, v);
+}
+
+const VMStateInfo vmstate_info_int8 = {
+    .name = "int8",
+    .get  = get_int8,
+    .put  = put_int8,
+};
+
+/* 16 bit int */
+
+static int get_int16(QEMUFile *f, void *pv, size_t size)
+{
+    int16_t *v = pv;
+    qemu_get_sbe16s(f, v);
+    return 0;
+}
+
+static void put_int16(QEMUFile *f, void *pv, size_t size)
+{
+    int16_t *v = pv;
+    qemu_put_sbe16s(f, v);
+}
+
+const VMStateInfo vmstate_info_int16 = {
+    .name = "int16",
+    .get  = get_int16,
+    .put  = put_int16,
+};
+
+/* 32 bit int */
+
+static int get_int32(QEMUFile *f, void *pv, size_t size)
+{
+    int32_t *v = pv;
+    qemu_get_sbe32s(f, v);
+    return 0;
+}
+
+static void put_int32(QEMUFile *f, void *pv, size_t size)
+{
+    int32_t *v = pv;
+    qemu_put_sbe32s(f, v);
+}
+
+const VMStateInfo vmstate_info_int32 = {
+    .name = "int32",
+    .get  = get_int32,
+    .put  = put_int32,
+};
+
+/* 32 bit int. See that the received value is the same than the one
+   in the field */
+
+static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
+{
+    int32_t *v = pv;
+    int32_t v2;
+    qemu_get_sbe32s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_int32_equal = {
+    .name = "int32 equal",
+    .get  = get_int32_equal,
+    .put  = put_int32,
+};
+
+/* 32 bit int. See that the received value is the less or the same
+   than the one in the field */
+
+static int get_int32_le(QEMUFile *f, void *pv, size_t size)
+{
+    int32_t *old = pv;
+    int32_t new;
+    qemu_get_sbe32s(f, &new);
+
+    if (*old <= new) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_int32_le = {
+    .name = "int32 equal",
+    .get  = get_int32_le,
+    .put  = put_int32,
+};
+
+/* 64 bit int */
+
+static int get_int64(QEMUFile *f, void *pv, size_t size)
+{
+    int64_t *v = pv;
+    qemu_get_sbe64s(f, v);
+    return 0;
+}
+
+static void put_int64(QEMUFile *f, void *pv, size_t size)
+{
+    int64_t *v = pv;
+    qemu_put_sbe64s(f, v);
+}
+
+const VMStateInfo vmstate_info_int64 = {
+    .name = "int64",
+    .get  = get_int64,
+    .put  = put_int64,
+};
+
+/* 8 bit unsigned int */
+
+static int get_uint8(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    qemu_get_8s(f, v);
+    return 0;
+}
+
+static void put_uint8(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    qemu_put_8s(f, v);
+}
+
+const VMStateInfo vmstate_info_uint8 = {
+    .name = "uint8",
+    .get  = get_uint8,
+    .put  = put_uint8,
+};
+
+/* 16 bit unsigned int */
+
+static int get_uint16(QEMUFile *f, void *pv, size_t size)
+{
+    uint16_t *v = pv;
+    qemu_get_be16s(f, v);
+    return 0;
+}
+
+static void put_uint16(QEMUFile *f, void *pv, size_t size)
+{
+    uint16_t *v = pv;
+    qemu_put_be16s(f, v);
+}
+
+const VMStateInfo vmstate_info_uint16 = {
+    .name = "uint16",
+    .get  = get_uint16,
+    .put  = put_uint16,
+};
+
+/* 32 bit unsigned int */
+
+static int get_uint32(QEMUFile *f, void *pv, size_t size)
+{
+    uint32_t *v = pv;
+    qemu_get_be32s(f, v);
+    return 0;
+}
+
+static void put_uint32(QEMUFile *f, void *pv, size_t size)
+{
+    uint32_t *v = pv;
+    qemu_put_be32s(f, v);
+}
+
+const VMStateInfo vmstate_info_uint32 = {
+    .name = "uint32",
+    .get  = get_uint32,
+    .put  = put_uint32,
+};
+
+/* 32 bit uint. See that the received value is the same than the one
+   in the field */
+
+static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint32_t *v = pv;
+    uint32_t v2;
+    qemu_get_be32s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint32_equal = {
+    .name = "uint32 equal",
+    .get  = get_uint32_equal,
+    .put  = put_uint32,
+};
+
+/* 64 bit unsigned int */
+
+static int get_uint64(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+    qemu_get_be64s(f, v);
+    return 0;
+}
+
+static void put_uint64(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+    qemu_put_be64s(f, v);
+}
+
+const VMStateInfo vmstate_info_uint64 = {
+    .name = "uint64",
+    .get  = get_uint64,
+    .put  = put_uint64,
+};
+
+/* 64 bit unsigned int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+    uint64_t v2;
+    qemu_get_be64s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint64_equal = {
+    .name = "int64 equal",
+    .get  = get_uint64_equal,
+    .put  = put_uint64,
+};
+
+/* 8 bit int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    uint8_t v2;
+    qemu_get_8s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint8_equal = {
+    .name = "uint8 equal",
+    .get  = get_uint8_equal,
+    .put  = put_uint8,
+};
+
+/* 16 bit unsigned int int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint16_t *v = pv;
+    uint16_t v2;
+    qemu_get_be16s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint16_equal = {
+    .name = "uint16 equal",
+    .get  = get_uint16_equal,
+    .put  = put_uint16,
+};
+
+/* floating point */
+
+static int get_float64(QEMUFile *f, void *pv, size_t size)
+{
+    float64 *v = pv;
+
+    *v = make_float64(qemu_get_be64(f));
+    return 0;
+}
+
+static void put_float64(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+
+    qemu_put_be64(f, float64_val(*v));
+}
+
+const VMStateInfo vmstate_info_float64 = {
+    .name = "float64",
+    .get  = get_float64,
+    .put  = put_float64,
+};
+
+/* uint8_t buffers */
+
+static int get_buffer(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    qemu_get_buffer(f, v, size);
+    return 0;
+}
+
+static void put_buffer(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    qemu_put_buffer(f, v, size);
+}
+
+const VMStateInfo vmstate_info_buffer = {
+    .name = "buffer",
+    .get  = get_buffer,
+    .put  = put_buffer,
+};
+
+/* unused buffers: space that was used for some fields that are
+   not useful anymore */
+
+static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t buf[1024];
+    int block_len;
+
+    while (size > 0) {
+        block_len = MIN(sizeof(buf), size);
+        size -= block_len;
+        qemu_get_buffer(f, buf, block_len);
+    }
+   return 0;
+}
+
+static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
+{
+    static const uint8_t buf[1024];
+    int block_len;
+
+    while (size > 0) {
+        block_len = MIN(sizeof(buf), size);
+        size -= block_len;
+        qemu_put_buffer(f, buf, block_len);
+    }
+}
+
+const VMStateInfo vmstate_info_unused_buffer = {
+    .name = "unused_buffer",
+    .get  = get_unused_buffer,
+    .put  = put_unused_buffer,
+};
+
+/* bitmaps (as defined by bitmap.h). Note that size here is the size
+ * of the bitmap in bits. The on-the-wire format of a bitmap is 64
+ * bit words with the bits in big endian order. The in-memory format
+ * is an array of 'unsigned long', which may be either 32 or 64 bits.
+ */
+/* This is the number of 64 bit words sent over the wire */
+#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
+static int get_bitmap(QEMUFile *f, void *pv, size_t size)
+{
+    unsigned long *bmp = pv;
+    int i, idx = 0;
+    for (i = 0; i < BITS_TO_U64S(size); i++) {
+        uint64_t w = qemu_get_be64(f);
+        bmp[idx++] = w;
+        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
+            bmp[idx++] = w >> 32;
+        }
+    }
+    return 0;
+}
+
+static void put_bitmap(QEMUFile *f, void *pv, size_t size)
+{
+    unsigned long *bmp = pv;
+    int i, idx = 0;
+    for (i = 0; i < BITS_TO_U64S(size); i++) {
+        uint64_t w = bmp[idx++];
+        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
+            w |= ((uint64_t)bmp[idx++]) << 32;
+        }
+        qemu_put_be64(f, w);
+    }
+}
+
+const VMStateInfo vmstate_info_bitmap = {
+    .name = "bitmap",
+    .get = get_bitmap,
+    .put = put_bitmap,
+};
commit 51b7fa5b3cf7678263382039a884aa2e74742bb6
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:14 2013 -0200

    savevm.c: Coding style fix
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 66b8b5e..bdb90ef 100644
--- a/savevm.c
+++ b/savevm.c
@@ -2114,7 +2114,8 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
     return NULL;
 }
 
-static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
+static const VMStateDescription *
+    vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
 {
     while (sub && sub->needed) {
         if (strcmp(idstr, sub->vmsd->name) == 0) {
commit 38ff78d363da0d2e0ad27853036b08eaa52ef18d
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:13 2013 -0200

    savevm.c: Coding style fixes
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 3cdd5f2..66b8b5e 100644
--- a/savevm.c
+++ b/savevm.c
@@ -137,14 +137,12 @@ struct QEMUFile {
     int last_error;
 };
 
-typedef struct QEMUFileStdio
-{
+typedef struct QEMUFileStdio {
     FILE *stdio_file;
     QEMUFile *file;
 } QEMUFileStdio;
 
-typedef struct QEMUFileSocket
-{
+typedef struct QEMUFileSocket {
     int fd;
     QEMUFile *file;
 } QEMUFileSocket;
@@ -208,7 +206,8 @@ static int stdio_get_fd(void *opaque)
     return fileno(s->stdio_file);
 }
 
-static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos,
+                            int size)
 {
     QEMUFileStdio *s = opaque;
     return fwrite(buf, 1, size, s->stdio_file);
@@ -310,7 +309,7 @@ QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
 
     s->stdio_file = stdio_file;
 
-    if(mode[0] == 'r') {
+    if (mode[0] == 'r') {
         s->file = qemu_fopen_ops(s, &stdio_pipe_read_ops);
     } else {
         s->file = qemu_fopen_ops(s, &stdio_pipe_write_ops);
@@ -429,7 +428,7 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
     s = g_malloc0(sizeof(QEMUFileSocket));
     s->fd = fd;
 
-    if(mode[0] == 'r') {
+    if (mode[0] == 'r') {
         s->file = qemu_fopen_ops(s, &unix_read_ops);
     } else {
         s->file = qemu_fopen_ops(s, &unix_write_ops);
@@ -491,10 +490,11 @@ QEMUFile *qemu_fopen(const char *filename, const char *mode)
     s = g_malloc0(sizeof(QEMUFileStdio));
 
     s->stdio_file = fopen(filename, mode);
-    if (!s->stdio_file)
+    if (!s->stdio_file) {
         goto fail;
-    
-    if(mode[0] == 'w') {
+    }
+
+    if (mode[0] == 'w') {
         s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
     } else {
         s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
@@ -550,8 +550,9 @@ static const QEMUFileOps bdrv_write_ops = {
 
 static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
 {
-    if (is_writable)
+    if (is_writable) {
         return qemu_fopen_ops(bs, &bdrv_write_ops);
+    }
     return qemu_fopen_ops(bs, &bdrv_read_ops);
 }
 
@@ -703,8 +704,9 @@ static void qemu_fill_buffer(QEMUFile *f)
         f->pos += len;
     } else if (len == 0) {
         qemu_file_set_error(f, -EIO);
-    } else if (len != -EAGAIN)
+    } else if (len != -EAGAIN) {
         qemu_file_set_error(f, len);
+    }
 }
 
 int qemu_get_fd(QEMUFile *f)
@@ -791,8 +793,9 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 
     while (size > 0) {
         l = IO_BUF_SIZE - f->buf_index;
-        if (l > size)
+        if (l > size) {
             l = size;
+        }
         memcpy(f->buf + f->buf_index, buf, l);
         f->bytes_xfer += l;
         if (f->ops->writev_buffer) {
@@ -1100,8 +1103,9 @@ static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
     int32_t v2;
     qemu_get_sbe32s(f, &v2);
 
-    if (*v == v2)
+    if (*v == v2) {
         return 0;
+    }
     return -EINVAL;
 }
 
@@ -1120,8 +1124,9 @@ static int get_int32_le(QEMUFile *f, void *pv, size_t size)
     int32_t new;
     qemu_get_sbe32s(f, &new);
 
-    if (*old <= new)
+    if (*old <= new) {
         return 0;
+    }
     return -EINVAL;
 }
 
@@ -1287,8 +1292,9 @@ static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
     uint8_t v2;
     qemu_get_8s(f, &v2);
 
-    if (*v == v2)
+    if (*v == v2) {
         return 0;
+    }
     return -EINVAL;
 }
 
@@ -1307,8 +1313,9 @@ static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
     uint16_t v2;
     qemu_get_be16s(f, &v2);
 
-    if (*v == v2)
+    if (*v == v2) {
         return 0;
+    }
     return -EINVAL;
 }
 
@@ -1502,8 +1509,9 @@ static int calculate_compat_instance_id(const char *idstr)
     int instance_id = 0;
 
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
-        if (!se->compat)
+        if (!se->compat) {
             continue;
+        }
 
         if (strcmp(idstr, se->compat->idstr) == 0
             && instance_id <= se->compat->instance_id) {
@@ -1690,10 +1698,11 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
     }
     if (vmsd->pre_load) {
         int ret = vmsd->pre_load(opaque);
-        if (ret)
+        if (ret) {
             return ret;
+        }
     }
-    while(field->name) {
+    while (field->name) {
         if ((field->field_exists &&
              field->field_exists(opaque, version_id)) ||
             (!field->field_exists &&
@@ -1729,7 +1738,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                     addr = *(void **)addr;
                 }
                 if (field->flags & VMS_STRUCT) {
-                    ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id);
+                    ret = vmstate_load_state(f, field->vmsd, addr,
+                                             field->vmsd->version_id);
                 } else {
                     ret = field->info->get(f, addr, size);
 
@@ -1759,7 +1769,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
     if (vmsd->pre_save) {
         vmsd->pre_save(opaque);
     }
-    while(field->name) {
+    while (field->name) {
         if (!field->field_exists ||
             field->field_exists(opaque, vmsd->version_id)) {
             void *base_addr = opaque + field->offset;
@@ -1818,7 +1828,7 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
         se->ops->save_state(f, se->opaque);
         return;
     }
-    vmstate_save_state(f,se->vmsd, se->opaque);
+    vmstate_save_state(f, se->vmsd, se->opaque);
 }
 
 bool qemu_savevm_state_blocked(Error **errp)
@@ -1846,7 +1856,7 @@ void qemu_savevm_state_begin(QEMUFile *f,
         }
         se->ops->set_params(params, se->opaque);
     }
-    
+
     qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
     qemu_put_be32(f, QEMU_VM_FILE_VERSION);
 
@@ -2106,7 +2116,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
 
 static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
 {
-    while(sub && sub->needed) {
+    while (sub && sub->needed) {
         if (strcmp(idstr, sub->vmsd->name) == 0) {
             return sub->vmsd;
         }
@@ -2198,16 +2208,18 @@ int qemu_loadvm_state(QEMUFile *f)
     }
 
     v = qemu_get_be32(f);
-    if (v != QEMU_VM_FILE_MAGIC)
+    if (v != QEMU_VM_FILE_MAGIC) {
         return -EINVAL;
+    }
 
     v = qemu_get_be32(f);
     if (v == QEMU_VM_FILE_VERSION_COMPAT) {
         fprintf(stderr, "SaveVM v2 format is obsolete and don't work anymore\n");
         return -ENOTSUP;
     }
-    if (v != QEMU_VM_FILE_VERSION)
+    if (v != QEMU_VM_FILE_VERSION) {
         return -ENOTSUP;
+    }
 
     while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
         uint32_t instance_id, version_id, section_id;
@@ -2326,8 +2338,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name)
     bs = NULL;
     while ((bs = bdrv_next(bs))) {
         if (bdrv_can_snapshot(bs) &&
-            bdrv_snapshot_find(bs, snapshot, name) >= 0)
-        {
+            bdrv_snapshot_find(bs, snapshot, name) >= 0) {
             bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
             if (error_is_set(&err)) {
                 monitor_printf(mon,
@@ -2437,8 +2448,9 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     }
 
  the_end:
-    if (saved_vm_running)
+    if (saved_vm_running) {
         vm_start();
+    }
 }
 
 void qmp_xen_save_devices_state(const char *filename, Error **errp)
@@ -2462,8 +2474,9 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp)
     }
 
  the_end:
-    if (saved_vm_running)
+    if (saved_vm_running) {
         vm_start();
+    }
 }
 
 int load_vmstate(const char *name)
commit 5cecf414945e5ba40da893cbdaed554371d4eca9
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:12 2013 -0200

    savevm: Convert all tabs to spaces
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 46643f1..3cdd5f2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -53,7 +53,7 @@
 #define ARP_OP_REQUEST_REV 0x3
 
 static int announce_self_create(uint8_t *buf,
-				uint8_t *mac_addr)
+                                uint8_t *mac_addr)
 {
     /* Ethernet header. */
     memset(buf, 0xff, 6);         /* destination MAC addr */
@@ -100,16 +100,16 @@ static void qemu_announce_self_once(void *opaque)
         timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
                        50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
     } else {
-	    timer_del(timer);
-	    timer_free(timer);
+            timer_del(timer);
+            timer_free(timer);
     }
 }
 
 void qemu_announce_self(void)
 {
-	static QEMUTimer *timer;
-	timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
-	qemu_announce_self_once(&timer);
+    static QEMUTimer *timer;
+    timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
+    qemu_announce_self_once(&timer);
 }
 
 /***********************************************************/
@@ -420,8 +420,8 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
     QEMUFileSocket *s;
 
     if (mode == NULL ||
-	(mode[0] != 'r' && mode[0] != 'w') ||
-	mode[1] != 'b' || mode[2] != 0) {
+        (mode[0] != 'r' && mode[0] != 'w') ||
+        mode[1] != 'b' || mode[2] != 0) {
         fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
         return NULL;
     }
@@ -1959,7 +1959,7 @@ void qemu_savevm_state_complete(QEMUFile *f)
         int len;
 
         if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
-	    continue;
+            continue;
         }
         trace_savevm_section_start();
         /* Section type */
commit b5503338ed1c66310f090cd9164abd244fc82631
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:11 2013 -0200

    migration: Move QEMU_VM_* defines to migration/migration.h
    
    The VMState code will be moved to vmstate.c and it uses some of the
    QEMU_VM_* constants, so move it to a header.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 140e6b4..bfa3951 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -23,6 +23,17 @@
 #include "qapi-types.h"
 #include "exec/cpu-common.h"
 
+#define QEMU_VM_FILE_MAGIC           0x5145564d
+#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
+#define QEMU_VM_FILE_VERSION         0x00000003
+
+#define QEMU_VM_EOF                  0x00
+#define QEMU_VM_SECTION_START        0x01
+#define QEMU_VM_SECTION_PART         0x02
+#define QEMU_VM_SECTION_END          0x03
+#define QEMU_VM_SECTION_FULL         0x04
+#define QEMU_VM_SUBSECTION           0x05
+
 struct MigrationParams {
     bool blk;
     bool shared;
diff --git a/savevm.c b/savevm.c
index 8da1d29..46643f1 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1821,17 +1821,6 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
     vmstate_save_state(f,se->vmsd, se->opaque);
 }
 
-#define QEMU_VM_FILE_MAGIC           0x5145564d
-#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
-#define QEMU_VM_FILE_VERSION         0x00000003
-
-#define QEMU_VM_EOF                  0x00
-#define QEMU_VM_SECTION_START        0x01
-#define QEMU_VM_SECTION_PART         0x02
-#define QEMU_VM_SECTION_END          0x03
-#define QEMU_VM_SECTION_FULL         0x04
-#define QEMU_VM_SUBSECTION           0x05
-
 bool qemu_savevm_state_blocked(Error **errp)
 {
     SaveStateEntry *se;
commit c961514fd9e707b6a39c60f687a711ffe0a33539
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Thu Nov 28 12:01:10 2013 -0200

    qemu-file: Make a few functions non-static
    
    The QEMUFile code will be moved to qemu-file.c. This will require making
    the following functions non-static because they are used by the savevm.c
    code:
    
     * qemu_peek_byte()
     * qemu_peek_buffer()
     * qemu_file_skip()
     * qemu_file_set_error()
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 0f757fb..a191fb6 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -121,8 +121,11 @@ static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
 void qemu_put_be16(QEMUFile *f, unsigned int v);
 void qemu_put_be32(QEMUFile *f, unsigned int v);
 void qemu_put_be64(QEMUFile *f, uint64_t v);
+int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset);
 int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
+int qemu_peek_byte(QEMUFile *f, int offset);
 int qemu_get_byte(QEMUFile *f);
+void qemu_file_skip(QEMUFile *f, int size);
 void qemu_update_position(QEMUFile *f, size_t size);
 
 static inline unsigned int qemu_get_ubyte(QEMUFile *f)
@@ -141,6 +144,7 @@ void qemu_file_reset_rate_limit(QEMUFile *f);
 void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate);
 int64_t qemu_file_get_rate_limit(QEMUFile *f);
 int qemu_file_get_error(QEMUFile *f);
+void qemu_file_set_error(QEMUFile *f, int ret);
 void qemu_fflush(QEMUFile *f);
 
 static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
diff --git a/savevm.c b/savevm.c
index 3f912dd..8da1d29 100644
--- a/savevm.c
+++ b/savevm.c
@@ -578,7 +578,7 @@ int qemu_file_get_error(QEMUFile *f)
     return f->last_error;
 }
 
-static void qemu_file_set_error(QEMUFile *f, int ret)
+void qemu_file_set_error(QEMUFile *f, int ret)
 {
     if (f->last_error == 0) {
         f->last_error = ret;
@@ -827,14 +827,14 @@ void qemu_put_byte(QEMUFile *f, int v)
     }
 }
 
-static void qemu_file_skip(QEMUFile *f, int size)
+void qemu_file_skip(QEMUFile *f, int size)
 {
     if (f->buf_index + size <= f->buf_size) {
         f->buf_index += size;
     }
 }
 
-static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
+int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
 {
     int pending;
     int index;
@@ -880,7 +880,7 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
     return done;
 }
 
-static int qemu_peek_byte(QEMUFile *f, int offset)
+int qemu_peek_byte(QEMUFile *f, int offset)
 {
     int index = f->buf_index + offset;
 
commit 40596834c0d57a223124a956ccbe39dfeadc9f0e
Author: Matthew Garrett <matthew.garrett at nebula.com>
Date:   Mon Nov 25 14:42:43 2013 -0500

    migration: Fix rate limit
    
    The migration thread appears to want to allow writeout to occur at full
    speed rather than being rate limited during completion of state saving,
    but sets the limit to INT_MAX when xfer_limit is INT64_MAX. This causes
    problems if there's more than 2GB of state left to save at this point. It
    probably ought to just be INT64_MAX instead.
    
    Signed-off-by: Matthew Garrett <matthew.garrett at nebula.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 4ee341b..e5f6b98 100644
--- a/migration.c
+++ b/migration.c
@@ -596,7 +596,7 @@ static void *migration_thread(void *opaque)
 
                 ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
                 if (ret >= 0) {
-                    qemu_file_set_rate_limit(s->file, INT_MAX);
+                    qemu_file_set_rate_limit(s->file, INT64_MAX);
                     qemu_savevm_state_complete(s->file);
                 }
                 qemu_mutex_unlock_iothread();
commit 51cf4c1a99a172679c2949a2d58a2a4ee307b557
Author: Zhanghaoyu (A) <haoyu.zhang at huawei.com>
Date:   Thu Nov 7 11:01:15 2013 +0000

    introduce MIG_STATE_CANCELLING state
    
    Introduce MIG_STATE_CANCELLING state to avoid starting a new migration task while the previous one still exist.
    
    Signed-off-by: Zeng Junliang <zengjunliang at huawei.com>
    Signed-off-by: Zhang Haoyu <haoyu.zhang at huawei.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index fd73b97..4ee341b 100644
--- a/migration.c
+++ b/migration.c
@@ -40,6 +40,7 @@ enum {
     MIG_STATE_ERROR = -1,
     MIG_STATE_NONE,
     MIG_STATE_SETUP,
+    MIG_STATE_CANCELLING,
     MIG_STATE_CANCELLED,
     MIG_STATE_ACTIVE,
     MIG_STATE_COMPLETED,
@@ -196,6 +197,7 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->has_total_time = false;
         break;
     case MIG_STATE_ACTIVE:
+    case MIG_STATE_CANCELLING:
         info->has_status = true;
         info->status = g_strdup("active");
         info->has_total_time = true;
@@ -282,6 +284,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
 
 /* shared migration helpers */
 
+static void migrate_set_state(MigrationState *s, int old_state, int new_state)
+{
+    if (atomic_cmpxchg(&s->state, old_state, new_state) == new_state) {
+        trace_migrate_set_state(new_state);
+    }
+}
+
 static void migrate_fd_cleanup(void *opaque)
 {
     MigrationState *s = opaque;
@@ -303,18 +312,14 @@ static void migrate_fd_cleanup(void *opaque)
 
     if (s->state != MIG_STATE_COMPLETED) {
         qemu_savevm_state_cancel();
+        if (s->state == MIG_STATE_CANCELLING) {
+            migrate_set_state(s, MIG_STATE_CANCELLING, MIG_STATE_CANCELLED);
+        }
     }
 
     notifier_list_notify(&migration_state_notifiers, s);
 }
 
-static void migrate_set_state(MigrationState *s, int old_state, int new_state)
-{
-    if (atomic_cmpxchg(&s->state, old_state, new_state) == new_state) {
-        trace_migrate_set_state(new_state);
-    }
-}
-
 void migrate_fd_error(MigrationState *s)
 {
     DPRINTF("setting error state\n");
@@ -334,8 +339,8 @@ static void migrate_fd_cancel(MigrationState *s)
         if (old_state != MIG_STATE_SETUP && old_state != MIG_STATE_ACTIVE) {
             break;
         }
-        migrate_set_state(s, old_state, MIG_STATE_CANCELLED);
-    } while (s->state != MIG_STATE_CANCELLED);
+        migrate_set_state(s, old_state, MIG_STATE_CANCELLING);
+    } while (s->state != MIG_STATE_CANCELLING);
 }
 
 void add_migration_state_change_notifier(Notifier *notify)
@@ -412,7 +417,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
     params.blk = has_blk && blk;
     params.shared = has_inc && inc;
 
-    if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) {
+    if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP ||
+        s->state == MIG_STATE_CANCELLING) {
         error_set(errp, QERR_MIGRATION_ACTIVE);
         return;
     }
commit 6f2b811a61810a7fd9f9a5085de223f66b823342
Author: Zhanghaoyu (A) <haoyu.zhang at huawei.com>
Date:   Thu Nov 7 08:21:23 2013 +0000

    avoid a bogus COMPLETED->CANCELLED transition
    
    Avoid a bogus COMPLETED->CANCELLED transition.
    There is a period of time from the timing of setting COMPLETED state to that of migration thread exits, so during which it's problematic in COMPLETED->CANCELLED transition.
    
    Signed-off-by: Zeng Junliang <zengjunliang at huawei.com>
    Signed-off-by: Zhang Haoyu <haoyu.zhang at huawei.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/migration.c b/migration.c
index 2b1ab20..fd73b97 100644
--- a/migration.c
+++ b/migration.c
@@ -326,9 +326,16 @@ void migrate_fd_error(MigrationState *s)
 
 static void migrate_fd_cancel(MigrationState *s)
 {
+    int old_state ;
     DPRINTF("cancelling migration\n");
 
-    migrate_set_state(s, s->state, MIG_STATE_CANCELLED);
+    do {
+        old_state = s->state;
+        if (old_state != MIG_STATE_SETUP && old_state != MIG_STATE_ACTIVE) {
+            break;
+        }
+        migrate_set_state(s, old_state, MIG_STATE_CANCELLED);
+    } while (s->state != MIG_STATE_CANCELLED);
 }
 
 void add_migration_state_change_notifier(Notifier *notify)
commit dd089c0a1e928fb80ba8a37983c1b0e9232d1c8b
Merge: 42bf25a 30ef3c7
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Sun Jan 12 17:50:52 2014 -0800

    Merge remote-tracking branch 'pmaydell/tags/pull-cocoa-20140112' into staging
    
    cocoa queue:
     * pass command key to guest when VM has mousegrab
     * add .qcow2 to extension list for image load dialog
     * fix bugs in code for starting QEMU via image load dialog
     * fix resize/redraw interaction
     * draw window black if guest hasn't sent anything to screen
     * minor style/typo fixes
     * add myself as cocoa co-maintainer
    
    # gpg: Signature made Sun 12 Jan 2014 02:45:52 PM PST using RSA key ID 14360CDE
    # gpg: Can't check signature: public key not found
    
    * pmaydell/tags/pull-cocoa-20140112:
      MAINTAINERS: add myself as cocoa UI co-maintainer
      ui/cocoa: Remove stray tabs
      ui/cocoa: Draw black rectangle if we have no data yet
      ui/cocoa: Redraw at correct size when switching surface
      ui/cocoa: Fix code for starting QEMU via image file load dialog
      ui/cocoa: Add ".qcow2" to extension list for image load dialog
      ui/cocoa: Send warning message to stderr, not stdout
      ui/cocoa: Correct typos in comments and variable names
      ui/cocoa: Pass command key through to guest when VM has mousegrab
    
    Message-id: 1389567158-31066-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 42bf25a9bf99559dd68d2b20824cd4879d5785ba
Merge: eedc1a5 5cd8a11
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Sun Jan 12 17:50:43 2014 -0800

    Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20140112' into staging
    
    target-arm queue:
     * build fix for bigendian hosts
    
    # gpg: Signature made Sun 12 Jan 2014 01:38:22 PM PST using RSA key ID 14360CDE
    # gpg: Can't check signature: public key not found
    
    * pmaydell/tags/pull-target-arm-20140112:
      arm: fix compile on bigendian host
    
    Message-id: 1389562970-30944-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 30ef3c742526baa7910ab5023f0b85062bd85579
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Dec 16 15:17:55 2013 +0000

    MAINTAINERS: add myself as cocoa UI co-maintainer
    
    Add myself to the maintainers list for the cocoa UI; status
    remains "Odd Fixes".
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Andreas Färber <andreas.faerber at web.de>
    Message-id: 1387207075-10280-1-git-send-email-peter.maydell at linaro.org

diff --git a/MAINTAINERS b/MAINTAINERS
index a5ab8f8..fb53242 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -714,6 +714,7 @@ F: ui/
 
 Cocoa graphics
 M: Andreas Färber <andreas.faerber at web.de>
+M: Peter Maydell <peter.maydell at linaro.org>
 S: Odd Fixes
 F: ui/cocoa.m
 
commit 49060c29c3751773265a405e6ceaed9d06fb4823
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 24 11:54:12 2013 +0000

    ui/cocoa: Remove stray tabs
    
    The ui/cocoa.m file has just three lines with hardcoded tabs; fix them.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1387886052-27067-1-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 22ec29b..8661777 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -427,8 +427,8 @@ QemuCocoaView *cocoaView;
         CGDataProviderRelease(dataProviderRef);
 
     //sync host window color space with guests
-	screen.bitsPerPixel = surface_bits_per_pixel(surface);
-	screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
+    screen.bitsPerPixel = surface_bits_per_pixel(surface);
+    screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
 
     dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL);
 
@@ -774,7 +774,7 @@ QemuCocoaView *cocoaView;
         [normalWindow setContentView:cocoaView];
         [normalWindow useOptimizedDrawing:YES];
         [normalWindow makeKeyAndOrderFront:self];
-		[normalWindow center];
+        [normalWindow center];
 
     }
     return self;
commit 7d270b1c21c692478245b90bfac0aa54c6a8d98a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 24 02:51:47 2013 +0000

    ui/cocoa: Draw black rectangle if we have no data yet
    
    If our redraw method is called before we have any data from the guest,
    then draw a black rectangle rather than leaving the window empty.
    This mostly only matters when the guest machine has no framebuffer
    device, but it is more in line with the behaviour of other QEMU UIs.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1387853507-26298-3-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 6a1f6b6..22ec29b 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -321,7 +321,12 @@ QemuCocoaView *cocoaView;
     CGContextSetShouldAntialias (viewContextRef, NO);
 
     // draw screen bitmap directly to Core Graphics context
-    if (dataProviderRef) {
+    if (!dataProviderRef) {
+        // Draw request before any guest device has set up a framebuffer:
+        // just draw an opaque black rectangle
+        CGContextSetRGBFillColor(viewContextRef, 0, 0, 0, 1.0);
+        CGContextFillRect(viewContextRef, NSRectToCGRect(rect));
+    } else {
         CGImageRef imageRef = CGImageCreate(
             screen.width, //width
             screen.height, //height
commit d3345a04849374af2b21d6624dd206c4444a6ffe
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Dec 24 02:51:46 2013 +0000

    ui/cocoa: Redraw at correct size when switching surface
    
    If the surface switch involved a resize, we were doing the redraw
    at the old size rather than the new, because the update of
    screen.width and screen.height was being done after the setFrame
    method calls which triggered a redraw. Normally this isn't very
    noticeable because typically after the guest triggers the window
    resize it also draws something to it, which will in turn cause
    us to redraw. However, the combination of a guest which never
    draws to the display and a command line setting of a screen size
    larger than the default can reveal odd effects.
    
    Move most of the handling of resizes to the top of the method,
    and guard it with a check that the surface size actually changed,
    to avoid unnecessary operations (including some user visible ones
    like "recenter the window on the screen") if the surface is the
    same size as the old one.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1387853507-26298-2-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index b90b782..6a1f6b6 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -405,6 +405,17 @@ QemuCocoaView *cocoaView;
 
     int w = surface_width(surface);
     int h = surface_height(surface);
+    bool isResize = (w != screen.width || h != screen.height);
+
+    int oldh = screen.height;
+    if (isResize) {
+        // Resize before we trigger the redraw, or we'll redraw at the wrong size
+        COCOA_DEBUG("switchSurface: new size %d x %d\n", w, h);
+        screen.width = w;
+        screen.height = h;
+        [self setContentDimensions];
+        [self setFrame:NSMakeRect(cx, cy, cw, ch)];
+    }
 
     // update screenBuffer
     if (dataProviderRef)
@@ -419,17 +430,16 @@ QemuCocoaView *cocoaView;
     // update windows
     if (isFullscreen) {
         [[fullScreenWindow contentView] setFrame:[[NSScreen mainScreen] frame]];
-        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:NO animate:NO];
+        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:NO animate:NO];
     } else {
         if (qemu_name)
             [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
-        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:YES animate:NO];
+        [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:YES animate:NO];
+    }
+
+    if (isResize) {
+        [normalWindow center];
     }
-    screen.width = w;
-    screen.height = h;
-	[normalWindow center];
-    [self setContentDimensions];
-    [self setFrame:NSMakeRect(cx, cy, cw, ch)];
 }
 
 - (void) toggleFullScreen:(id)sender
commit 98db429d2c6d157b7e00e3f24b6b1d9036f5e358
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 8 22:59:06 2013 +0000

    ui/cocoa: Fix code for starting QEMU via image file load dialog
    
    Fix a number of bugs in the code for starting QEMU via the image
    file load dialog:
     * use the actual argv[0] rather than "qemu": this avoids failures to
       find BIOS image files caused by not looking in the correct directory
       relative to the executable path
     * allocate a large enough argv array to NULL terminate it
     * use g_strdup(X) rather than g_strdup_printf("%s", X) or
       g_strdup_printf(X)
     * disable the printing of the simulated command line argument
       (which is presumably intended for debug only)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1386543546-31919-6-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index fd55044..b90b782 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -833,18 +833,18 @@ QemuCocoaView *cocoaView;
     if(returnCode == NSCancelButton) {
         exit(0);
     } else if(returnCode == NSOKButton) {
-        const char *bin = "qemu";
         char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding];
 
-        char **argv = (char**)malloc( sizeof(char*)*3 );
+        char **argv = g_new(char *, 4);
 
         [sheet close];
 
-        argv[0] = g_strdup_printf("%s", bin);
-        argv[1] = g_strdup_printf("-hda");
-        argv[2] = g_strdup_printf("%s", img);
+        argv[0] = g_strdup(gArgv[0]);
+        argv[1] = g_strdup("-hda");
+        argv[2] = g_strdup(img);
+        argv[3] = NULL;
 
-        printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
+        // printf("Using argc %d argv %s -hda %s\n", 3, gArgv[0], img);
 
         [self startEmulationWithArgc:3 argv:(char**)argv];
     }
commit 5342f990f46512487e3e5be1047a5b424f00d255
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 8 22:59:05 2013 +0000

    ui/cocoa: Add ".qcow2" to extension list for image load dialog
    
    Add ".qcow2" to the list of file extensions which are accepted
    by the initial disk image load dialog which is displayed if the
    user runs QEMU without any command line arguments.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1386543546-31919-5-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 5249891..fd55044 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -785,7 +785,7 @@ QemuCocoaView *cocoaView;
         [op setPrompt:@"Boot image"];
         [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
         NSArray *filetypes = [NSArray arrayWithObjects:@"img", @"iso", @"dmg",
-                                 @"qcow", @"cow", @"cloop", @"vmdk", nil];
+                                 @"qcow", @"qcow2", @"cow", @"cloop", @"vmdk", nil];
 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
         [op setAllowedFileTypes:filetypes];
         [op beginSheetModalForWindow:normalWindow
commit 01cc4e6fd7d364c6c401c579d504d82c0523d67e
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 8 22:59:04 2013 +0000

    ui/cocoa: Send warning message to stderr, not stdout
    
    Bring a warning message into line with the others in this file by
    sending it to stderr, not stdout.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1386543546-31919-4-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 1edb944..5249891 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -239,7 +239,7 @@ int keymap[] =
 static int cocoa_keycode_to_qemu(int keycode)
 {
     if (ARRAY_SIZE(keymap) <= keycode) {
-        printf("(cocoa) warning unknown keycode 0x%x\n", keycode);
+        fprintf(stderr, "(cocoa) warning unknown keycode 0x%x\n", keycode);
         return 0;
     }
     return keymap[keycode];
commit 49b9bd4dccac26178a4796367e4358bd67f4f59b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 8 22:59:03 2013 +0000

    ui/cocoa: Correct typos in comments and variable names
    
    Fix various non-user-visible typos in comments and variable names.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1386543546-31919-3-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 34b58d5..1edb944 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -52,7 +52,7 @@
 #define COCOA_MOUSE_EVENT \
         if (isTabletEnabled) { \
             kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, buttons); \
-        } else if (isMouseGrabed) { \
+        } else if (isMouseGrabbed) { \
             kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, buttons); \
         } else { \
             [NSApp sendEvent:event]; \
@@ -204,7 +204,7 @@ int keymap[] =
     200,//  126     0x7E    0xc8    E0,48   U ARROW QZ_UP
 /* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
 
-/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
+/* Additional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
 /*
     221 //          0xdd            e0,5d   APPS
         //              E0,2A,E0,37         PRNT SCRN
@@ -259,7 +259,7 @@ static int cocoa_keycode_to_qemu(int keycode)
     float cx,cy,cw,ch,cdx,cdy;
     CGDataProviderRef dataProviderRef;
     int modifiers_state[256];
-    BOOL isMouseGrabed;
+    BOOL isMouseGrabbed;
     BOOL isFullscreen;
     BOOL isAbsoluteEnabled;
     BOOL isTabletEnabled;
@@ -270,7 +270,7 @@ static int cocoa_keycode_to_qemu(int keycode)
 - (void) toggleFullScreen:(id)sender;
 - (void) handleEvent:(NSEvent *)event;
 - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
-- (BOOL) isMouseGrabed;
+- (BOOL) isMouseGrabbed;
 - (BOOL) isAbsoluteEnabled;
 - (float) cdx;
 - (float) cdy;
@@ -492,7 +492,7 @@ QemuCocoaView *cocoaView;
         case NSFlagsChanged:
             keycode = cocoa_keycode_to_qemu([event keyCode]);
 
-            if ((keycode == 219 || keycode == 220) && !isMouseGrabed) {
+            if ((keycode == 219 || keycode == 220) && !isMouseGrabbed) {
               /* Don't pass command key changes to guest unless mouse is grabbed */
               keycode = 0;
             }
@@ -523,7 +523,7 @@ QemuCocoaView *cocoaView;
             keycode = cocoa_keycode_to_qemu([event keyCode]);
 
             // forward command key combos to the host UI unless the mouse is grabbed
-            if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) {
+            if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) {
                 [NSApp sendEvent:event];
                 return;
             }
@@ -587,7 +587,7 @@ QemuCocoaView *cocoaView;
 
             // don't pass the guest a spurious key-up if we treated this
             // command-key combo as a host UI action
-            if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) {
+            if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) {
                 return;
             }
 
@@ -648,7 +648,7 @@ QemuCocoaView *cocoaView;
         case NSLeftMouseUp:
             if (isTabletEnabled) {
                     COCOA_MOUSE_EVENT
-            } else if (!isMouseGrabed) {
+            } else if (!isMouseGrabbed) {
                 if (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height) {
                     [self grabMouse];
                 } else {
@@ -665,7 +665,7 @@ QemuCocoaView *cocoaView;
             COCOA_MOUSE_EVENT
             break;
         case NSScrollWheel:
-            if (isTabletEnabled || isMouseGrabed) {
+            if (isTabletEnabled || isMouseGrabbed) {
                 kbd_mouse_event(0, 0, -[event deltaY], 0);
             } else {
                 [NSApp sendEvent:event];
@@ -688,7 +688,7 @@ QemuCocoaView *cocoaView;
     }
     [NSCursor hide];
     CGAssociateMouseAndMouseCursorPosition(FALSE);
-    isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
+    isMouseGrabbed = TRUE; // while isMouseGrabbed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
 }
 
 - (void) ungrabMouse
@@ -703,11 +703,11 @@ QemuCocoaView *cocoaView;
     }
     [NSCursor unhide];
     CGAssociateMouseAndMouseCursorPosition(TRUE);
-    isMouseGrabed = FALSE;
+    isMouseGrabbed = FALSE;
 }
 
 - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {isAbsoluteEnabled = tIsAbsoluteEnabled;}
-- (BOOL) isMouseGrabed {return isMouseGrabed;}
+- (BOOL) isMouseGrabbed {return isMouseGrabbed;}
 - (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
 - (float) cdx {return cdx;}
 - (float) cdy {return cdy;}
@@ -778,7 +778,7 @@ QemuCocoaView *cocoaView;
 {
     COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n");
 
-    // Display an open dialog box if no argument were passed or
+    // Display an open dialog box if no arguments were passed or
     // if qemu was launched from the finder ( the Finder passes "-psn" )
     if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) {
         NSOpenPanel *op = [[NSOpenPanel alloc] init];
@@ -1010,7 +1010,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl)
 
     if (kbd_mouse_is_absolute()) {
         if (![cocoaView isAbsoluteEnabled]) {
-            if ([cocoaView isMouseGrabed]) {
+            if ([cocoaView isMouseGrabbed]) {
                 [cocoaView ungrabMouse];
             }
         }
commit 8895919a044e9e8111faebabacaa2245d8ce4e51
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sun Dec 8 22:59:02 2013 +0000

    ui/cocoa: Pass command key through to guest when VM has mousegrab
    
    The guest might want to be able to use the command key for its won
    purposes (as command if it is MacOS X, or for the Windows key if
    it is a PC guest, for instance). In line with other UI frontends,
    pass it through if the guest has mousegrab, and only use it for UI
    menu accelerators if not grabbed.
    
    Thanks to John Arbuckle for reporting this problem, helping
    us work through what the best solution would be and providing
    a patch which was the initial inspiration for this one.
    
    Reported-by: John Arbuckle <programmingkidx at gmail.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1386543546-31919-2-git-send-email-peter.maydell at linaro.org

diff --git a/ui/cocoa.m b/ui/cocoa.m
index 2524f18..34b58d5 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -129,8 +129,8 @@ int keymap[] =
     14, //  51      0x33    0x0e            BKSP    QZ_BACKSPACE
     0,  //  52      0x34    Undefined
     1,  //  53      0x35    0x01            ESC     QZ_ESCAPE
-    0,  //  54      0x36                            QZ_RMETA
-    0,  //  55      0x37                            QZ_LMETA
+    220, // 54      0x36    0xdc    E0,5C   R GUI   QZ_RMETA
+    219, // 55      0x37    0xdb    E0,5B   L GUI   QZ_LMETA
     42, //  56      0x38    0x2a            L SHFT  QZ_LSHIFT
     58, //  57      0x39    0x3a            CAPS    QZ_CAPSLOCK
     56, //  58      0x3A    0x38            L ALT   QZ_LALT
@@ -206,8 +206,6 @@ int keymap[] =
 
 /* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
 /*
-    219 //          0xdb            e0,5b   L GUI
-    220 //          0xdc            e0,5c   R GUI
     221 //          0xdd            e0,5d   APPS
         //              E0,2A,E0,37         PRNT SCRN
         //              E1,1D,45,E1,9D,C5   PAUSE
@@ -493,6 +491,12 @@ QemuCocoaView *cocoaView;
     switch ([event type]) {
         case NSFlagsChanged:
             keycode = cocoa_keycode_to_qemu([event keyCode]);
+
+            if ((keycode == 219 || keycode == 220) && !isMouseGrabed) {
+              /* Don't pass command key changes to guest unless mouse is grabbed */
+              keycode = 0;
+            }
+
             if (keycode) {
                 if (keycode == 58 || keycode == 69) { // emulate caps lock and num lock keydown and keyup
                     kbd_put_keycode(keycode);
@@ -516,15 +520,15 @@ QemuCocoaView *cocoaView;
             }
             break;
         case NSKeyDown:
+            keycode = cocoa_keycode_to_qemu([event keyCode]);
 
-            // forward command Key Combos
-            if ([event modifierFlags] & NSCommandKeyMask) {
+            // forward command key combos to the host UI unless the mouse is grabbed
+            if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) {
                 [NSApp sendEvent:event];
                 return;
             }
 
             // default
-            keycode = cocoa_keycode_to_qemu([event keyCode]);
 
             // handle control + alt Key Combos (ctrl+alt is reserved for QEMU)
             if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
@@ -580,6 +584,13 @@ QemuCocoaView *cocoaView;
             break;
         case NSKeyUp:
             keycode = cocoa_keycode_to_qemu([event keyCode]);
+
+            // don't pass the guest a spurious key-up if we treated this
+            // command-key combo as a host UI action
+            if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) {
+                return;
+            }
+
             if (qemu_console_is_graphic(NULL)) {
                 if (keycode & 0x80)
                     kbd_put_keycode(0xe0);
commit 5cd8a11834d1fbb12439604ff6793b9f0bae4a15
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Sun Jan 12 21:37:37 2014 +0000

    arm: fix compile on bigendian host
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f1307eb..198b6b8 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -73,7 +73,7 @@
  * significant half of a uint64_t struct member.
  */
 #ifdef HOST_WORDS_BIGENDIAN
-#define offsetoflow32(S, M) offsetof(S, M + sizeof(uint32_t))
+#define offsetoflow32(S, M) (offsetof(S, M) + sizeof(uint32_t))
 #else
 #define offsetoflow32(S, M) offsetof(S, M)
 #endif
commit eedc1a5db5e4d941e39e54344322c0b1e89dfdcd
Merge: debe40f 8a1bd29
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 11:05:17 2014 -0800

    Merge remote-tracking branch 'bonzini/scsi-next' into staging
    
    * bonzini/scsi-next:
      scsi-disk: add UNMAP limits to block limits VPD page
      block/iscsi: use a bh to schedule co reentrance
    
    Message-id: 1387720926-11421-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit debe40fbc5f112672d0ab8f7f393e483304059f4
Merge: d181976 18da7f9
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 11:05:05 2014 -0800

    Merge remote-tracking branch 'stefanha/block' into staging
    
    * stefanha/block:
      commit: Remove unused check
      qemu-iotests: Update test cases for commit active
      commit: Support commit active layer
      block: Add commit_active_start()
      mirror: Move base to MirrorBlockJob
      mirror: Don't close target
      qemu-iotests: drop duplicate virtio-blk initialization failure
      vmdk: Allow vmdk_create to work with protocol
      vmdk: Check VMFS extent line field number
      docs: updated qemu-img man page and qemu-doc to reflect VHDX support.
      block: vhdx - improve error message, and .bdrv_check implementation
      block/iscsi: Fix compilation for libiscsi 1.4.0 (API change)
      qapi-schema: fix QEMU 1.8 references
      dataplane: replace hostmem with memory_region_find
      dataplane: change vring API to use VirtQueueElement
      vring: factor common code for error exits
      vring: create a common function to parse descriptors
      sheepdog: fix dynamic grow for running qcow2 format
    
    Message-id: 1387554416-5837-1-git-send-email-stefanha at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit d1819762fcf5d50f30df603eb606eb31bf62e29d
Merge: 4cddc7f 5bf58ab
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 11:04:48 2014 -0800

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    acpi,pci,pc,fedora,virtio fixes and enhancements
    
    This includes some Preparatory patches for cpu hotplug for q25 and memory
    hotplug by Igor, tests and memory mapping change
    by Laszlo and pci reset cleanup by Paolo.
    There are also some fixes for fedora and virtio:
    included here since they are test blockers for me.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Mon 23 Dec 2013 08:07:18 AM PST using RSA key ID D28D5469
    # gpg: Can't check signature: public key not found
    
    * mst/tags/for_anthony:
      target-arm: fix build with gcc 4.8.2
      virtio: add back call to virtio_bus_device_unplugged
      piix: fix 32bit pci hole
      qdev: switch reset to post-order
      qdev: allow both pre- and post-order vists in qdev walking functions
      pci: clean up resetting of IRQs
      pci: do not export pci_bus_reset
      ACPI/DSDT-CPU: cleanup bogus comment
      ACPI: Q35 DSDT: fix CPU hotplug GPE0.2 handler
      acpi: ich9: allow guest to clear SCI rised by GPE
      acpi: factor out common pm_update_sci() into acpi core
      acpi: piix4: remove not needed GPE0 mask
      i440fx-test: verify firmware under 4G and 1M, both -bios and -pflash
      i440fx-test: generate temporary firmware blob
      i440fx-test: give each GTest case its own qtest
      i440fx-test: qtest_start() should be paired with qtest_end()
      hw/i386/pc_sysfw: support two flash drives
      pc_piix: document gigabyte_align
      piix: gigabyte alignment for ram
    
    Message-id: 1387815007-1272-1-git-send-email-mst at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 4cddc7f44ff83ff3545059f1b8648b8bd7fe0e72
Merge: 62a6a1f d024d20
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 11:04:31 2014 -0800

    Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging
    
    QOM CPUState refactorings / X86CPU
    
    * TLB invalidation optimizations
    * X86CPU initialization cleanups
    * Preparations for X86CPU hot-unplug
    
    # gpg: Signature made Tue 24 Dec 2013 04:51:52 AM PST using RSA key ID 3E7E013F
    # gpg: Good signature from "Andreas Färber <afaerber at suse.de>"
    # gpg:                 aka "Andreas Färber <afaerber at suse.com>"
    # gpg: WARNING: This key is not certified with a trusted signature!
    # gpg:          There is no indication that the signature belongs to the owner.
    # Primary key fingerprint: 174F 0347 1BCC 221A 6175  6F96 FA2E D12D 3E7E 013F
    
    * afaerber/tags/qom-cpu-for-anthony:
      target-i386: Cleanup 'foo=val' feature handling
      target-i386: Cleanup 'foo' feature handling
      target-i386: Convert 'check' and 'enforce' to static properties
      target-i386: Convert 'hv_spinlocks' to static property
      target-i386: Convert 'hv_vapic' to static property
      target-i386: Convert 'hv_relaxed' to static property
      cpu-exec: Optimize X86CPU usage in cpu_exec()
      target-i386: Move apic_state field from CPUX86State to X86CPU
      cputlb: Tidy memset() of arrays
      cputlb: Use memset() when flushing entries

commit 62a6a1fb895b881a938426fadb808f78a86ee222
Merge: 205b6b6 096fc76
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 10:48:46 2014 -0800

    Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20140107' into staging
    
    target-arm queue:
     * further A64 decoder patches, including enabling the aarch64-linux-user
       target; this includes full floating point support. Neon is not yet
       supported.
     * cadence UART model fixes.
     * some minor bug fixes and cleanups.
     * all the softfloat fixes required by the new A64 instructions;
       several of these will also be used by PPC.
    
    * pmaydell/tags/pull-target-arm-20140107: (61 commits)
      target-arm: A64: Add support for FCVT between half, single and double
      target-arm: A64: Add 1-source 32-to-32 and 64-to-64 FP instructions
      target-arm: A64: Add floating-point<->integer conversion instructions
      target-arm: A64: Add floating-point<->fixed-point instructions
      target-arm: A64: Add extra VFP fixed point conversion helpers
      target-arm: Ignore most exceptions from scalbn when doing fixpoint conversion
      target-arm: Rename A32 VFP conversion helpers
      target-arm: Prepare VFP_CONV_FIX helpers for A64 uses
      softfloat: Add support for ties-away rounding
      softfloat: Refactor code handling various rounding modes
      softfloat: Add float16 <=> float64 conversion functions
      softfloat: Factor out RoundAndPackFloat16 and NormalizeFloat16Subnormal
      softfloat: Provide complete set of accessors for fp state
      softfloat: Fix float64_to_uint32_round_to_zero
      softfloat: Fix float64_to_uint32
      softfloat: Fix float64_to_uint64_round_to_zero
      softfloat: Add float32_to_uint64()
      softfloat: Fix factor 2 error for scalbn on denormal inputs
      softfloat: Only raise Invalid when conversions to int are out of range
      softfloat: Fix float64_to_uint64
      ...
    
    Conflicts:
    	target-arm/cpu.h
    
    aliguori: resolved trivial conflict
    
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 205b6b617519d53f17ef2158ff18cb0fe50f5d6c
Merge: 1d327fb f0116c5
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Fri Jan 10 10:47:30 2014 -0800

    Merge remote-tracking branch 'riku/linux-user-for-upstream' into staging
    
    * riku/linux-user-for-upstream:
      linux-user: Remove regs parameter of load_elf_binary and load_flt_binary
      linux-user: Support the accept4 socketcall
    
    Message-id: 1389364137-23287-1-git-send-email-riku.voipio at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit f0116c5458dc3be398ee7ef8daeaa02ba738bdc1
Author: Will Newton <will.newton at linaro.org>
Date:   Thu Jan 9 09:10:50 2014 +0000

    linux-user: Remove regs parameter of load_elf_binary and load_flt_binary
    
    The regs parameter is not used anywhere, so remove it.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Reviewed-by: Erik de Castro Lopo <erikd at mega-nerd.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8dd424d..5902f16 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1998,8 +1998,7 @@ give_up:
     free(syms);
 }
 
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info)
+int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 {
     struct image_info interp_info;
     struct elfhdr elf_ex;
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index ceb89bb..566a7a8 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -704,8 +704,7 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
 
 #endif /* CONFIG_BINFMT_SHARED_FLAT */
 
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info)
+int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
 {
     struct lib_info libinfo[MAX_SHARED_LIBS];
     abi_ulong p = bprm->p;
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index a1fe5ed..f2997c2 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -154,13 +154,13 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
                 && bprm->buf[1] == 'E'
                 && bprm->buf[2] == 'L'
                 && bprm->buf[3] == 'F') {
-            retval = load_elf_binary(bprm, regs, infop);
+            retval = load_elf_binary(bprm, infop);
 #if defined(TARGET_HAS_BFLT)
         } else if (bprm->buf[0] == 'b'
                 && bprm->buf[1] == 'F'
                 && bprm->buf[2] == 'L'
                 && bprm->buf[3] == 'T') {
-            retval = load_flt_binary(bprm,regs,infop);
+            retval = load_flt_binary(bprm, infop);
 #endif
         } else {
             return -ENOEXEC;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index e2717e0..c2f74f3 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -178,10 +178,8 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
              struct target_pt_regs * regs, struct image_info *infop,
              struct linux_binprm *);
 
-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
-                    struct image_info * info);
+int load_elf_binary(struct linux_binprm *bprm, struct image_info *info);
+int load_flt_binary(struct linux_binprm *bprm, struct image_info *info);
 
 abi_long memcpy_to_target(abi_ulong dest, const void *src,
                           unsigned long len);
commit b9d36eb2c7d73875ef44182f18d625f1bc4c7fda
Author: André Hentschel <nerv at dawncrow.de>
Date:   Mon Jan 6 20:18:52 2014 +0100

    linux-user: Support the accept4 socketcall
    
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: André Hentschel <nerv at dawncrow.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Erik de Castro Lopo <erikd at mega-nerd.com>
    Reviewed-by: Laurent Vivier <laurent at vivier.eu>
    Signed-off-by: Riku Voipio <riku.voipio at linaro.org>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index efd1453..0ac05b8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2245,6 +2245,22 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
             ret = do_accept4(sockfd, target_addr, target_addrlen, 0);
         }
         break;
+    case SOCKOP_accept4:
+        {
+            abi_ulong sockfd;
+            abi_ulong target_addr, target_addrlen;
+            abi_ulong flags;
+
+            if (get_user_ual(sockfd, vptr)
+                || get_user_ual(target_addr, vptr + n)
+                || get_user_ual(target_addrlen, vptr + 2 * n)
+                || get_user_ual(flags, vptr + 3 * n)) {
+                return -TARGET_EFAULT;
+            }
+
+            ret = do_accept4(sockfd, target_addr, target_addrlen, flags);
+        }
+        break;
     case SOCKOP_getsockname:
         {
             abi_ulong sockfd;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index cf08db5..ae30476 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -27,6 +27,7 @@
 #define SOCKOP_getsockopt       15
 #define SOCKOP_sendmsg          16
 #define SOCKOP_recvmsg          17
+#define SOCKOP_accept4          18
 
 #define IPCOP_semop		1
 #define IPCOP_semget		2
commit 1d327fb4c72b898f7500989f3e624b7349581159
Merge: 074dcc2 2a13f99
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Jan 9 13:56:27 2014 -0800

    Merge remote-tracking branch 'otubo/seccomp' into staging
    
    * otubo/seccomp:
      seccomp: exit if seccomp_init() fails
    
    Message-id: 1387565447-24241-1-git-send-email-otubo at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 074dcc228a92de8285ada7d7a0f14549de7aacaa
Merge: c06f13c 7826163
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Jan 9 13:44:00 2014 -0800

    Merge remote-tracking branch 'rth/ldst-i386-2' into staging
    
    * rth/ldst-i386-2: (49 commits)
      target-i386: Tidy ljmp
      target-i386: Rename gen_op_jmp_T0 to gen_op_jmp_v
      target-i386: Tidy some size computation
      target-i386: Remove gen_op_mov_reg_A0
      target-i386: Remove gen_op_mov_TN_reg
      target-i386: Remove gen_op_addl_T0_T1
      target-i386: Remove gen_op_mov_reg_T1
      target-i386: Remove gen_op_mov_reg_T0
      target-i386: Tidy cpu_regs initialization
      target_i386: Clean up gen_pop_T0
      target-i386: Combine gen_push_T* into gen_push_v
      target-i386: Tidy addr16 code in gen_lea_modrm
      target-i386: Change dflag to TCGMemOp
      target-i386: Change gen_op_mov_reg_A0 size parameter to TCGMemOp
      target-i386: Change aflag to TCGMemOp
      target-i386: Change gen_op_j*z_ecx size parameter to TCGMemOp
      target-i386: Change gen_op_add_reg_* size parameter to TCGMemOp
      target-i386: Use TCGMemOp for 'ot' variables
      target-i386: Remove gen_op_andl_A0_ffff
      target-i386: Remove gen_op_movl_T0_T1
      ...
    
    Message-id: 1389128439-10067-1-git-send-email-rth at twiddle.net
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit c06f13c6da306180e9531114570d7800357f7446
Merge: 666eb03 11c308b
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Jan 9 11:24:48 2014 -0800

    Merge remote-tracking branch 'afaerber/tags/qom-devices-for-anthony' into staging
    
    QOM infrastructure fixes and device conversions
    
    * QOM interface fixes and unit test
    * Device no_user sanitization and documentation
    * Device error reporting improvement
    * Conversion of APIC, ICC, IOAPIC to QOM realization model
    
    # gpg: Signature made Tue 24 Dec 2013 09:04:05 AM PST using RSA key ID 3E7E013F
    # gpg: Good signature from "Andreas Färber <afaerber at suse.de>"
    # gpg:                 aka "Andreas Färber <afaerber at suse.com>"
    # gpg: WARNING: This key is not certified with a trusted signature!
    # gpg:          There is no indication that the signature belongs to the owner.
    # Primary key fingerprint: 174F 0347 1BCC 221A 6175  6F96 FA2E D12D 3E7E 013F
    
    * afaerber/tags/qom-devices-for-anthony: (24 commits)
      qdev-monitor: Improve error message for -device nonexistant
      ioapic: QOM'ify ioapic
      ioapic: Cleanup for QOM'ification
      icc_bus: QOM'ify ICC
      apic: QOM'ify APIC
      apic: Cleanup for QOM'ification
      qdev: Drop misleading qbus_free() function
      qom: Detect bad reentrance during object_class_foreach()
      tests: Test QOM interface casting
      qom: Do not register interface "types" in the type table and fix names
      qom: Split out object and class caches
      qdev: Document that pointer properties kill device_add
      hw: cannot_instantiate_with_device_add_yet due to pointer props
      qdev-monitor: Avoid device_add crashing on non-device driver name
      qdev: Do not let the user try to device_add when it cannot work
      isa: Clean up use of cannot_instantiate_with_device_add_yet
      vt82c686: Clean up use of cannot_instantiate_with_device_add_yet
      piix3 piix4: Clean up use of cannot_instantiate_with_device_add_yet
      ich9: Document why cannot_instantiate_with_device_add_yet
      pci-host: Consistently set cannot_instantiate_with_device_add_yet
      ...

commit 666eb032d34961a06713049c56361179903527e4
Merge: b61740d 5862ad0
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Jan 9 11:24:12 2014 -0800

    Merge remote-tracking branch 'mjt/trivial-patches' into staging
    
    * mjt/trivial-patches:
      acpi unit-test: Remove temporary disk after test
      mainstone: Fix duplicate array values for key 'space'
      pxa27x: Add 'const' attribute to keyboard maps
      pxa27x: Reduce size of keyboard matrix mapping
      doc: Mention chardev:id in available devices for -serial
      configure: Python tests must be done before help message
      configure: Rewrite code for help message
      fix -boot strict regressed in commit 6ef4716
      vl: make boot_strict variable static (not used outside vl.c)
      x86: only allow real mode to access 32bit without LMA
      linux-user: Use macro TARGET_NSIG_WORDS where possible
      exynos4210: Use macro ARRAY_SIZE where possible
      ui/cocoa: Use macro ARRAY_SIZE where possible
      misc: Use macro ARRAY_SIZE where possible
      openrisc: Fix spelling in comment (transaltion -> translation)
      hw/arm/highbank: Simplify code (memory region in device state)
    
    Message-id: 1388182050-10270-1-git-send-email-mjt at msgid.tls.msk.ru
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit b61740dbef8d1c8fda8a0f46ecb617e6e865e9e2
Merge: f976b09 8900aad
Author: Anthony Liguori <aliguori at amazon.com>
Date:   Thu Jan 9 11:23:49 2014 -0800

    Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20140108' into staging
    
    target-arm queue:
     * further A64 decoder patches, including enabling the aarch64-linux-user
       target; this includes full floating point support. Neon is not yet
       supported.
     * cadence UART model fixes.
     * some minor bug fixes and cleanups.
     * all the softfloat fixes required by the new A64 instructions;
       several of these will also be used by PPC.
    
    # gpg: Signature made Wed 08 Jan 2014 11:25:12 AM PST using RSA key ID 14360CDE
    # gpg: Can't check signature: public key not found
    
    * pmaydell/tags/pull-target-arm-20140108: (76 commits)
      target-arm: A64: Add support for FCVT between half, single and double
      target-arm: A64: Add 1-source 32-to-32 and 64-to-64 FP instructions
      target-arm: A64: Add floating-point<->integer conversion instructions
      target-arm: A64: Add floating-point<->fixed-point instructions
      target-arm: A64: Add extra VFP fixed point conversion helpers
      target-arm: Ignore most exceptions from scalbn when doing fixpoint conversion
      target-arm: Rename A32 VFP conversion helpers
      target-arm: Prepare VFP_CONV_FIX helpers for A64 uses
      softfloat: Add support for ties-away rounding
      softfloat: Refactor code handling various rounding modes
      softfloat: Add float16 <=> float64 conversion functions
      softfloat: Factor out RoundAndPackFloat16 and NormalizeFloat16Subnormal
      softfloat: Provide complete set of accessors for fp state
      softfloat: Fix float64_to_uint32_round_to_zero
      softfloat: Fix float64_to_uint32
      softfloat: Fix float64_to_uint64_round_to_zero
      softfloat: Add float32_to_uint64()
      softfloat: Fix factor 2 error for scalbn on denormal inputs
      softfloat: Only raise Invalid when conversions to int are out of range
      softfloat: Fix float64_to_uint64
      ...
    
    Message-id: 1389209439-25448-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at amazon.com>

commit 8900aad218f8f2348bcd688eacf06d6c1f66bc69
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:15 2014 +0000

    target-arm: A64: Add support for FCVT between half, single and double
    
    Add support for FCVT between half, single and double precision.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c6a6281..c708f15 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4089,6 +4089,26 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
     return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
 }
 
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, CPUARMState *env)
+{
+    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
+    float64 r = float16_to_float64(make_float16(a), ieee, &env->vfp.fp_status);
+    if (ieee) {
+        return float64_maybe_silence_nan(r);
+    }
+    return r;
+}
+
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, CPUARMState *env)
+{
+    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
+    float16 r = float64_to_float16(a, ieee, &env->vfp.fp_status);
+    if (ieee) {
+        r = float16_maybe_silence_nan(r);
+    }
+    return float16_val(r);
+}
+
 #define float32_two make_float32(0x40000000)
 #define float32_three make_float32(0x40400000)
 #define float32_one_point_five make_float32(0x3fc00000)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 7532e29..70872df 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -154,6 +154,8 @@ DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
+DEF_HELPER_FLAGS_2(vfp_fcvt_f16_to_f64, TCG_CALL_NO_RWG, f64, i32, env)
+DEF_HELPER_FLAGS_2(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, i32, f64, env)
 
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 345a47b..cf80c46 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3498,6 +3498,72 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
     tcg_temp_free_i64(tcg_res);
 }
 
+static void handle_fp_fcvt(DisasContext *s, int opcode,
+                           int rd, int rn, int dtype, int ntype)
+{
+    switch (ntype) {
+    case 0x0:
+    {
+        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
+        if (dtype == 1) {
+            /* Single to double */
+            TCGv_i64 tcg_rd = tcg_temp_new_i64();
+            gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
+            write_fp_dreg(s, rd, tcg_rd);
+            tcg_temp_free_i64(tcg_rd);
+        } else {
+            /* Single to half */
+            TCGv_i32 tcg_rd = tcg_temp_new_i32();
+            gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
+            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
+            write_fp_sreg(s, rd, tcg_rd);
+            tcg_temp_free_i32(tcg_rd);
+        }
+        tcg_temp_free_i32(tcg_rn);
+        break;
+    }
+    case 0x1:
+    {
+        TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
+        TCGv_i32 tcg_rd = tcg_temp_new_i32();
+        if (dtype == 0) {
+            /* Double to single */
+            gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
+        } else {
+            /* Double to half */
+            gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
+            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
+        }
+        write_fp_sreg(s, rd, tcg_rd);
+        tcg_temp_free_i32(tcg_rd);
+        tcg_temp_free_i64(tcg_rn);
+        break;
+    }
+    case 0x3:
+    {
+        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
+        tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
+        if (dtype == 0) {
+            /* Half to single */
+            TCGv_i32 tcg_rd = tcg_temp_new_i32();
+            gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
+            write_fp_sreg(s, rd, tcg_rd);
+            tcg_temp_free_i32(tcg_rd);
+        } else {
+            /* Half to double */
+            TCGv_i64 tcg_rd = tcg_temp_new_i64();
+            gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
+            write_fp_dreg(s, rd, tcg_rd);
+            tcg_temp_free_i64(tcg_rd);
+        }
+        tcg_temp_free_i32(tcg_rn);
+        break;
+    }
+    default:
+        abort();
+    }
+}
+
 /* C3.6.25 Floating point data-processing (1 source)
  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
  * +---+---+---+-----------+------+---+--------+-----------+------+------+
@@ -3513,9 +3579,16 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
 
     switch (opcode) {
     case 0x4: case 0x5: case 0x7:
+    {
         /* FCVT between half, single and double precision */
-        unsupported_encoding(s, insn);
+        int dtype = extract32(opcode, 0, 2);
+        if (type == 2 || dtype == type) {
+            unallocated_encoding(s);
+            return;
+        }
+        handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
         break;
+    }
     case 0x0 ... 0x3:
     case 0x8 ... 0xc:
     case 0xe ... 0xf:
commit d9b0848d944aab124f03cedc8f54c3940450f3b0
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:14 2014 +0000

    target-arm: A64: Add 1-source 32-to-32 and 64-to-64 FP instructions
    
    This patch adds support for those instructions in the  "Floating-point
    data-processing (1 source)" group which are simple 32-bit-to-32-bit
    or 64-bit-to-64-bit operations (ie everything except FCVT between
    single/double/half precision).
    
    We put the new round-to-int helpers in helper.c because they will
    also be used by the new ARMv8 A32/T32 rounding instructions.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, merged single and double precision patches,
     updated to new infrastructure.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM: reworked decode, split FCVT out into their own patch]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2e76d0b..c6a6281 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4353,3 +4353,48 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     float_status *fpst = fpstp;
     return float64_muladd(a, b, c, 0, fpst);
 }
+
+/* ARMv8 round to integral */
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
+{
+    return float32_round_to_int(x, fp_status);
+}
+
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
+{
+    return float64_round_to_int(x, fp_status);
+}
+
+float32 HELPER(rints)(float32 x, void *fp_status)
+{
+    int old_flags = get_float_exception_flags(fp_status), new_flags;
+    float32 ret;
+
+    ret = float32_round_to_int(x, fp_status);
+
+    /* Suppress any inexact exceptions the conversion produced */
+    if (!(old_flags & float_flag_inexact)) {
+        new_flags = get_float_exception_flags(fp_status);
+        set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
+    }
+
+    return ret;
+}
+
+float64 HELPER(rintd)(float64 x, void *fp_status)
+{
+    int old_flags = get_float_exception_flags(fp_status), new_flags;
+    float64 ret;
+
+    ret = float64_round_to_int(x, fp_status);
+
+    new_flags = get_float_exception_flags(fp_status);
+
+    /* Suppress any inexact exceptions the conversion produced */
+    if (!(old_flags & float_flag_inexact)) {
+        new_flags = get_float_exception_flags(fp_status);
+        set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
+    }
+
+    return ret;
+}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 25b6b4f..7532e29 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -171,6 +171,11 @@ DEF_HELPER_3(shr_cc, i32, env, i32, i32)
 DEF_HELPER_3(sar_cc, i32, env, i32, i32)
 DEF_HELPER_3(ror_cc, i32, env, i32, i32)
 
+DEF_HELPER_FLAGS_2(rints_exact, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(rintd_exact, TCG_CALL_NO_RWG, f64, f64, ptr)
+DEF_HELPER_FLAGS_2(rints, TCG_CALL_NO_RWG, f32, f32, ptr)
+DEF_HELPER_FLAGS_2(rintd, TCG_CALL_NO_RWG, f64, f64, ptr)
+
 /* neon_helper.c */
 DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
 DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 9b23d37..345a47b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3386,6 +3386,118 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
     }
 }
 
+/* C3.6.25 Floating-point data-processing (1 source) - single precision */
+static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
+{
+    TCGv_ptr fpst;
+    TCGv_i32 tcg_op;
+    TCGv_i32 tcg_res;
+
+    fpst = get_fpstatus_ptr();
+    tcg_op = read_fp_sreg(s, rn);
+    tcg_res = tcg_temp_new_i32();
+
+    switch (opcode) {
+    case 0x0: /* FMOV */
+        tcg_gen_mov_i32(tcg_res, tcg_op);
+        break;
+    case 0x1: /* FABS */
+        gen_helper_vfp_abss(tcg_res, tcg_op);
+        break;
+    case 0x2: /* FNEG */
+        gen_helper_vfp_negs(tcg_res, tcg_op);
+        break;
+    case 0x3: /* FSQRT */
+        gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
+        break;
+    case 0x8: /* FRINTN */
+    case 0x9: /* FRINTP */
+    case 0xa: /* FRINTM */
+    case 0xb: /* FRINTZ */
+    case 0xc: /* FRINTA */
+    {
+        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+        gen_helper_rints(tcg_res, tcg_op, fpst);
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+        tcg_temp_free_i32(tcg_rmode);
+        break;
+    }
+    case 0xe: /* FRINTX */
+        gen_helper_rints_exact(tcg_res, tcg_op, fpst);
+        break;
+    case 0xf: /* FRINTI */
+        gen_helper_rints(tcg_res, tcg_op, fpst);
+        break;
+    default:
+        abort();
+    }
+
+    write_fp_sreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i32(tcg_op);
+    tcg_temp_free_i32(tcg_res);
+}
+
+/* C3.6.25 Floating-point data-processing (1 source) - double precision */
+static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
+{
+    TCGv_ptr fpst;
+    TCGv_i64 tcg_op;
+    TCGv_i64 tcg_res;
+
+    fpst = get_fpstatus_ptr();
+    tcg_op = read_fp_dreg(s, rn);
+    tcg_res = tcg_temp_new_i64();
+
+    switch (opcode) {
+    case 0x0: /* FMOV */
+        tcg_gen_mov_i64(tcg_res, tcg_op);
+        break;
+    case 0x1: /* FABS */
+        gen_helper_vfp_absd(tcg_res, tcg_op);
+        break;
+    case 0x2: /* FNEG */
+        gen_helper_vfp_negd(tcg_res, tcg_op);
+        break;
+    case 0x3: /* FSQRT */
+        gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
+        break;
+    case 0x8: /* FRINTN */
+    case 0x9: /* FRINTP */
+    case 0xa: /* FRINTM */
+    case 0xb: /* FRINTZ */
+    case 0xc: /* FRINTA */
+    {
+        TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+        gen_helper_rintd(tcg_res, tcg_op, fpst);
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+        tcg_temp_free_i32(tcg_rmode);
+        break;
+    }
+    case 0xe: /* FRINTX */
+        gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
+        break;
+    case 0xf: /* FRINTI */
+        gen_helper_rintd(tcg_res, tcg_op, fpst);
+        break;
+    default:
+        abort();
+    }
+
+    write_fp_dreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i64(tcg_op);
+    tcg_temp_free_i64(tcg_res);
+}
+
 /* C3.6.25 Floating point data-processing (1 source)
  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
  * +---+---+---+-----------+------+---+--------+-----------+------+------+
@@ -3394,7 +3506,35 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_1src(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int type = extract32(insn, 22, 2);
+    int opcode = extract32(insn, 15, 6);
+    int rn = extract32(insn, 5, 5);
+    int rd = extract32(insn, 0, 5);
+
+    switch (opcode) {
+    case 0x4: case 0x5: case 0x7:
+        /* FCVT between half, single and double precision */
+        unsupported_encoding(s, insn);
+        break;
+    case 0x0 ... 0x3:
+    case 0x8 ... 0xc:
+    case 0xe ... 0xf:
+        /* 32-to-32 and 64-to-64 ops */
+        switch (type) {
+        case 0:
+            handle_fp_1src_single(s, opcode, rd, rn);
+            break;
+        case 1:
+            handle_fp_1src_double(s, opcode, rd, rn);
+            break;
+        default:
+            unallocated_encoding(s);
+        }
+        break;
+    default:
+        unallocated_encoding(s);
+        break;
+    }
 }
 
 /* C3.6.26 Floating-point data-processing (2 source) - single precision */
commit c436d40614ccfa756bbf3d7448356889ede825fb
Author: Will Newton <will.newton at linaro.org>
Date:   Tue Jan 7 17:19:14 2014 +0000

    target-arm: A64: Add floating-point<->integer conversion instructions
    
    Add support for the AArch64 floating-point <-> integer conversion
    instructions to disas_fpintconv. In the process we can rearrange
    and simplify the detection of unallocated encodings a little.
    We also correct a typo in the instruction encoding diagram for this
    instruction group: bit 21 is 1, not 0.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ec8abc7..9b23d37 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3904,7 +3904,7 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
 /* C3.6.30 Floating point <-> integer conversions
  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
- * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
+ * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
  */
 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
@@ -3917,10 +3917,20 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
     bool sbit = extract32(insn, 29, 1);
     bool sf = extract32(insn, 31, 1);
 
-    if (!sbit && (rmode < 2) && (opcode > 5)) {
+    if (sbit) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (opcode > 5) {
         /* FMOV */
         bool itof = opcode & 1;
 
+        if (rmode >= 2) {
+            unallocated_encoding(s);
+            return;
+        }
+
         switch (sf << 3 | type << 1 | rmode) {
         case 0x0: /* 32 bit */
         case 0xa: /* 64 bit */
@@ -3935,7 +3945,14 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
         handle_fmov(s, rd, rn, type, itof);
     } else {
         /* actual FP conversions */
-        unsupported_encoding(s, insn);
+        bool itof = extract32(opcode, 1, 1);
+
+        if (type > 1 || (rmode != 0 && opcode > 1)) {
+            unallocated_encoding(s);
+            return;
+        }
+
+        handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
     }
 }
 
commit 52a1f6a3abb88ab875d5a70cec1048bb05e47263
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Jan 7 17:19:14 2014 +0000

    target-arm: A64: Add floating-point<->fixed-point instructions
    
    This patch adds emulation for the instruction group labeled
    "Floating-point <-> fixed-point conversions" in the ARM ARM.
    
    Namely this includes the instructions SCVTF, UCVTF, FCVTZS, FCVTZU
    (scalar, fixed-point).
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, rebased, updated to new infrastructure.
     Applied bug fixes from Michael Matz and Janne Grunau.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM: significant cleanup]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index dcf6aa4..2e76d0b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4035,6 +4035,19 @@ VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
 #undef VFP_CONV_FIX_FLOAT
 #undef VFP_CONV_FLOAT_FIX_ROUND
 
+/* Set the current fp rounding mode and return the old one.
+ * The argument is a softfloat float_round_ value.
+ */
+uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
+{
+    float_status *fp_status = &env->vfp.fp_status;
+
+    uint32_t prev_rmode = get_float_rounding_mode(fp_status);
+    set_float_rounding_mode(rmode, fp_status);
+
+    return prev_rmode;
+}
+
 /* Half precision conversions.  */
 static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
 {
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 2e1af46..25b6b4f 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -148,6 +148,8 @@ DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
 
+DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, env)
+
 DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index c9fbf0f..ec8abc7 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3186,6 +3186,34 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
     }
 }
 
+/* Convert ARM rounding mode to softfloat */
+static inline int arm_rmode_to_sf(int rmode)
+{
+    switch (rmode) {
+    case FPROUNDING_TIEAWAY:
+        rmode = float_round_ties_away;
+        break;
+    case FPROUNDING_ODD:
+        /* FIXME: add support for TIEAWAY and ODD */
+        qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
+                      rmode);
+    case FPROUNDING_TIEEVEN:
+    default:
+        rmode = float_round_nearest_even;
+        break;
+    case FPROUNDING_POSINF:
+        rmode = float_round_up;
+        break;
+    case FPROUNDING_NEGINF:
+        rmode = float_round_down;
+        break;
+    case FPROUNDING_ZERO:
+        rmode = float_round_to_zero;
+        break;
+    }
+    return rmode;
+}
+
 static void handle_fp_compare(DisasContext *s, bool is_double,
                               unsigned int rn, unsigned int rm,
                               bool cmp_with_zero, bool signal_all_nans)
@@ -3651,6 +3679,132 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_res);
 }
 
+/* Handle floating point <=> fixed point conversions. Note that we can
+ * also deal with fp <=> integer conversions as a special case (scale == 64)
+ * OPTME: consider handling that special case specially or at least skipping
+ * the call to scalbn in the helpers for zero shifts.
+ */
+static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
+                           bool itof, int rmode, int scale, int sf, int type)
+{
+    bool is_signed = !(opcode & 1);
+    bool is_double = type;
+    TCGv_ptr tcg_fpstatus;
+    TCGv_i32 tcg_shift;
+
+    tcg_fpstatus = get_fpstatus_ptr();
+
+    tcg_shift = tcg_const_i32(64 - scale);
+
+    if (itof) {
+        TCGv_i64 tcg_int = cpu_reg(s, rn);
+        if (!sf) {
+            TCGv_i64 tcg_extend = new_tmp_a64(s);
+
+            if (is_signed) {
+                tcg_gen_ext32s_i64(tcg_extend, tcg_int);
+            } else {
+                tcg_gen_ext32u_i64(tcg_extend, tcg_int);
+            }
+
+            tcg_int = tcg_extend;
+        }
+
+        if (is_double) {
+            TCGv_i64 tcg_double = tcg_temp_new_i64();
+            if (is_signed) {
+                gen_helper_vfp_sqtod(tcg_double, tcg_int,
+                                     tcg_shift, tcg_fpstatus);
+            } else {
+                gen_helper_vfp_uqtod(tcg_double, tcg_int,
+                                     tcg_shift, tcg_fpstatus);
+            }
+            write_fp_dreg(s, rd, tcg_double);
+            tcg_temp_free_i64(tcg_double);
+        } else {
+            TCGv_i32 tcg_single = tcg_temp_new_i32();
+            if (is_signed) {
+                gen_helper_vfp_sqtos(tcg_single, tcg_int,
+                                     tcg_shift, tcg_fpstatus);
+            } else {
+                gen_helper_vfp_uqtos(tcg_single, tcg_int,
+                                     tcg_shift, tcg_fpstatus);
+            }
+            write_fp_sreg(s, rd, tcg_single);
+            tcg_temp_free_i32(tcg_single);
+        }
+    } else {
+        TCGv_i64 tcg_int = cpu_reg(s, rd);
+        TCGv_i32 tcg_rmode;
+
+        if (extract32(opcode, 2, 1)) {
+            /* There are too many rounding modes to all fit into rmode,
+             * so FCVTA[US] is a special case.
+             */
+            rmode = FPROUNDING_TIEAWAY;
+        }
+
+        tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+
+        if (is_double) {
+            TCGv_i64 tcg_double = read_fp_dreg(s, rn);
+            if (is_signed) {
+                if (!sf) {
+                    gen_helper_vfp_tosld(tcg_int, tcg_double,
+                                         tcg_shift, tcg_fpstatus);
+                } else {
+                    gen_helper_vfp_tosqd(tcg_int, tcg_double,
+                                         tcg_shift, tcg_fpstatus);
+                }
+            } else {
+                if (!sf) {
+                    gen_helper_vfp_tould(tcg_int, tcg_double,
+                                         tcg_shift, tcg_fpstatus);
+                } else {
+                    gen_helper_vfp_touqd(tcg_int, tcg_double,
+                                         tcg_shift, tcg_fpstatus);
+                }
+            }
+            tcg_temp_free_i64(tcg_double);
+        } else {
+            TCGv_i32 tcg_single = read_fp_sreg(s, rn);
+            if (sf) {
+                if (is_signed) {
+                    gen_helper_vfp_tosqs(tcg_int, tcg_single,
+                                         tcg_shift, tcg_fpstatus);
+                } else {
+                    gen_helper_vfp_touqs(tcg_int, tcg_single,
+                                         tcg_shift, tcg_fpstatus);
+                }
+            } else {
+                TCGv_i32 tcg_dest = tcg_temp_new_i32();
+                if (is_signed) {
+                    gen_helper_vfp_tosls(tcg_dest, tcg_single,
+                                         tcg_shift, tcg_fpstatus);
+                } else {
+                    gen_helper_vfp_touls(tcg_dest, tcg_single,
+                                         tcg_shift, tcg_fpstatus);
+                }
+                tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
+                tcg_temp_free_i32(tcg_dest);
+            }
+            tcg_temp_free_i32(tcg_single);
+        }
+
+        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
+        tcg_temp_free_i32(tcg_rmode);
+
+        if (!sf) {
+            tcg_gen_ext32u_i64(tcg_int, tcg_int);
+        }
+    }
+
+    tcg_temp_free_ptr(tcg_fpstatus);
+    tcg_temp_free_i32(tcg_shift);
+}
+
 /* C3.6.29 Floating point <-> fixed point conversions
  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
@@ -3659,7 +3813,37 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int scale = extract32(insn, 10, 6);
+    int opcode = extract32(insn, 16, 3);
+    int rmode = extract32(insn, 19, 2);
+    int type = extract32(insn, 22, 2);
+    bool sbit = extract32(insn, 29, 1);
+    bool sf = extract32(insn, 31, 1);
+    bool itof;
+
+    if (sbit || (type > 1)
+        || (!sf && scale < 32)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch ((rmode << 3) | opcode) {
+    case 0x2: /* SCVTF */
+    case 0x3: /* UCVTF */
+        itof = true;
+        break;
+    case 0x18: /* FCVTZS */
+    case 0x19: /* FCVTZU */
+        itof = false;
+        break;
+    default:
+        unallocated_encoding(s);
+        return;
+    }
+
+    handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
 }
 
 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
commit 3c6a074a08ed3797624d4fb667564b9f3487eeaa
Author: Will Newton <will.newton at linaro.org>
Date:   Tue Jan 7 17:19:14 2014 +0000

    target-arm: A64: Add extra VFP fixed point conversion helpers
    
    Define the full set of floating point to fixed point conversion
    helpers required to support AArch64.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c995562..dcf6aa4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4012,16 +4012,25 @@ uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
 
 #define VFP_CONV_FIX(name, p, fsz, isz, itype)                   \
 VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype)                     \
-VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero)
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero) \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
+
+#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype)               \
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype)                     \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
 
 VFP_CONV_FIX(sh, d, 64, 64, int16)
 VFP_CONV_FIX(sl, d, 64, 64, int32)
+VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
 VFP_CONV_FIX(uh, d, 64, 64, uint16)
 VFP_CONV_FIX(ul, d, 64, 64, uint32)
+VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
 VFP_CONV_FIX(sh, s, 32, 32, int16)
 VFP_CONV_FIX(sl, s, 32, 32, int32)
+VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
 VFP_CONV_FIX(uh, s, 32, 32, uint16)
 VFP_CONV_FIX(ul, s, 32, 32, uint32)
+VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
 #undef VFP_CONV_FIX
 #undef VFP_CONV_FIX_FLOAT
 #undef VFP_CONV_FLOAT_FIX_ROUND
diff --git a/target-arm/helper.h b/target-arm/helper.h
index b785623..2e1af46 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -123,14 +123,30 @@ DEF_HELPER_3(vfp_toshd_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_tosld_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_tosqs, i64, f32, i32, ptr)
+DEF_HELPER_3(vfp_touhs, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touls, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touqs, i64, f32, i32, ptr)
+DEF_HELPER_3(vfp_toshd, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tosld, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tosqd, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_touhd, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tould, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_touqd, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_shtos, f32, i32, i32, ptr)
 DEF_HELPER_3(vfp_sltos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_sqtos, f32, i64, i32, ptr)
 DEF_HELPER_3(vfp_uhtos, f32, i32, i32, ptr)
 DEF_HELPER_3(vfp_ultos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_uqtos, f32, i64, i32, ptr)
 DEF_HELPER_3(vfp_shtod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_sltod, f64, i64, i32, ptr)
+DEF_HELPER_3(vfp_sqtod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
+DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
 
 DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
commit abe66f702cac88fd6b1ccdca5d6f0c57f814ab0f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:13 2014 +0000

    target-arm: Ignore most exceptions from scalbn when doing fixpoint conversion
    
    The VFP fixed point conversion helpers first call float_scalbn and
    then convert the result to an integer. This scalbn operation may
    set floating point exception flags for:
     * overflow & inexact (if it overflows to infinity)
     * input denormal squashed to zero
     * output denormal squashed to zero
    Of these, we only care about the input-denormal flag, since
    the output of the whole scale-and-convert operation will be
    an integer (so squashed-output-denormal and overflow don't
    apply). Suppress the others by saving the pre-scalb exception
    flags and only copying across a potential input-denormal flag.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index db4f516..c995562 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3986,18 +3986,27 @@ float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t  x, uint32_t shift, \
     return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
 }
 
+/* Notice that we want only input-denormal exception flags from the
+ * scalbn operation: the other possible flags (overflow+inexact if
+ * we overflow to infinity, output-denormal) aren't correct for the
+ * complete scale-and-convert operation.
+ */
 #define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
 uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
                                              uint32_t shift, \
                                              void *fpstp) \
 { \
     float_status *fpst = fpstp; \
+    int old_exc_flags = get_float_exception_flags(fpst); \
     float##fsz tmp; \
     if (float##fsz##_is_any_nan(x)) { \
         float_raise(float_flag_invalid, fpst); \
         return 0; \
     } \
     tmp = float##fsz##_scalbn(x, shift, fpst); \
+    old_exc_flags |= get_float_exception_flags(fpst) \
+        & float_flag_input_denormal; \
+    set_float_exception_flags(old_exc_flags, fpst); \
     return float##fsz##_to_##itype##round(tmp, fpst); \
 }
 
commit 16d5b3caca11360fd1d706403221c7bef40aa6f6
Author: Will Newton <will.newton at linaro.org>
Date:   Tue Jan 7 17:19:13 2014 +0000

    target-arm: Rename A32 VFP conversion helpers
    
    The VFP conversion helpers for A32 round to zero as this is the only
    rounding mode supported. Rename these helpers to make it clear that
    they round to zero and are not suitable for use in the AArch64 code.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5579565..db4f516 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3976,7 +3976,7 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
 }
 
 /* VFP3 fixed point conversion.  */
-#define VFP_CONV_FIX(name, p, fsz, isz, itype)                         \
+#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
 float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t  x, uint32_t shift, \
                                      void *fpstp) \
 { \
@@ -3984,9 +3984,12 @@ float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t  x, uint32_t shift, \
     float##fsz tmp; \
     tmp = itype##_to_##float##fsz(x, fpst); \
     return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
-} \
-uint##isz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
-                                      void *fpstp) \
+}
+
+#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
+uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
+                                             uint32_t shift, \
+                                             void *fpstp) \
 { \
     float_status *fpst = fpstp; \
     float##fsz tmp; \
@@ -3995,9 +3998,13 @@ uint##isz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
         return 0; \
     } \
     tmp = float##fsz##_scalbn(x, shift, fpst); \
-    return float##fsz##_to_##itype##_round_to_zero(tmp, fpst); \
+    return float##fsz##_to_##itype##round(tmp, fpst); \
 }
 
+#define VFP_CONV_FIX(name, p, fsz, isz, itype)                   \
+VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype)                     \
+VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero)
+
 VFP_CONV_FIX(sh, d, 64, 64, int16)
 VFP_CONV_FIX(sl, d, 64, 64, int32)
 VFP_CONV_FIX(uh, d, 64, 64, uint16)
@@ -4007,6 +4014,8 @@ VFP_CONV_FIX(sl, s, 32, 32, int32)
 VFP_CONV_FIX(uh, s, 32, 32, uint16)
 VFP_CONV_FIX(ul, s, 32, 32, uint32)
 #undef VFP_CONV_FIX
+#undef VFP_CONV_FIX_FLOAT
+#undef VFP_CONV_FLOAT_FIX_ROUND
 
 /* Half precision conversions.  */
 static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index dd1160e..b785623 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -115,14 +115,14 @@ DEF_HELPER_2(vfp_tosid, i32, f64, ptr)
 DEF_HELPER_2(vfp_tosizs, i32, f32, ptr)
 DEF_HELPER_2(vfp_tosizd, i32, f64, ptr)
 
-DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
-DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
-DEF_HELPER_3(vfp_touhs, i32, f32, i32, ptr)
-DEF_HELPER_3(vfp_touls, i32, f32, i32, ptr)
-DEF_HELPER_3(vfp_toshd, i64, f64, i32, ptr)
-DEF_HELPER_3(vfp_tosld, i64, f64, i32, ptr)
-DEF_HELPER_3(vfp_touhd, i64, f64, i32, ptr)
-DEF_HELPER_3(vfp_tould, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_toshs_round_to_zero, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_tosls_round_to_zero, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touhs_round_to_zero, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touls_round_to_zero, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_toshd_round_to_zero, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tosld_round_to_zero, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_shtos, f32, i32, i32, ptr)
 DEF_HELPER_3(vfp_sltos, f32, i32, i32, ptr)
 DEF_HELPER_3(vfp_uhtos, f32, i32, i32, ptr)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index d04fc9f..8d240e1 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -1098,27 +1098,29 @@ VFP_GEN_FTOI(tosi)
 VFP_GEN_FTOI(tosiz)
 #undef VFP_GEN_FTOI
 
-#define VFP_GEN_FIX(name) \
+#define VFP_GEN_FIX(name, round) \
 static inline void gen_vfp_##name(int dp, int shift, int neon) \
 { \
     TCGv_i32 tmp_shift = tcg_const_i32(shift); \
     TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
     if (dp) { \
-        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
+        gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
+                                        statusptr); \
     } else { \
-        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
+        gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
+                                        statusptr); \
     } \
     tcg_temp_free_i32(tmp_shift); \
     tcg_temp_free_ptr(statusptr); \
 }
-VFP_GEN_FIX(tosh)
-VFP_GEN_FIX(tosl)
-VFP_GEN_FIX(touh)
-VFP_GEN_FIX(toul)
-VFP_GEN_FIX(shto)
-VFP_GEN_FIX(slto)
-VFP_GEN_FIX(uhto)
-VFP_GEN_FIX(ulto)
+VFP_GEN_FIX(tosh, _round_to_zero)
+VFP_GEN_FIX(tosl, _round_to_zero)
+VFP_GEN_FIX(touh, _round_to_zero)
+VFP_GEN_FIX(toul, _round_to_zero)
+VFP_GEN_FIX(shto, )
+VFP_GEN_FIX(slto, )
+VFP_GEN_FIX(uhto, )
+VFP_GEN_FIX(ulto, )
 #undef VFP_GEN_FIX
 
 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
commit 8ed697e88b7ead01edca6bf762921b962c265c82
Author: Will Newton <will.newton at linaro.org>
Date:   Tue Jan 7 17:19:13 2014 +0000

    target-arm: Prepare VFP_CONV_FIX helpers for A64 uses
    
    Make the VFP_CONV_FIX helpers a little more flexible in
    preparation for the A64 uses. This requires two changes:
     * use the correct softfloat conversion function based on itype
       rather than always the int32 one; this is possible now that
       softfloat provides int16 versions and necessary for the
       future conversion-to-int64 A64 variants. This also allows
       us to drop the awkward 'sign' macro argument.
     * split the 'fsz' argument which currently controls both
       width of the input float type and width of the output
       integer type into two; this will allow us to specify the
       A64 64-bit-int-to-single conversion function, where the
       two widths are different.
    
    We can also drop the (itype##_t) cast now that softfloat
    guarantees that all the itype##_to_float* functions take
    an integer argument of exactly the correct type.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 6f629f3..5579565 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3976,17 +3976,17 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
 }
 
 /* VFP3 fixed point conversion.  */
-#define VFP_CONV_FIX(name, p, fsz, itype, sign) \
-float##fsz HELPER(vfp_##name##to##p)(uint##fsz##_t  x, uint32_t shift, \
-                                    void *fpstp) \
+#define VFP_CONV_FIX(name, p, fsz, isz, itype)                         \
+float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t  x, uint32_t shift, \
+                                     void *fpstp) \
 { \
     float_status *fpst = fpstp; \
     float##fsz tmp; \
-    tmp = sign##int32_to_##float##fsz((itype##_t)x, fpst); \
+    tmp = itype##_to_##float##fsz(x, fpst); \
     return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
 } \
-uint##fsz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
-                                       void *fpstp) \
+uint##isz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
+                                      void *fpstp) \
 { \
     float_status *fpst = fpstp; \
     float##fsz tmp; \
@@ -3998,14 +3998,14 @@ uint##fsz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
     return float##fsz##_to_##itype##_round_to_zero(tmp, fpst); \
 }
 
-VFP_CONV_FIX(sh, d, 64, int16, )
-VFP_CONV_FIX(sl, d, 64, int32, )
-VFP_CONV_FIX(uh, d, 64, uint16, u)
-VFP_CONV_FIX(ul, d, 64, uint32, u)
-VFP_CONV_FIX(sh, s, 32, int16, )
-VFP_CONV_FIX(sl, s, 32, int32, )
-VFP_CONV_FIX(uh, s, 32, uint16, u)
-VFP_CONV_FIX(ul, s, 32, uint32, u)
+VFP_CONV_FIX(sh, d, 64, 64, int16)
+VFP_CONV_FIX(sl, d, 64, 64, int32)
+VFP_CONV_FIX(uh, d, 64, 64, uint16)
+VFP_CONV_FIX(ul, d, 64, 64, uint32)
+VFP_CONV_FIX(sh, s, 32, 32, int16)
+VFP_CONV_FIX(sl, s, 32, 32, int32)
+VFP_CONV_FIX(uh, s, 32, 32, uint16)
+VFP_CONV_FIX(ul, s, 32, 32, uint32)
 #undef VFP_CONV_FIX
 
 /* Half precision conversions.  */
commit f9288a76f1819c2dbf8d2873aebab6aec0f461f5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:12 2014 +0000

    softfloat: Add support for ties-away rounding
    
    IEEE754-2008 specifies a new rounding mode:
    
    "roundTiesToAway: the floating-point number nearest to the infinitely
    precise result shall be delivered; if the two nearest floating-point
    numbers bracketing an unrepresentable infinitely precise result are
    equally near, the one with larger magnitude shall be delivered."
    
    Implement this new mode (it is needed for ARM). The general principle
    is that the required code is exactly like the ties-to-even code,
    except that we do not need to do the "in case of exact tie clear LSB
    to round-to-even", because the rounding operation naturally causes
    the exact tie to round up in magnitude.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6c7a90a..e0ea599 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -111,6 +111,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         roundIncrement = 0x40;
         break;
     case float_round_to_zero:
@@ -161,6 +162,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         increment = ((int64_t) absZ1 < 0);
         break;
     case float_round_to_zero:
@@ -214,6 +216,7 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
     roundNearestEven = (roundingMode == float_round_nearest_even);
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         increment = ((int64_t)absZ1 < 0);
         break;
     case float_round_to_zero:
@@ -366,6 +369,7 @@ static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         roundIncrement = 0x40;
         break;
     case float_round_to_zero:
@@ -550,6 +554,7 @@ static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         roundIncrement = 0x200;
         break;
     case float_round_to_zero:
@@ -734,6 +739,7 @@ static floatx80
     zSig0 |= ( zSig1 != 0 );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         break;
     case float_round_to_zero:
         roundIncrement = 0;
@@ -794,6 +800,7 @@ static floatx80
  precision80:
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         increment = ((int64_t)zSig1 < 0);
         break;
     case float_round_to_zero:
@@ -838,6 +845,7 @@ static floatx80
             if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
             switch (roundingMode) {
             case float_round_nearest_even:
+            case float_round_ties_away:
                 increment = ((int64_t)zSig1 < 0);
                 break;
             case float_round_to_zero:
@@ -1052,6 +1060,7 @@ static float128
     roundNearestEven = ( roundingMode == float_round_nearest_even );
     switch (roundingMode) {
     case float_round_nearest_even:
+    case float_round_ties_away:
         increment = ((int64_t)zSig2 < 0);
         break;
     case float_round_to_zero:
@@ -1114,6 +1123,7 @@ static float128
             if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
             switch (roundingMode) {
             case float_round_nearest_even:
+            case float_round_ties_away:
                 increment = ((int64_t)zSig2 < 0);
                 break;
             case float_round_to_zero:
@@ -1785,6 +1795,11 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
                 return packFloat32( aSign, 0x7F, 0 );
             }
             break;
+        case float_round_ties_away:
+            if (aExp == 0x7E) {
+                return packFloat32(aSign, 0x7F, 0);
+            }
+            break;
          case float_round_down:
             return make_float32(aSign ? 0xBF800000 : 0);
          case float_round_up:
@@ -1803,6 +1818,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
             z &= ~lastBitMask;
         }
         break;
+    case float_round_ties_away:
+        z += lastBitMask >> 1;
+        break;
     case float_round_to_zero:
         break;
     case float_round_up:
@@ -3183,6 +3201,9 @@ static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp,
             increment = zSig & (increment << 1);
         }
         break;
+    case float_round_ties_away:
+        increment = (mask + 1) >> 1;
+        break;
     case float_round_up:
         increment = zSign ? 0 : mask;
         break;
@@ -3487,6 +3508,11 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
                 return packFloat64( aSign, 0x3FF, 0 );
             }
             break;
+        case float_round_ties_away:
+            if (aExp == 0x3FE) {
+                return packFloat64(aSign, 0x3ff, 0);
+            }
+            break;
          case float_round_down:
             return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0);
          case float_round_up:
@@ -3506,6 +3532,9 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
             z &= ~lastBitMask;
         }
         break;
+    case float_round_ties_away:
+        z += lastBitMask >> 1;
+        break;
     case float_round_to_zero:
         break;
     case float_round_up:
@@ -4771,6 +4800,11 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
                     packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
             }
             break;
+        case float_round_ties_away:
+            if (aExp == 0x3FFE) {
+                return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000));
+            }
+            break;
          case float_round_down:
             return
                   aSign ?
@@ -4794,6 +4828,9 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
             z.low &= ~lastBitMask;
         }
         break;
+    case float_round_ties_away:
+        z.low += lastBitMask >> 1;
+        break;
     case float_round_to_zero:
         break;
     case float_round_up:
@@ -5862,6 +5899,15 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
                 }
             }
             break;
+        case float_round_ties_away:
+            if (lastBitMask) {
+                add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low);
+            } else {
+                if ((int64_t) z.low < 0) {
+                    ++z.high;
+                }
+            }
+            break;
         case float_round_to_zero:
             break;
         case float_round_up:
@@ -5893,6 +5939,11 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
                     return packFloat128( aSign, 0x3FFF, 0, 0 );
                 }
                 break;
+            case float_round_ties_away:
+                if (aExp == 0x3FFE) {
+                    return packFloat128(aSign, 0x3FFF, 0, 0);
+                }
+                break;
              case float_round_down:
                 return
                       aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
@@ -5916,6 +5967,9 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
                 z.high &= ~ lastBitMask;
             }
             break;
+        case float_round_ties_away:
+            z.high += lastBitMask>>1;
+            break;
         case float_round_to_zero:
             break;
         case float_round_up:
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 83d324a..806ae13 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -152,7 +152,8 @@ enum {
     float_round_nearest_even = 0,
     float_round_down         = 1,
     float_round_up           = 2,
-    float_round_to_zero      = 3
+    float_round_to_zero      = 3,
+    float_round_ties_away    = 4,
 };
 
 /*----------------------------------------------------------------------------
commit dc355b764de890e1b5872d0b402dccfd9a9b5286
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:12 2014 +0000

    softfloat: Refactor code handling various rounding modes
    
    Refactor the code in various functions which calculates rounding
    increments given the current rounding mode, so that instead of a
    set of nested if statements we have a simple switch statement.
    This will give us a clean place to add the case for the new
    tiesAway rounding mode.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index d4ca7cf..6c7a90a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -42,6 +42,9 @@ these four paragraphs for those parts of this code that are retained.
 
 #include "fpu/softfloat.h"
 
+/* We only need stdlib for abort() */
+#include <stdlib.h>
+
 /*----------------------------------------------------------------------------
 | Primitive arithmetic functions, including multi-word arithmetic, and
 | division and square root approximations.  (Can be specialized to target if
@@ -106,20 +109,21 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM)
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    roundIncrement = 0x40;
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            roundIncrement = 0;
-        }
-        else {
-            roundIncrement = 0x7F;
-            if ( zSign ) {
-                if ( roundingMode == float_round_up ) roundIncrement = 0;
-            }
-            else {
-                if ( roundingMode == float_round_down ) roundIncrement = 0;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        roundIncrement = 0x40;
+        break;
+    case float_round_to_zero:
+        roundIncrement = 0;
+        break;
+    case float_round_up:
+        roundIncrement = zSign ? 0 : 0x7f;
+        break;
+    case float_round_down:
+        roundIncrement = zSign ? 0x7f : 0;
+        break;
+    default:
+        abort();
     }
     roundBits = absZ & 0x7F;
     absZ = ( absZ + roundIncrement )>>7;
@@ -155,19 +159,21 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    increment = ( (int64_t) absZ1 < 0 );
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            increment = 0;
-        }
-        else {
-            if ( zSign ) {
-                increment = ( roundingMode == float_round_down ) && absZ1;
-            }
-            else {
-                increment = ( roundingMode == float_round_up ) && absZ1;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = ((int64_t) absZ1 < 0);
+        break;
+    case float_round_to_zero:
+        increment = 0;
+        break;
+    case float_round_up:
+        increment = !zSign && absZ1;
+        break;
+    case float_round_down:
+        increment = zSign && absZ1;
+        break;
+    default:
+        abort();
     }
     if ( increment ) {
         ++absZ0;
@@ -206,17 +212,21 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = (roundingMode == float_round_nearest_even);
-    increment = ((int64_t)absZ1 < 0);
-    if (!roundNearestEven) {
-        if (roundingMode == float_round_to_zero) {
-            increment = 0;
-        } else if (absZ1) {
-            if (zSign) {
-                increment = (roundingMode == float_round_down) && absZ1;
-            } else {
-                increment = (roundingMode == float_round_up) && absZ1;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = ((int64_t)absZ1 < 0);
+        break;
+    case float_round_to_zero:
+        increment = 0;
+        break;
+    case float_round_up:
+        increment = !zSign && absZ1;
+        break;
+    case float_round_down:
+        increment = zSign && absZ1;
+        break;
+    default:
+        abort();
     }
     if (increment) {
         ++absZ0;
@@ -354,20 +364,22 @@ static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    roundIncrement = 0x40;
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            roundIncrement = 0;
-        }
-        else {
-            roundIncrement = 0x7F;
-            if ( zSign ) {
-                if ( roundingMode == float_round_up ) roundIncrement = 0;
-            }
-            else {
-                if ( roundingMode == float_round_down ) roundIncrement = 0;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        roundIncrement = 0x40;
+        break;
+    case float_round_to_zero:
+        roundIncrement = 0;
+        break;
+    case float_round_up:
+        roundIncrement = zSign ? 0 : 0x7f;
+        break;
+    case float_round_down:
+        roundIncrement = zSign ? 0x7f : 0;
+        break;
+    default:
+        abort();
+        break;
     }
     roundBits = zSig & 0x7F;
     if ( 0xFD <= (uint16_t) zExp ) {
@@ -536,20 +548,21 @@ static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    roundIncrement = 0x200;
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            roundIncrement = 0;
-        }
-        else {
-            roundIncrement = 0x3FF;
-            if ( zSign ) {
-                if ( roundingMode == float_round_up ) roundIncrement = 0;
-            }
-            else {
-                if ( roundingMode == float_round_down ) roundIncrement = 0;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        roundIncrement = 0x200;
+        break;
+    case float_round_to_zero:
+        roundIncrement = 0;
+        break;
+    case float_round_up:
+        roundIncrement = zSign ? 0 : 0x3ff;
+        break;
+    case float_round_down:
+        roundIncrement = zSign ? 0x3ff : 0;
+        break;
+    default:
+        abort();
     }
     roundBits = zSig & 0x3FF;
     if ( 0x7FD <= (uint16_t) zExp ) {
@@ -719,19 +732,20 @@ static floatx80
         goto precision80;
     }
     zSig0 |= ( zSig1 != 0 );
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            roundIncrement = 0;
-        }
-        else {
-            roundIncrement = roundMask;
-            if ( zSign ) {
-                if ( roundingMode == float_round_up ) roundIncrement = 0;
-            }
-            else {
-                if ( roundingMode == float_round_down ) roundIncrement = 0;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        break;
+    case float_round_to_zero:
+        roundIncrement = 0;
+        break;
+    case float_round_up:
+        roundIncrement = zSign ? 0 : roundMask;
+        break;
+    case float_round_down:
+        roundIncrement = zSign ? roundMask : 0;
+        break;
+    default:
+        abort();
     }
     roundBits = zSig0 & roundMask;
     if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
@@ -778,19 +792,21 @@ static floatx80
     if ( zSig0 == 0 ) zExp = 0;
     return packFloatx80( zSign, zExp, zSig0 );
  precision80:
-    increment = ( (int64_t) zSig1 < 0 );
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            increment = 0;
-        }
-        else {
-            if ( zSign ) {
-                increment = ( roundingMode == float_round_down ) && zSig1;
-            }
-            else {
-                increment = ( roundingMode == float_round_up ) && zSig1;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = ((int64_t)zSig1 < 0);
+        break;
+    case float_round_to_zero:
+        increment = 0;
+        break;
+    case float_round_up:
+        increment = !zSign && zSig1;
+        break;
+    case float_round_down:
+        increment = zSign && zSig1;
+        break;
+    default:
+        abort();
     }
     if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
         if (    ( 0x7FFE < zExp )
@@ -820,16 +836,21 @@ static floatx80
             zExp = 0;
             if ( isTiny && zSig1 ) float_raise( float_flag_underflow STATUS_VAR);
             if ( zSig1 ) STATUS(float_exception_flags) |= float_flag_inexact;
-            if ( roundNearestEven ) {
-                increment = ( (int64_t) zSig1 < 0 );
-            }
-            else {
-                if ( zSign ) {
-                    increment = ( roundingMode == float_round_down ) && zSig1;
-                }
-                else {
-                    increment = ( roundingMode == float_round_up ) && zSig1;
-                }
+            switch (roundingMode) {
+            case float_round_nearest_even:
+                increment = ((int64_t)zSig1 < 0);
+                break;
+            case float_round_to_zero:
+                increment = 0;
+                break;
+            case float_round_up:
+                increment = !zSign && zSig1;
+                break;
+            case float_round_down:
+                increment = zSign && zSig1;
+                break;
+            default:
+                abort();
             }
             if ( increment ) {
                 ++zSig0;
@@ -1029,19 +1050,21 @@ static float128
 
     roundingMode = STATUS(float_rounding_mode);
     roundNearestEven = ( roundingMode == float_round_nearest_even );
-    increment = ( (int64_t) zSig2 < 0 );
-    if ( ! roundNearestEven ) {
-        if ( roundingMode == float_round_to_zero ) {
-            increment = 0;
-        }
-        else {
-            if ( zSign ) {
-                increment = ( roundingMode == float_round_down ) && zSig2;
-            }
-            else {
-                increment = ( roundingMode == float_round_up ) && zSig2;
-            }
-        }
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = ((int64_t)zSig2 < 0);
+        break;
+    case float_round_to_zero:
+        increment = 0;
+        break;
+    case float_round_up:
+        increment = !zSign && zSig2;
+        break;
+    case float_round_down:
+        increment = zSign && zSig2;
+        break;
+    default:
+        abort();
     }
     if ( 0x7FFD <= (uint32_t) zExp ) {
         if (    ( 0x7FFD < zExp )
@@ -1089,16 +1112,21 @@ static float128
                 zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
             zExp = 0;
             if ( isTiny && zSig2 ) float_raise( float_flag_underflow STATUS_VAR);
-            if ( roundNearestEven ) {
-                increment = ( (int64_t) zSig2 < 0 );
-            }
-            else {
-                if ( zSign ) {
-                    increment = ( roundingMode == float_round_down ) && zSig2;
-                }
-                else {
-                    increment = ( roundingMode == float_round_up ) && zSig2;
-                }
+            switch (roundingMode) {
+            case float_round_nearest_even:
+                increment = ((int64_t)zSig2 < 0);
+                break;
+            case float_round_to_zero:
+                increment = 0;
+                break;
+            case float_round_up:
+                increment = !zSign && zSig2;
+                break;
+            case float_round_down:
+                increment = zSign && zSig2;
+                break;
+            default:
+                abort();
             }
         }
     }
@@ -1737,7 +1765,6 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
     flag aSign;
     int_fast16_t aExp;
     uint32_t lastBitMask, roundBitsMask;
-    int8 roundingMode;
     uint32_t z;
     a = float32_squash_input_denormal(a STATUS_VAR);
 
@@ -1769,15 +1796,27 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
     lastBitMask <<= 0x96 - aExp;
     roundBitsMask = lastBitMask - 1;
     z = float32_val(a);
-    roundingMode = STATUS(float_rounding_mode);
-    if ( roundingMode == float_round_nearest_even ) {
+    switch (STATUS(float_rounding_mode)) {
+    case float_round_nearest_even:
         z += lastBitMask>>1;
-        if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
-    }
-    else if ( roundingMode != float_round_to_zero ) {
-        if ( extractFloat32Sign( make_float32(z) ) ^ ( roundingMode == float_round_up ) ) {
+        if ((z & roundBitsMask) == 0) {
+            z &= ~lastBitMask;
+        }
+        break;
+    case float_round_to_zero:
+        break;
+    case float_round_up:
+        if (!extractFloat32Sign(make_float32(z))) {
+            z += roundBitsMask;
+        }
+        break;
+    case float_round_down:
+        if (extractFloat32Sign(make_float32(z))) {
             z += roundBitsMask;
         }
+        break;
+    default:
+        abort();
     }
     z &= ~ roundBitsMask;
     if ( z != float32_val(a) ) STATUS(float_exception_flags) |= float_flag_inexact;
@@ -3120,7 +3159,6 @@ static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp,
     int maxexp = ieee ? 29 : 30;
     uint32_t mask;
     uint32_t increment;
-    int8 roundingMode;
     bool rounding_bumps_exp;
     bool is_tiny = false;
 
@@ -3138,8 +3176,7 @@ static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp,
         mask = 0x00001fff;
     }
 
-    roundingMode = STATUS(float_rounding_mode);
-    switch (roundingMode) {
+    switch (STATUS(float_rounding_mode)) {
     case float_round_nearest_even:
         increment = (mask + 1) >> 1;
         if ((zSig & mask) == increment) {
@@ -3430,7 +3467,6 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
     flag aSign;
     int_fast16_t aExp;
     uint64_t lastBitMask, roundBitsMask;
-    int8 roundingMode;
     uint64_t z;
     a = float64_squash_input_denormal(a STATUS_VAR);
 
@@ -3463,15 +3499,27 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
     lastBitMask <<= 0x433 - aExp;
     roundBitsMask = lastBitMask - 1;
     z = float64_val(a);
-    roundingMode = STATUS(float_rounding_mode);
-    if ( roundingMode == float_round_nearest_even ) {
-        z += lastBitMask>>1;
-        if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
-    }
-    else if ( roundingMode != float_round_to_zero ) {
-        if ( extractFloat64Sign( make_float64(z) ) ^ ( roundingMode == float_round_up ) ) {
+    switch (STATUS(float_rounding_mode)) {
+    case float_round_nearest_even:
+        z += lastBitMask >> 1;
+        if ((z & roundBitsMask) == 0) {
+            z &= ~lastBitMask;
+        }
+        break;
+    case float_round_to_zero:
+        break;
+    case float_round_up:
+        if (!extractFloat64Sign(make_float64(z))) {
+            z += roundBitsMask;
+        }
+        break;
+    case float_round_down:
+        if (extractFloat64Sign(make_float64(z))) {
             z += roundBitsMask;
         }
+        break;
+    default:
+        abort();
     }
     z &= ~ roundBitsMask;
     if ( z != float64_val(a) )
@@ -4699,7 +4747,6 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
     flag aSign;
     int32 aExp;
     uint64_t lastBitMask, roundBitsMask;
-    int8 roundingMode;
     floatx80 z;
 
     aExp = extractFloatx80Exp( a );
@@ -4740,15 +4787,27 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM )
     lastBitMask <<= 0x403E - aExp;
     roundBitsMask = lastBitMask - 1;
     z = a;
-    roundingMode = STATUS(float_rounding_mode);
-    if ( roundingMode == float_round_nearest_even ) {
+    switch (STATUS(float_rounding_mode)) {
+    case float_round_nearest_even:
         z.low += lastBitMask>>1;
-        if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
-    }
-    else if ( roundingMode != float_round_to_zero ) {
-        if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+        if ((z.low & roundBitsMask) == 0) {
+            z.low &= ~lastBitMask;
+        }
+        break;
+    case float_round_to_zero:
+        break;
+    case float_round_up:
+        if (!extractFloatx80Sign(z)) {
+            z.low += roundBitsMask;
+        }
+        break;
+    case float_round_down:
+        if (extractFloatx80Sign(z)) {
             z.low += roundBitsMask;
         }
+        break;
+    default:
+        abort();
     }
     z.low &= ~ roundBitsMask;
     if ( z.low == 0 ) {
@@ -5774,7 +5833,6 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
     flag aSign;
     int32 aExp;
     uint64_t lastBitMask, roundBitsMask;
-    int8 roundingMode;
     float128 z;
 
     aExp = extractFloat128Exp( a );
@@ -5791,8 +5849,8 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
         lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
         roundBitsMask = lastBitMask - 1;
         z = a;
-        roundingMode = STATUS(float_rounding_mode);
-        if ( roundingMode == float_round_nearest_even ) {
+        switch (STATUS(float_rounding_mode)) {
+        case float_round_nearest_even:
             if ( lastBitMask ) {
                 add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
                 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
@@ -5803,12 +5861,21 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
                     if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1;
                 }
             }
-        }
-        else if ( roundingMode != float_round_to_zero ) {
-            if (   extractFloat128Sign( z )
-                 ^ ( roundingMode == float_round_up ) ) {
-                add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
+            break;
+        case float_round_to_zero:
+            break;
+        case float_round_up:
+            if (!extractFloat128Sign(z)) {
+                add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
+            }
+            break;
+        case float_round_down:
+            if (extractFloat128Sign(z)) {
+                add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);
             }
+            break;
+        default:
+            abort();
         }
         z.low &= ~ roundBitsMask;
     }
@@ -5842,19 +5909,29 @@ float128 float128_round_to_int( float128 a STATUS_PARAM )
         roundBitsMask = lastBitMask - 1;
         z.low = 0;
         z.high = a.high;
-        roundingMode = STATUS(float_rounding_mode);
-        if ( roundingMode == float_round_nearest_even ) {
+        switch (STATUS(float_rounding_mode)) {
+        case float_round_nearest_even:
             z.high += lastBitMask>>1;
             if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
                 z.high &= ~ lastBitMask;
             }
-        }
-        else if ( roundingMode != float_round_to_zero ) {
-            if (   extractFloat128Sign( z )
-                 ^ ( roundingMode == float_round_up ) ) {
+            break;
+        case float_round_to_zero:
+            break;
+        case float_round_up:
+            if (!extractFloat128Sign(z)) {
                 z.high |= ( a.low != 0 );
                 z.high += roundBitsMask;
             }
+            break;
+        case float_round_down:
+            if (extractFloat128Sign(z)) {
+                z.high |= (a.low != 0);
+                z.high += roundBitsMask;
+            }
+            break;
+        default:
+            abort();
         }
         z.high &= ~ roundBitsMask;
     }
commit 14c9a07eb9cae3d3bc1d39cc8815dd88337ce07a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:12 2014 +0000

    softfloat: Add float16 <=> float64 conversion functions
    
    Add the conversion functions float16_to_float64() and
    float64_to_float16(), which will be needed for the ARM
    A64 instruction set.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c63e011..d4ca7cf 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -3281,6 +3281,81 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     return roundAndPackFloat16(aSign, aExp, aSig, ieee STATUS_VAR);
 }
 
+float64 float16_to_float64(float16 a, flag ieee STATUS_PARAM)
+{
+    flag aSign;
+    int_fast16_t aExp;
+    uint32_t aSig;
+
+    aSign = extractFloat16Sign(a);
+    aExp = extractFloat16Exp(a);
+    aSig = extractFloat16Frac(a);
+
+    if (aExp == 0x1f && ieee) {
+        if (aSig) {
+            return commonNaNToFloat64(
+                float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+        }
+        return packFloat64(aSign, 0x7ff, 0);
+    }
+    if (aExp == 0) {
+        if (aSig == 0) {
+            return packFloat64(aSign, 0, 0);
+        }
+
+        normalizeFloat16Subnormal(aSig, &aExp, &aSig);
+        aExp--;
+    }
+    return packFloat64(aSign, aExp + 0x3f0, ((uint64_t)aSig) << 42);
+}
+
+float16 float64_to_float16(float64 a, flag ieee STATUS_PARAM)
+{
+    flag aSign;
+    int_fast16_t aExp;
+    uint64_t aSig;
+    uint32_t zSig;
+
+    a = float64_squash_input_denormal(a STATUS_VAR);
+
+    aSig = extractFloat64Frac(a);
+    aExp = extractFloat64Exp(a);
+    aSign = extractFloat64Sign(a);
+    if (aExp == 0x7FF) {
+        if (aSig) {
+            /* Input is a NaN */
+            if (!ieee) {
+                float_raise(float_flag_invalid STATUS_VAR);
+                return packFloat16(aSign, 0, 0);
+            }
+            return commonNaNToFloat16(
+                float64ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+        }
+        /* Infinity */
+        if (!ieee) {
+            float_raise(float_flag_invalid STATUS_VAR);
+            return packFloat16(aSign, 0x1f, 0x3ff);
+        }
+        return packFloat16(aSign, 0x1f, 0);
+    }
+    shift64RightJamming(aSig, 29, &aSig);
+    zSig = aSig;
+    if (aExp == 0 && zSig == 0) {
+        return packFloat16(aSign, 0, 0);
+    }
+    /* Decimal point between bits 22 and 23. Note that we add the 1 bit
+     * even if the input is denormal; however this is harmless because
+     * the largest possible single-precision denormal is still smaller
+     * than the smallest representable half-precision denormal, and so we
+     * will end up ignoring aSig and returning via the "always return zero"
+     * codepath.
+     */
+    zSig |= 0x00800000;
+    aExp -= 0x3F1;
+
+    return roundAndPackFloat16(aSign, aExp, zSig, ieee STATUS_VAR);
+}
+
 /*----------------------------------------------------------------------------
 | Returns the result of converting the double-precision floating-point value
 | `a' to the extended double-precision floating-point format.  The conversion
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index a634a4e..83d324a 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -298,6 +298,8 @@ INLINE float64 uint16_to_float64(uint16_t v STATUS_PARAM)
 *----------------------------------------------------------------------------*/
 float16 float32_to_float16( float32, flag STATUS_PARAM );
 float32 float16_to_float32( float16, flag STATUS_PARAM );
+float16 float64_to_float16(float64 a, flag ieee STATUS_PARAM);
+float64 float16_to_float64(float16 a, flag ieee STATUS_PARAM);
 
 /*----------------------------------------------------------------------------
 | Software half-precision operations.
commit c4a1c5e7e2fae28ef3fde2aadf7ec6fed0a5a967
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:11 2014 +0000

    softfloat: Factor out RoundAndPackFloat16 and NormalizeFloat16Subnormal
    
    In preparation for adding conversions between float16 and float64,
    factor out code currently done inline in the float16<=>float32
    conversion functions into functions RoundAndPackFloat16 and
    NormalizeFloat16Subnormal along the lines of the existing versions
    for the other float types.
    
    Note that we change the handling of zExp from the inline code
    to match the API of the other RoundAndPackFloat functions; however
    we leave the positioning of the binary point between bits 22 and 23
    rather than shifting it up to the high end of the word.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 4abcd36..c63e011 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -3086,6 +3086,127 @@ static float16 packFloat16(flag zSign, int_fast16_t zExp, uint16_t zSig)
         (((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig);
 }
 
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and significand `zSig', and returns the proper half-precision floating-
+| point value corresponding to the abstract input.  Ordinarily, the abstract
+| value is simply rounded and packed into the half-precision format, with
+| the inexact exception raised if the abstract input cannot be represented
+| exactly.  However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned.  If the abstract value is too small, the input value is rounded to
+| a subnormal number, and the underflow and inexact exceptions are raised if
+| the abstract input cannot be represented exactly as a subnormal half-
+| precision floating-point number.
+| The `ieee' flag indicates whether to use IEEE standard half precision, or
+| ARM-style "alternative representation", which omits the NaN and Inf
+| encodings in order to raise the maximum representable exponent by one.
+|     The input significand `zSig' has its binary point between bits 22
+| and 23, which is 13 bits to the left of the usual location.  This shifted
+| significand must be normalized or smaller.  If `zSig' is not normalized,
+| `zExp' must be 0; in that case, the result returned is a subnormal number,
+| and it must not require rounding.  In the usual case that `zSig' is
+| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+| Note the slightly odd position of the binary point in zSig compared with the
+| other roundAndPackFloat functions. This should probably be fixed if we
+| need to implement more float16 routines than just conversion.
+| The handling of underflow and overflow follows the IEC/IEEE Standard for
+| Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp,
+                                   uint32_t zSig, flag ieee STATUS_PARAM)
+{
+    int maxexp = ieee ? 29 : 30;
+    uint32_t mask;
+    uint32_t increment;
+    int8 roundingMode;
+    bool rounding_bumps_exp;
+    bool is_tiny = false;
+
+    /* Calculate the mask of bits of the mantissa which are not
+     * representable in half-precision and will be lost.
+     */
+    if (zExp < 1) {
+        /* Will be denormal in halfprec */
+        mask = 0x00ffffff;
+        if (zExp >= -11) {
+            mask >>= 11 + zExp;
+        }
+    } else {
+        /* Normal number in halfprec */
+        mask = 0x00001fff;
+    }
+
+    roundingMode = STATUS(float_rounding_mode);
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = (mask + 1) >> 1;
+        if ((zSig & mask) == increment) {
+            increment = zSig & (increment << 1);
+        }
+        break;
+    case float_round_up:
+        increment = zSign ? 0 : mask;
+        break;
+    case float_round_down:
+        increment = zSign ? mask : 0;
+        break;
+    default: /* round_to_zero */
+        increment = 0;
+        break;
+    }
+
+    rounding_bumps_exp = (zSig + increment >= 0x01000000);
+
+    if (zExp > maxexp || (zExp == maxexp && rounding_bumps_exp)) {
+        if (ieee) {
+            float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR);
+            return packFloat16(zSign, 0x1f, 0);
+        } else {
+            float_raise(float_flag_invalid STATUS_VAR);
+            return packFloat16(zSign, 0x1f, 0x3ff);
+        }
+    }
+
+    if (zExp < 0) {
+        /* Note that flush-to-zero does not affect half-precision results */
+        is_tiny =
+            (STATUS(float_detect_tininess) == float_tininess_before_rounding)
+            || (zExp < -1)
+            || (!rounding_bumps_exp);
+    }
+    if (zSig & mask) {
+        float_raise(float_flag_inexact STATUS_VAR);
+        if (is_tiny) {
+            float_raise(float_flag_underflow STATUS_VAR);
+        }
+    }
+
+    zSig += increment;
+    if (rounding_bumps_exp) {
+        zSig >>= 1;
+        zExp++;
+    }
+
+    if (zExp < -10) {
+        return packFloat16(zSign, 0, 0);
+    }
+    if (zExp < 0) {
+        zSig >>= -zExp;
+        zExp = 0;
+    }
+    return packFloat16(zSign, zExp, zSig >> 13);
+}
+
+static void normalizeFloat16Subnormal(uint32_t aSig, int_fast16_t *zExpPtr,
+                                      uint32_t *zSigPtr)
+{
+    int8_t shiftCount = countLeadingZeros32(aSig) - 21;
+    *zSigPtr = aSig << shiftCount;
+    *zExpPtr = 1 - shiftCount;
+}
+
 /* Half precision floats come in two formats: standard IEEE and "ARM" format.
    The latter gains extra exponent range by omitting the NaN/Inf encodings.  */
 
@@ -3106,15 +3227,12 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
         return packFloat32(aSign, 0xff, 0);
     }
     if (aExp == 0) {
-        int8 shiftCount;
-
         if (aSig == 0) {
             return packFloat32(aSign, 0, 0);
         }
 
-        shiftCount = countLeadingZeros32( aSig ) - 21;
-        aSig = aSig << shiftCount;
-        aExp = -shiftCount;
+        normalizeFloat16Subnormal(aSig, &aExp, &aSig);
+        aExp--;
     }
     return packFloat32( aSign, aExp + 0x70, aSig << 13);
 }
@@ -3124,12 +3242,6 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     flag aSign;
     int_fast16_t aExp;
     uint32_t aSig;
-    uint32_t mask;
-    uint32_t increment;
-    int8 roundingMode;
-    int maxexp = ieee ? 15 : 16;
-    bool rounding_bumps_exp;
-    bool is_tiny = false;
 
     a = float32_squash_input_denormal(a STATUS_VAR);
 
@@ -3164,80 +3276,9 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
      * codepath.
      */
     aSig |= 0x00800000;
-    aExp -= 0x7f;
-    /* Calculate the mask of bits of the mantissa which are not
-     * representable in half-precision and will be lost.
-     */
-    if (aExp < -14) {
-        /* Will be denormal in halfprec */
-        mask = 0x00ffffff;
-        if (aExp >= -24) {
-            mask >>= 25 + aExp;
-        }
-    } else {
-        /* Normal number in halfprec */
-        mask = 0x00001fff;
-    }
+    aExp -= 0x71;
 
-    roundingMode = STATUS(float_rounding_mode);
-    switch (roundingMode) {
-    case float_round_nearest_even:
-        increment = (mask + 1) >> 1;
-        if ((aSig & mask) == increment) {
-            increment = aSig & (increment << 1);
-        }
-        break;
-    case float_round_up:
-        increment = aSign ? 0 : mask;
-        break;
-    case float_round_down:
-        increment = aSign ? mask : 0;
-        break;
-    default: /* round_to_zero */
-        increment = 0;
-        break;
-    }
-
-    rounding_bumps_exp = (aSig + increment >= 0x01000000);
-
-    if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) {
-        if (ieee) {
-            float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR);
-            return packFloat16(aSign, 0x1f, 0);
-        } else {
-            float_raise(float_flag_invalid STATUS_VAR);
-            return packFloat16(aSign, 0x1f, 0x3ff);
-        }
-    }
-
-    if (aExp < -14) {
-        /* Note that flush-to-zero does not affect half-precision results */
-        is_tiny =
-            (STATUS(float_detect_tininess) == float_tininess_before_rounding)
-            || (aExp < -15)
-            || (!rounding_bumps_exp);
-    }
-    if (aSig & mask) {
-        float_raise(float_flag_inexact STATUS_VAR);
-        if (is_tiny) {
-            float_raise(float_flag_underflow STATUS_VAR);
-        }
-    }
-
-    aSig += increment;
-    if (rounding_bumps_exp) {
-        aSig >>= 1;
-        aExp++;
-    }
-
-    if (aExp < -24) {
-        return packFloat16(aSign, 0, 0);
-    }
-    if (aExp < -14) {
-        aSig >>= -14 - aExp;
-        aExp = -14;
-    }
-    return packFloat16(aSign, aExp + 14, aSig >> 13);
+    return roundAndPackFloat16(aSign, aExp, aSig, ieee STATUS_VAR);
 }
 
 /*----------------------------------------------------------------------------
commit 879d096b37b1233fec334bc2c2f569ac3b8fec9a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:11 2014 +0000

    softfloat: Provide complete set of accessors for fp state
    
    Tidy up the get/set accessors for the fp state to add missing ones
    and make them all inline in softfloat.h rather than some inline and
    some not.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 3232ce2..4abcd36 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -59,21 +59,6 @@ these four paragraphs for those parts of this code that are retained.
 *----------------------------------------------------------------------------*/
 #include "softfloat-specialize.h"
 
-void set_float_rounding_mode(int val STATUS_PARAM)
-{
-    STATUS(float_rounding_mode) = val;
-}
-
-void set_float_exception_flags(int val STATUS_PARAM)
-{
-    STATUS(float_exception_flags) = val;
-}
-
-void set_floatx80_rounding_precision(int val STATUS_PARAM)
-{
-    STATUS(floatx80_rounding_precision) = val;
-}
-
 /*----------------------------------------------------------------------------
 | Returns the fraction bits of the half-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index eb81c3b..a634a4e 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -180,12 +180,22 @@ typedef struct float_status {
     flag default_nan_mode;
 } float_status;
 
-void set_float_rounding_mode(int val STATUS_PARAM);
-void set_float_exception_flags(int val STATUS_PARAM);
 INLINE void set_float_detect_tininess(int val STATUS_PARAM)
 {
     STATUS(float_detect_tininess) = val;
 }
+INLINE void set_float_rounding_mode(int val STATUS_PARAM)
+{
+    STATUS(float_rounding_mode) = val;
+}
+INLINE void set_float_exception_flags(int val STATUS_PARAM)
+{
+    STATUS(float_exception_flags) = val;
+}
+INLINE void set_floatx80_rounding_precision(int val STATUS_PARAM)
+{
+    STATUS(floatx80_rounding_precision) = val;
+}
 INLINE void set_flush_to_zero(flag val STATUS_PARAM)
 {
     STATUS(flush_to_zero) = val;
@@ -198,11 +208,34 @@ INLINE void set_default_nan_mode(flag val STATUS_PARAM)
 {
     STATUS(default_nan_mode) = val;
 }
+INLINE int get_float_detect_tininess(float_status *status)
+{
+    return STATUS(float_detect_tininess);
+}
+INLINE int get_float_rounding_mode(float_status *status)
+{
+    return STATUS(float_rounding_mode);
+}
 INLINE int get_float_exception_flags(float_status *status)
 {
     return STATUS(float_exception_flags);
 }
-void set_floatx80_rounding_precision(int val STATUS_PARAM);
+INLINE int get_floatx80_rounding_precision(float_status *status)
+{
+    return STATUS(floatx80_rounding_precision);
+}
+INLINE flag get_flush_to_zero(float_status *status)
+{
+    return STATUS(flush_to_zero);
+}
+INLINE flag get_flush_inputs_to_zero(float_status *status)
+{
+    return STATUS(flush_inputs_to_zero);
+}
+INLINE flag get_default_nan_mode(float_status *status)
+{
+    return STATUS(default_nan_mode);
+}
 
 /*----------------------------------------------------------------------------
 | Routine to raise any or all of the software IEC/IEEE floating-point
commit fd728f2f949273563f799640b863b4b94dc4c6da
Author: Tom Musta <tommusta at gmail.com>
Date:   Tue Jan 7 17:17:51 2014 +0000

    softfloat: Fix float64_to_uint32_round_to_zero
    
    The float64_to_uint32_round_to_zero routine is incorrect.
    
    For example, the following test pattern:
    
        425F81378DC0CD1F / 0x1.f81378dc0cd1fp+38
    
    will erroneously set the inexact flag.
    
    This patch re-implements the routine to use the float64_to_uint64_round_to_zero
    routine.  If saturation occurs we ignore any flags set by the
    conversion function and raise only Invalid.
    
    This contribution can be licensed under either the softfloat-2a or -2b
    license.
    
    Signed-off-by: Tom Musta <tommusta at gmail.com>
    Message-id: 1387397961-4894-6-git-send-email-tommusta at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e68a87b..3232ce2 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6667,19 +6667,18 @@ uint32 float64_to_uint32( float64 a STATUS_PARAM )
 
 uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
 {
-    int64_t v;
+    uint64_t v;
     uint32 res;
+    int old_exc_flags = get_float_exception_flags(status);
 
-    v = float64_to_int64_round_to_zero(a STATUS_VAR);
-    if (v < 0) {
-        res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
-    } else if (v > 0xffffffff) {
+    v = float64_to_uint64_round_to_zero(a STATUS_VAR);
+    if (v > 0xffffffff) {
         res = 0xffffffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
commit 5e7f654fa152de246f2254707bacac31ba50c660
Author: Tom Musta <tommusta at gmail.com>
Date:   Tue Jan 7 17:17:51 2014 +0000

    softfloat: Fix float64_to_uint32
    
    The float64_to_uint32 has several flaws:
    
     - for numbers between 2**32 and 2**64, the inexact exception flag
       may get incorrectly set.  In this case, only the invalid flag
       should be set.
    
           test pattern: 425F81378DC0CD1F / 0x1.f81378dc0cd1fp+38
    
     - for numbers between 2**63 and 2**64, incorrect results may
       be produced:
    
           test pattern: 43EAAF73F1F0B8BD / 0x1.aaf73f1f0b8bdp+63
    
    This patch re-implements float64_to_uint32 to re-use the
    float64_to_uint64 routine (instead of float64_to_int64).  For the
    saturation case, we ignore any flags which the conversion routine
    has set and raise only the invalid flag.
    
    This contribution can be licensed under either the softfloat-2a or -2b
    license.
    
    Signed-off-by: Tom Musta <tommusta at gmail.com>
    Message-id: 1387397961-4894-5-git-send-email-tommusta at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f782c24..e68a87b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6650,19 +6650,18 @@ uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
 
 uint32 float64_to_uint32( float64 a STATUS_PARAM )
 {
-    int64_t v;
+    uint64_t v;
     uint32 res;
+    int old_exc_flags = get_float_exception_flags(status);
 
-    v = float64_to_int64(a STATUS_VAR);
-    if (v < 0) {
-        res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
-    } else if (v > 0xffffffff) {
+    v = float64_to_uint64(a STATUS_VAR);
+    if (v > 0xffffffff) {
         res = 0xffffffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
commit 0a87a3107dad97abff5b06558b0cce6832229086
Author: Tom Musta <tommusta at gmail.com>
Date:   Tue Jan 7 17:17:50 2014 +0000

    softfloat: Fix float64_to_uint64_round_to_zero
    
    The float64_to_uint64_round_to_zero routine is incorrect.
    
    For example, the following test pattern:
    
        46697351FF4AEC29 / 0x1.97351ff4aec29p+103
    
    currently produces 8000000000000000 instead of FFFFFFFFFFFFFFFF.
    
    This patch re-implements the routine to temporarily force the
    rounding mode and use the float64_to_uint64 routine.
    
    This contribution can be licensed under either the softfloat-2a or -2b
    license.
    
    Signed-off-by: Tom Musta <tommusta at gmail.com>
    Message-id: 1387397961-4894-4-git-send-email-tommusta at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c2c1a56..f782c24 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6792,13 +6792,11 @@ uint64_t float64_to_uint64(float64 a STATUS_PARAM)
 
 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
 {
-    int64_t v;
-
-    v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
-    v += float64_val(a);
-    v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR);
-
-    return v - INT64_MIN;
+    signed char current_rounding_mode = STATUS(float_rounding_mode);
+    set_float_rounding_mode(float_round_to_zero STATUS_VAR);
+    int64_t v = float64_to_uint64(a STATUS_VAR);
+    set_float_rounding_mode(current_rounding_mode STATUS_VAR);
+    return v;
 }
 
 #define COMPARE(s, nan_exp)                                                  \
commit 2f18bbf9844ad110e0e69ad22708f37cab1557f6
Author: Tom Musta <tommusta at gmail.com>
Date:   Tue Jan 7 17:17:50 2014 +0000

    softfloat: Add float32_to_uint64()
    
    This patch adds the float32_to_uint64() routine, which converts a
    32-bit floating point number to an unsigned 64 bit number.
    
    This contribution can be licensed under either the softfloat-2a or -2b
    license.
    
    Signed-off-by: Tom Musta <tommusta at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    [PMM: removed harmless but silly int64_t casts]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index d2e9095..c2c1a56 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1559,6 +1559,52 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
 
 /*----------------------------------------------------------------------------
 | Returns the result of converting the single-precision floating-point value
+| `a' to the 64-bit unsigned integer format.  The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic---which means in particular that the conversion is rounded
+| according to the current rounding mode.  If `a' is a NaN, the largest
+| unsigned integer is returned.  Otherwise, if the conversion overflows, the
+| largest unsigned integer is returned.  If the 'a' is negative, the result
+| is rounded and zero is returned; values that do not round to zero will
+| raise the inexact exception flag.
+*----------------------------------------------------------------------------*/
+
+uint64 float32_to_uint64(float32 a STATUS_PARAM)
+{
+    flag aSign;
+    int_fast16_t aExp, shiftCount;
+    uint32_t aSig;
+    uint64_t aSig64, aSigExtra;
+    a = float32_squash_input_denormal(a STATUS_VAR);
+
+    aSig = extractFloat32Frac(a);
+    aExp = extractFloat32Exp(a);
+    aSign = extractFloat32Sign(a);
+    if ((aSign) && (aExp > 126)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+        if (float32_is_any_nan(a)) {
+            return LIT64(0xFFFFFFFFFFFFFFFF);
+        } else {
+            return 0;
+        }
+    }
+    shiftCount = 0xBE - aExp;
+    if (aExp) {
+        aSig |= 0x00800000;
+    }
+    if (shiftCount < 0) {
+        float_raise(float_flag_invalid STATUS_VAR);
+        return LIT64(0xFFFFFFFFFFFFFFFF);
+    }
+
+    aSig64 = aSig;
+    aSig64 <<= 40;
+    shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra);
+    return roundAndPackUint64(aSign, aSig64, aSigExtra STATUS_VAR);
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the single-precision floating-point value
 | `a' to the 64-bit two's complement integer format.  The conversion is
 | performed according to the IEC/IEEE Standard for Binary Floating-Point
 | Arithmetic, except that the conversion is always rounded toward zero.  If
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 78b1656..eb81c3b 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -295,6 +295,7 @@ int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM );
 uint32 float32_to_uint32( float32 STATUS_PARAM );
 uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
 int64 float32_to_int64( float32 STATUS_PARAM );
+uint64 float32_to_uint64(float32 STATUS_PARAM);
 int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
 float64 float32_to_float64( float32 STATUS_PARAM );
 floatx80 float32_to_floatx80( float32 STATUS_PARAM );
commit 3c85c37f254bdfaea4e105b5014a287b5cf9514b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:17:50 2014 +0000

    softfloat: Fix factor 2 error for scalbn on denormal inputs
    
    If the input to float*_scalbn() is denormal then it represents
    a number 0.[mantissabits] * 2^(1-exponentbias) (and the actual
    exponent field is all zeroes). This means that when we convert
    it to our unpacked encoding the unpacked exponent must be one
    greater than for a normal number, which represents
    1.[mantissabits] * 2^(e-exponentbias) for an exponent field e.
    
    This meant we were giving answers too small by a factor of 2 for
    all denormal inputs.
    
    Note that the float-to-int routines also have this behaviour
    of not adjusting the exponent for denormals; however there it is
    harmless because denormals will all convert to integer zero anyway.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6312e0c..d2e9095 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6991,10 +6991,13 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
         }
         return a;
     }
-    if ( aExp != 0 )
+    if (aExp != 0) {
         aSig |= 0x00800000;
-    else if ( aSig == 0 )
+    } else if (aSig == 0) {
         return a;
+    } else {
+        aExp++;
+    }
 
     if (n > 0x200) {
         n = 0x200;
@@ -7024,10 +7027,13 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
         }
         return a;
     }
-    if ( aExp != 0 )
+    if (aExp != 0) {
         aSig |= LIT64( 0x0010000000000000 );
-    else if ( aSig == 0 )
+    } else if (aSig == 0) {
         return a;
+    } else {
+        aExp++;
+    }
 
     if (n > 0x1000) {
         n = 0x1000;
@@ -7057,8 +7063,12 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
         return a;
     }
 
-    if (aExp == 0 && aSig == 0)
-        return a;
+    if (aExp == 0) {
+        if (aSig == 0) {
+            return a;
+        }
+        aExp++;
+    }
 
     if (n > 0x10000) {
         n = 0x10000;
@@ -7087,10 +7097,13 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
         }
         return a;
     }
-    if ( aExp != 0 )
+    if (aExp != 0) {
         aSig0 |= LIT64( 0x0001000000000000 );
-    else if ( aSig0 == 0 && aSig1 == 0 )
+    } else if (aSig0 == 0 && aSig1 == 0) {
         return a;
+    } else {
+        aExp++;
+    }
 
     if (n > 0x10000) {
         n = 0x10000;
commit 34e1c27bc3094ffe484d9855e07ad104bddf579f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:17:49 2014 +0000

    softfloat: Only raise Invalid when conversions to int are out of range
    
    We implement a number of float-to-integer conversions using conversion
    to an integer type with a wider range and then a check against the
    narrower range we are actually converting to. If we find the result to
    be out of range we correctly raise the Invalid exception, but we must
    also suppress other exceptions which might have been raised by the
    conversion function we called.
    
    This won't throw away exceptions we should have preserved, because for
    the 'core' exception flags the IEEE spec mandates that the only valid
    combinations of exception that can be raised by a single operation are
    Inexact + Overflow and Inexact + Underflow. For the non-IEEE softfloat
    flag for input denormals, we can guarantee that that flag won't have
    been set for out of range float-to-int conversions because a squashed
    denormal by definition goes to plus or minus zero, which is always in
    range after conversion to integer zero.
    
    This bug has been fixed for some of the float-to-int conversion routines
    by previous patches; fix it for the remaining functions as well, so
    that they all restore the pre-conversion status flags prior to raising
    Invalid.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 2364513..6312e0c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6509,17 +6509,18 @@ uint32 float32_to_uint32( float32 a STATUS_PARAM )
 {
     int64_t v;
     uint32 res;
+    int old_exc_flags = get_float_exception_flags(status);
 
     v = float32_to_int64(a STATUS_VAR);
     if (v < 0) {
         res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else if (v > 0xffffffff) {
         res = 0xffffffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
@@ -6527,17 +6528,18 @@ uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
 {
     int64_t v;
     uint32 res;
+    int old_exc_flags = get_float_exception_flags(status);
 
     v = float32_to_int64_round_to_zero(a STATUS_VAR);
     if (v < 0) {
         res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else if (v > 0xffffffff) {
         res = 0xffffffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
@@ -6585,17 +6587,18 @@ uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
 {
     int64_t v;
     uint_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
 
     v = float32_to_int64_round_to_zero(a STATUS_VAR);
     if (v < 0) {
         res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else if (v > 0xffff) {
         res = 0xffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
@@ -6679,17 +6682,18 @@ uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
 {
     int64_t v;
     uint_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
 
     v = float64_to_int64_round_to_zero(a STATUS_VAR);
     if (v < 0) {
         res = 0;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else if (v > 0xffff) {
         res = 0xffff;
-        float_raise( float_flag_invalid STATUS_VAR);
     } else {
-        res = v;
+        return v;
     }
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
     return res;
 }
 
commit fb3ea83aa53cead46465c74ddd1872babe9f4a3e
Author: Tom Musta <tommusta at gmail.com>
Date:   Tue Jan 7 17:17:49 2014 +0000

    softfloat: Fix float64_to_uint64
    
    The comment preceding the float64_to_uint64 routine suggests that
    the implementation is broken.  And this is, indeed, the case.
    
    This patch properly implements the conversion of a 64-bit floating
    point number to an unsigned, 64 bit integer.
    
    This contribution can be licensed under either the softfloat-2a or -2b
    license.
    
    Signed-off-by: Tom Musta <tommusta at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 3170b88..2364513 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -204,6 +204,56 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU
 }
 
 /*----------------------------------------------------------------------------
+| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
+| `absZ1', with binary point between bits 63 and 64 (between the input words),
+| and returns the properly rounded 64-bit unsigned integer corresponding to the
+| input.  Ordinarily, the fixed-point input is simply rounded to an integer,
+| with the inexact exception raised if the input cannot be represented exactly
+| as an integer.  However, if the fixed-point input is too large, the invalid
+| exception is raised and the largest unsigned integer is returned.
+*----------------------------------------------------------------------------*/
+
+static int64 roundAndPackUint64(flag zSign, uint64_t absZ0,
+                                uint64_t absZ1 STATUS_PARAM)
+{
+    int8 roundingMode;
+    flag roundNearestEven, increment;
+
+    roundingMode = STATUS(float_rounding_mode);
+    roundNearestEven = (roundingMode == float_round_nearest_even);
+    increment = ((int64_t)absZ1 < 0);
+    if (!roundNearestEven) {
+        if (roundingMode == float_round_to_zero) {
+            increment = 0;
+        } else if (absZ1) {
+            if (zSign) {
+                increment = (roundingMode == float_round_down) && absZ1;
+            } else {
+                increment = (roundingMode == float_round_up) && absZ1;
+            }
+        }
+    }
+    if (increment) {
+        ++absZ0;
+        if (absZ0 == 0) {
+            float_raise(float_flag_invalid STATUS_VAR);
+            return LIT64(0xFFFFFFFFFFFFFFFF);
+        }
+        absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven);
+    }
+
+    if (zSign && absZ0) {
+        float_raise(float_flag_invalid STATUS_VAR);
+        return 0;
+    }
+
+    if (absZ1) {
+        STATUS(float_exception_flags) |= float_flag_inexact;
+    }
+    return absZ0;
+}
+
+/*----------------------------------------------------------------------------
 | Returns the fraction bits of the single-precision floating-point value `a'.
 *----------------------------------------------------------------------------*/
 
@@ -6643,16 +6693,51 @@ uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
     return res;
 }
 
-/* FIXME: This looks broken.  */
-uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
-{
-    int64_t v;
+/*----------------------------------------------------------------------------
+| Returns the result of converting the double-precision floating-point value
+| `a' to the 64-bit unsigned integer format.  The conversion is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic---which means in particular that the conversion is rounded
+| according to the current rounding mode.  If `a' is a NaN, the largest
+| positive integer is returned.  If the conversion overflows, the
+| largest unsigned integer is returned.  If 'a' is negative, the value is
+| rounded and zero is returned; negative values that do not round to zero
+| will raise the inexact exception.
+*----------------------------------------------------------------------------*/
 
-    v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
-    v += float64_val(a);
-    v = float64_to_int64(make_float64(v) STATUS_VAR);
+uint64_t float64_to_uint64(float64 a STATUS_PARAM)
+{
+    flag aSign;
+    int_fast16_t aExp, shiftCount;
+    uint64_t aSig, aSigExtra;
+    a = float64_squash_input_denormal(a STATUS_VAR);
 
-    return v - INT64_MIN;
+    aSig = extractFloat64Frac(a);
+    aExp = extractFloat64Exp(a);
+    aSign = extractFloat64Sign(a);
+    if (aSign && (aExp > 1022)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+        if (float64_is_any_nan(a)) {
+            return LIT64(0xFFFFFFFFFFFFFFFF);
+        } else {
+            return 0;
+        }
+    }
+    if (aExp) {
+        aSig |= LIT64(0x0010000000000000);
+    }
+    shiftCount = 0x433 - aExp;
+    if (shiftCount <= 0) {
+        if (0x43E < aExp) {
+            float_raise(float_flag_invalid STATUS_VAR);
+            return LIT64(0xFFFFFFFFFFFFFFFF);
+        }
+        aSigExtra = 0;
+        aSig <<= -shiftCount;
+    } else {
+        shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra);
+    }
+    return roundAndPackUint64(aSign, aSig, aSigExtra STATUS_VAR);
 }
 
 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
commit c4850f9e1b9cef2ac35cd6e6f3d8d2147787740c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:17:49 2014 +0000

    softfloat: Make the int-to-float functions take exact-width types
    
    Currently the int-to-float functions take types which are specified
    as "at least X bits wide", rather than "exactly X bits wide". This is
    confusing and unhelpful since it means that the callers have to include
    an explicit cast to [u]intXX_t to ensure the correct behaviour. Fix
    them all to take the exactly-X-bits-wide types instead.
    
    Note that this doesn't change behaviour at all since at the moment
    we happen to define the 'int32' and 'uint32' types as exactly 32 bits
    wide, and the 'int64' and 'uint64' types as exactly 64 bits wide.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index dbaa32c..3170b88 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1121,7 +1121,7 @@ static float128
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float32 int32_to_float32( int32 a STATUS_PARAM )
+float32 int32_to_float32(int32_t a STATUS_PARAM)
 {
     flag zSign;
 
@@ -1138,7 +1138,7 @@ float32 int32_to_float32( int32 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float64 int32_to_float64( int32 a STATUS_PARAM )
+float64 int32_to_float64(int32_t a STATUS_PARAM)
 {
     flag zSign;
     uint32 absA;
@@ -1161,7 +1161,7 @@ float64 int32_to_float64( int32 a STATUS_PARAM )
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
+floatx80 int32_to_floatx80(int32_t a STATUS_PARAM)
 {
     flag zSign;
     uint32 absA;
@@ -1183,7 +1183,7 @@ floatx80 int32_to_floatx80( int32 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float128 int32_to_float128( int32 a STATUS_PARAM )
+float128 int32_to_float128(int32_t a STATUS_PARAM)
 {
     flag zSign;
     uint32 absA;
@@ -1205,7 +1205,7 @@ float128 int32_to_float128( int32 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float32 int64_to_float32( int64 a STATUS_PARAM )
+float32 int64_to_float32(int64_t a STATUS_PARAM)
 {
     flag zSign;
     uint64 absA;
@@ -1231,7 +1231,7 @@ float32 int64_to_float32( int64 a STATUS_PARAM )
 
 }
 
-float32 uint64_to_float32( uint64 a STATUS_PARAM )
+float32 uint64_to_float32(uint64_t a STATUS_PARAM)
 {
     int8 shiftCount;
 
@@ -1258,7 +1258,7 @@ float32 uint64_to_float32( uint64 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float64 int64_to_float64( int64 a STATUS_PARAM )
+float64 int64_to_float64(int64_t a STATUS_PARAM)
 {
     flag zSign;
 
@@ -1271,7 +1271,7 @@ float64 int64_to_float64( int64 a STATUS_PARAM )
 
 }
 
-float64 uint64_to_float64(uint64 a STATUS_PARAM)
+float64 uint64_to_float64(uint64_t a STATUS_PARAM)
 {
     int exp =  0x43C;
 
@@ -1292,7 +1292,7 @@ float64 uint64_to_float64(uint64 a STATUS_PARAM)
 | Arithmetic.
 *----------------------------------------------------------------------------*/
 
-floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
+floatx80 int64_to_floatx80(int64_t a STATUS_PARAM)
 {
     flag zSign;
     uint64 absA;
@@ -1312,7 +1312,7 @@ floatx80 int64_to_floatx80( int64 a STATUS_PARAM )
 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
 *----------------------------------------------------------------------------*/
 
-float128 int64_to_float128( int64 a STATUS_PARAM )
+float128 int64_to_float128(int64_t a STATUS_PARAM)
 {
     flag zSign;
     uint64 absA;
@@ -1339,7 +1339,7 @@ float128 int64_to_float128( int64 a STATUS_PARAM )
 
 }
 
-float128 uint64_to_float128(uint64 a STATUS_PARAM)
+float128 uint64_to_float128(uint64_t a STATUS_PARAM)
 {
     if (a == 0) {
         return float128_zero;
@@ -6445,12 +6445,12 @@ int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM )
 }
 
 /* misc functions */
-float32 uint32_to_float32( uint32 a STATUS_PARAM )
+float32 uint32_to_float32(uint32_t a STATUS_PARAM)
 {
     return int64_to_float32(a STATUS_VAR);
 }
 
-float64 uint32_to_float64( uint32 a STATUS_PARAM )
+float64 uint32_to_float64(uint32_t a STATUS_PARAM)
 {
     return int64_to_float64(a STATUS_VAR);
 }
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 926d849..78b1656 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -225,19 +225,19 @@ enum {
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE integer-to-floating-point conversion routines.
 *----------------------------------------------------------------------------*/
-float32 int32_to_float32( int32 STATUS_PARAM );
-float64 int32_to_float64( int32 STATUS_PARAM );
-float32 uint32_to_float32( uint32 STATUS_PARAM );
-float64 uint32_to_float64( uint32 STATUS_PARAM );
-floatx80 int32_to_floatx80( int32 STATUS_PARAM );
-float128 int32_to_float128( int32 STATUS_PARAM );
-float32 int64_to_float32( int64 STATUS_PARAM );
-float32 uint64_to_float32( uint64 STATUS_PARAM );
-float64 int64_to_float64( int64 STATUS_PARAM );
-float64 uint64_to_float64( uint64 STATUS_PARAM );
-floatx80 int64_to_floatx80( int64 STATUS_PARAM );
-float128 int64_to_float128( int64 STATUS_PARAM );
-float128 uint64_to_float128( uint64 STATUS_PARAM );
+float32 int32_to_float32(int32_t STATUS_PARAM);
+float64 int32_to_float64(int32_t STATUS_PARAM);
+float32 uint32_to_float32(uint32_t STATUS_PARAM);
+float64 uint32_to_float64(uint32_t STATUS_PARAM);
+floatx80 int32_to_floatx80(int32_t STATUS_PARAM);
+float128 int32_to_float128(int32_t STATUS_PARAM);
+float32 int64_to_float32(int64_t STATUS_PARAM);
+float32 uint64_to_float32(uint64_t STATUS_PARAM);
+float64 int64_to_float64(int64_t STATUS_PARAM);
+float64 uint64_to_float64(uint64_t STATUS_PARAM);
+floatx80 int64_to_floatx80(int64_t STATUS_PARAM);
+float128 int64_to_float128(int64_t STATUS_PARAM);
+float128 uint64_to_float128(uint64_t STATUS_PARAM);
 
 /* We provide the int16 versions for symmetry of API with float-to-int */
 INLINE float32 int16_to_float32(int16_t v STATUS_PARAM)
commit 8afbdabac2a1bdc137691c46965ef8c490cb5e44
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:17:49 2014 +0000

    softfloat: Add 16 bit integer to float conversions
    
    Add the float to 16 bit integer conversion routines. These can be
    trivially implemented in terms of the int32_to_float* routines, but
    providing them makes our API more symmetrical and can simplify callers.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index a9b8cd9..926d849 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -239,6 +239,27 @@ floatx80 int64_to_floatx80( int64 STATUS_PARAM );
 float128 int64_to_float128( int64 STATUS_PARAM );
 float128 uint64_to_float128( uint64 STATUS_PARAM );
 
+/* We provide the int16 versions for symmetry of API with float-to-int */
+INLINE float32 int16_to_float32(int16_t v STATUS_PARAM)
+{
+    return int32_to_float32(v STATUS_VAR);
+}
+
+INLINE float32 uint16_to_float32(uint16_t v STATUS_PARAM)
+{
+    return uint32_to_float32(v STATUS_VAR);
+}
+
+INLINE float64 int16_to_float64(int16_t v STATUS_PARAM)
+{
+    return int32_to_float64(v STATUS_VAR);
+}
+
+INLINE float64 uint16_to_float64(uint16_t v STATUS_PARAM)
+{
+    return uint32_to_float64(v STATUS_VAR);
+}
+
 /*----------------------------------------------------------------------------
 | Software half-precision conversion routines.
 *----------------------------------------------------------------------------*/
commit f581bf5474d2319ca37484eb63208017ac96ce0a
Author: Will Newton <will.newton at linaro.org>
Date:   Tue Jan 7 17:17:48 2014 +0000

    softfloat: Add float to 16bit integer conversions.
    
    ARMv8 requires support for converting 32 and 64bit floating point
    values to signed and unsigned 16bit integers.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM: updated not to incorrectly set Inexact for Invalid inputs]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6a6b656..dbaa32c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6491,6 +6491,46 @@ uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
     return res;
 }
 
+int_fast16_t float32_to_int16(float32 a STATUS_PARAM)
+{
+    int32_t v;
+    int_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
+
+    v = float32_to_int32(a STATUS_VAR);
+    if (v < -0x8000) {
+        res = -0x8000;
+    } else if (v > 0x7fff) {
+        res = 0x7fff;
+    } else {
+        return v;
+    }
+
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
+    return res;
+}
+
+uint_fast16_t float32_to_uint16(float32 a STATUS_PARAM)
+{
+    int32_t v;
+    uint_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
+
+    v = float32_to_int32(a STATUS_VAR);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffff) {
+        res = 0xffff;
+    } else {
+        return v;
+    }
+
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
+    return res;
+}
+
 uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
 {
     int64_t v;
@@ -6545,6 +6585,46 @@ uint32 float64_to_uint32_round_to_zero( float64 a STATUS_PARAM )
     return res;
 }
 
+int_fast16_t float64_to_int16(float64 a STATUS_PARAM)
+{
+    int64_t v;
+    int_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
+
+    v = float64_to_int32(a STATUS_VAR);
+    if (v < -0x8000) {
+        res = -0x8000;
+    } else if (v > 0x7fff) {
+        res = 0x7fff;
+    } else {
+        return v;
+    }
+
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
+    return res;
+}
+
+uint_fast16_t float64_to_uint16(float64 a STATUS_PARAM)
+{
+    int64_t v;
+    uint_fast16_t res;
+    int old_exc_flags = get_float_exception_flags(status);
+
+    v = float64_to_int32(a STATUS_VAR);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffff) {
+        res = 0xffff;
+    } else {
+        return v;
+    }
+
+    set_float_exception_flags(old_exc_flags, status);
+    float_raise(float_flag_invalid STATUS_VAR);
+    return res;
+}
+
 uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
 {
     int64_t v;
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 2365274..a9b8cd9 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -265,6 +265,8 @@ extern const float16 float16_default_nan;
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
 *----------------------------------------------------------------------------*/
+int_fast16_t float32_to_int16(float32 STATUS_PARAM);
+uint_fast16_t float32_to_uint16(float32 STATUS_PARAM);
 int_fast16_t float32_to_int16_round_to_zero(float32 STATUS_PARAM);
 uint_fast16_t float32_to_uint16_round_to_zero(float32 STATUS_PARAM);
 int32 float32_to_int32( float32 STATUS_PARAM );
@@ -371,6 +373,8 @@ extern const float32 float32_default_nan;
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
+int_fast16_t float64_to_int16(float64 STATUS_PARAM);
+uint_fast16_t float64_to_uint16(float64 STATUS_PARAM);
 int_fast16_t float64_to_int16_round_to_zero(float64 STATUS_PARAM);
 uint_fast16_t float64_to_uint16_round_to_zero(float64 STATUS_PARAM);
 int32 float64_to_int32( float64 STATUS_PARAM );
commit 38970efafdfa8a992c177563c4f0d77062b88fd9
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jan 6 11:47:21 2014 +0000

    softfloat: Fix exception flag handling for float32_to_float16()
    
    Our float32 to float16 conversion routine was generating the correct
    numerical answers, but not always setting the right set of exception
    flags. Fix this, mostly by rearranging the code to more closely
    resemble RoundAndPackFloat*, and in particular:
     * non-IEEE halfprec always raises Invalid for input NaNs
     * we need to check for the overflow case before underflow
     * we weren't getting the tininess-detected-after-rounding
       case correct (somewhat academic since only ARM uses halfprec
       and it is always tininess-detected-before-rounding)
     * non-IEEE halfprec overflow raises only Invalid, not
       Invalid + Inexact
     * we weren't setting Inexact when we should
    
    Also add some clarifying comments about what the code is doing.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index dbda61b..6a6b656 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -3046,6 +3046,10 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     uint32_t mask;
     uint32_t increment;
     int8 roundingMode;
+    int maxexp = ieee ? 15 : 16;
+    bool rounding_bumps_exp;
+    bool is_tiny = false;
+
     a = float32_squash_input_denormal(a STATUS_VAR);
 
     aSig = extractFloat32Frac( a );
@@ -3054,11 +3058,12 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     if ( aExp == 0xFF ) {
         if (aSig) {
             /* Input is a NaN */
-            float16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
             if (!ieee) {
+                float_raise(float_flag_invalid STATUS_VAR);
                 return packFloat16(aSign, 0, 0);
             }
-            return r;
+            return commonNaNToFloat16(
+                float32ToCommonNaN(a STATUS_VAR) STATUS_VAR);
         }
         /* Infinity */
         if (!ieee) {
@@ -3070,58 +3075,80 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
     if (aExp == 0 && aSig == 0) {
         return packFloat16(aSign, 0, 0);
     }
-    /* Decimal point between bits 22 and 23.  */
+    /* Decimal point between bits 22 and 23. Note that we add the 1 bit
+     * even if the input is denormal; however this is harmless because
+     * the largest possible single-precision denormal is still smaller
+     * than the smallest representable half-precision denormal, and so we
+     * will end up ignoring aSig and returning via the "always return zero"
+     * codepath.
+     */
     aSig |= 0x00800000;
     aExp -= 0x7f;
+    /* Calculate the mask of bits of the mantissa which are not
+     * representable in half-precision and will be lost.
+     */
     if (aExp < -14) {
+        /* Will be denormal in halfprec */
         mask = 0x00ffffff;
         if (aExp >= -24) {
             mask >>= 25 + aExp;
         }
     } else {
+        /* Normal number in halfprec */
         mask = 0x00001fff;
     }
-    if (aSig & mask) {
-        float_raise( float_flag_underflow STATUS_VAR );
-        roundingMode = STATUS(float_rounding_mode);
-        switch (roundingMode) {
-        case float_round_nearest_even:
-            increment = (mask + 1) >> 1;
-            if ((aSig & mask) == increment) {
-                increment = aSig & (increment << 1);
-            }
-            break;
-        case float_round_up:
-            increment = aSign ? 0 : mask;
-            break;
-        case float_round_down:
-            increment = aSign ? mask : 0;
-            break;
-        default: /* round_to_zero */
-            increment = 0;
-            break;
-        }
-        aSig += increment;
-        if (aSig >= 0x01000000) {
-            aSig >>= 1;
-            aExp++;
-        }
-    } else if (aExp < -14
-          && STATUS(float_detect_tininess) == float_tininess_before_rounding) {
-        float_raise( float_flag_underflow STATUS_VAR);
-    }
 
-    if (ieee) {
-        if (aExp > 15) {
-            float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
+    roundingMode = STATUS(float_rounding_mode);
+    switch (roundingMode) {
+    case float_round_nearest_even:
+        increment = (mask + 1) >> 1;
+        if ((aSig & mask) == increment) {
+            increment = aSig & (increment << 1);
+        }
+        break;
+    case float_round_up:
+        increment = aSign ? 0 : mask;
+        break;
+    case float_round_down:
+        increment = aSign ? mask : 0;
+        break;
+    default: /* round_to_zero */
+        increment = 0;
+        break;
+    }
+
+    rounding_bumps_exp = (aSig + increment >= 0x01000000);
+
+    if (aExp > maxexp || (aExp == maxexp && rounding_bumps_exp)) {
+        if (ieee) {
+            float_raise(float_flag_overflow | float_flag_inexact STATUS_VAR);
             return packFloat16(aSign, 0x1f, 0);
-        }
-    } else {
-        if (aExp > 16) {
-            float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
+        } else {
+            float_raise(float_flag_invalid STATUS_VAR);
             return packFloat16(aSign, 0x1f, 0x3ff);
         }
     }
+
+    if (aExp < -14) {
+        /* Note that flush-to-zero does not affect half-precision results */
+        is_tiny =
+            (STATUS(float_detect_tininess) == float_tininess_before_rounding)
+            || (aExp < -15)
+            || (!rounding_bumps_exp);
+    }
+    if (aSig & mask) {
+        float_raise(float_flag_inexact STATUS_VAR);
+        if (is_tiny) {
+            float_raise(float_flag_underflow STATUS_VAR);
+        }
+    }
+
+    aSig += increment;
+    if (rounding_bumps_exp) {
+        aSig >>= 1;
+        aExp++;
+    }
+
     if (aExp < -24) {
         return packFloat16(aSign, 0, 0);
     }
commit 9df90ad078ec782d1339bd6879b6ea117f9759f7
Author: Christoffer Dall <christoffer.dall at linaro.org>
Date:   Fri Dec 20 22:09:33 2013 -0800

    hw: arm_gic: Introduce gic_set_priority function
    
    To make the code slightly cleaner to look at and make the save/restore
    code easier to understand, introduce this function to set the priority of
    interrupts.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
    Message-id: 1387606179-22709-3-git-send-email-christoffer.dall at linaro.org
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 27c258a..6c59650 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -168,6 +168,15 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu)
     return new_irq;
 }
 
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
+{
+    if (irq < GIC_INTERNAL) {
+        s->priority1[irq][cpu] = val;
+    } else {
+        s->priority2[(irq) - GIC_INTERNAL] = val;
+    }
+}
+
 void gic_complete_irq(GICState *s, int cpu, int irq)
 {
     int update = 0;
@@ -443,11 +452,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
         irq = (offset - 0x400) + GIC_BASE_IRQ;
         if (irq >= s->num_irq)
             goto bad_reg;
-        if (irq < GIC_INTERNAL) {
-            s->priority1[irq][cpu] = value;
-        } else {
-            s->priority2[irq - GIC_INTERNAL] = value;
-        }
+        gic_set_priority(s, cpu, irq, value);
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target. RAZ/WI on uniprocessor GICs, with the
          * annoying exception of the 11MPCore's GIC.
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index efac78d..8c02d58 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -61,5 +61,6 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu);
 void gic_complete_irq(GICState *s, int cpu, int irq);
 void gic_update(GICState *s);
 void gic_init_irqs_and_distributor(GICState *s, int num_irq);
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val);
 
 #endif /* !QEMU_ARM_GIC_INTERNAL_H */
commit 04050c5c6aa6f9c086a63a30b182b996fb2d3d02
Author: Christoffer Dall <christoffer.dall at linaro.org>
Date:   Fri Dec 20 22:09:32 2013 -0800

    arm_gic: Rename GIC_X_TRIGGER to GIC_X_EDGE_TRIGGER
    
    TRIGGER can really mean mean anything (e.g. was it triggered, is it
    level-triggered, is it edge-triggered, etc.).  Rename to EDGE_TRIGGER to
    make the code comprehensible without looking up the data structure.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
    Message-id: 1387606179-22709-2-git-send-email-christoffer.dall at linaro.org
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d431b7a..27c258a 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -128,7 +128,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
 
     if (level) {
         GIC_SET_LEVEL(irq, cm);
-        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+        if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
             DPRINTF("Set %d pending mask %x\n", irq, target);
             GIC_SET_PENDING(irq, target);
         }
@@ -188,7 +188,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq)
         return; /* No active IRQ.  */
     /* Mark level triggered interrupts as pending if they are still
        raised.  */
-    if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
+    if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
         && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
         DPRINTF("Set %d pending mask %x\n", irq, cm);
         GIC_SET_PENDING(irq, cm);
@@ -311,7 +311,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
         for (i = 0; i < 4; i++) {
             if (GIC_TEST_MODEL(irq + i))
                 res |= (1 << (i * 2));
-            if (GIC_TEST_TRIGGER(irq + i))
+            if (GIC_TEST_EDGE_TRIGGER(irq + i))
                 res |= (2 << (i * 2));
         }
     } else if (offset < 0xfe0) {
@@ -386,7 +386,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
                 /* If a raised level triggered IRQ enabled then mark
                    is as pending.  */
                 if (GIC_TEST_LEVEL(irq + i, mask)
-                        && !GIC_TEST_TRIGGER(irq + i)) {
+                        && !GIC_TEST_EDGE_TRIGGER(irq + i)) {
                     DPRINTF("Set %d pending mask %x\n", irq + i, mask);
                     GIC_SET_PENDING(irq + i, mask);
                 }
@@ -478,9 +478,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
                 GIC_CLEAR_MODEL(irq + i);
             }
             if (value & (2 << (i * 2))) {
-                GIC_SET_TRIGGER(irq + i);
+                GIC_SET_EDGE_TRIGGER(irq + i);
             } else {
-                GIC_CLEAR_TRIGGER(irq + i);
+                GIC_CLEAR_EDGE_TRIGGER(irq + i);
             }
         }
     } else {
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index c765850..710607b 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -51,7 +51,7 @@ static const VMStateDescription vmstate_gic_irq_state = {
         VMSTATE_UINT8(active, gic_irq_state),
         VMSTATE_UINT8(level, gic_irq_state),
         VMSTATE_BOOL(model, gic_irq_state),
-        VMSTATE_BOOL(trigger, gic_irq_state),
+        VMSTATE_BOOL(edge_trigger, gic_irq_state),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -126,7 +126,7 @@ static void arm_gic_common_reset(DeviceState *dev)
     }
     for (i = 0; i < 16; i++) {
         GIC_SET_ENABLED(i, ALL_CPU_MASK);
-        GIC_SET_TRIGGER(i);
+        GIC_SET_EDGE_TRIGGER(i);
     }
     if (s->num_cpu == 1) {
         /* For uniprocessor GICs all interrupts always target the sole CPU */
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 3989fd1..efac78d 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -44,9 +44,9 @@
 #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
 #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
 #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
-#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
+#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
+#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
+#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
 #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?            \
                                     s->priority1[irq][cpu] :            \
                                     s->priority2[(irq) - GIC_INTERNAL])
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 4f381bd..0d232df 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -37,7 +37,7 @@ typedef struct gic_irq_state {
     uint8_t active;
     uint8_t level;
     bool model; /* 0 = N:N, 1 = 1:N */
-    bool trigger; /* nonzero = edge triggered.  */
+    bool edge_trigger; /* true: edge-triggered, false: level-triggered  */
 } gic_irq_state;
 
 typedef struct GICState {
commit 7b1aa025bdd8a62b203eb0a936e20af424fa2870
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 23 16:52:16 2013 +0200

    target-arm: fix build with gcc 4.8.2
    
    commit 5ce4f35781028ce1aee3341e6002f925fdc7aaf3
        "target-arm: A64: add set_pc cpu method"
    
    introduces an array aarch64_cpus which is zero
    size if this code is built without CONFIG_USER_ONLY.
    In particular an attempt to iterate over this array produces a warning
    under gcc 4.8.2:
    
     CC    aarch64-softmmu/target-arm/cpu64.o
    /scm/qemu/target-arm/cpu64.c: In function ‘aarch64_cpu_register_types’:
    /scm/qemu/target-arm/cpu64.c:124:5: error: comparison of unsigned
    expression < 0 is always false [-Werror=type-limits]
         for (i = 0; i < ARRAY_SIZE(aarch64_cpus); i++) {
         ^
    cc1: all warnings being treated as errors
    
    This is the result of ARRAY_SIZE being an unsigned type,
    causing "i" to be promoted to unsigned int as well.
    
    As zero size arrays are a gcc extension, it seems
    cleanest to add a dummy element with NULL name,
    and test for it during registration.
    
    We'll be able to drop this when we add more CPUs.
    
    Cc: Alexander Graf <agraf at suse.de>
    Cc: Peter Maydell <peter.maydell at linaro.org>
    Cc: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 20131223145216.GA22663 at redhat.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index 04ce879..60acd24 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -58,6 +58,7 @@ static const ARMCPUInfo aarch64_cpus[] = {
 #ifdef CONFIG_USER_ONLY
     { .name = "any",         .initfn = aarch64_any_initfn },
 #endif
+    { .name = NULL } /* TODO: drop when we support more CPUs */
 };
 
 static void aarch64_cpu_initfn(Object *obj)
@@ -100,6 +101,11 @@ static void aarch64_cpu_register(const ARMCPUInfo *info)
         .class_init = info->class_init,
     };
 
+    /* TODO: drop when we support more CPUs - all entries will have name set */
+    if (!info->name) {
+        return;
+    }
+
     type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
     type_register(&type_info);
     g_free((void *)type_info.name);
commit 7fcd57e80d134deb925aa47934040a39fd5fa1e0
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Fri Jan 3 17:58:43 2014 -0800

    arm/xilinx_zynq: Always instantiate the GEMs
    
    Don't conditionalise GEM instantiation on networking attachments. The
    device should always be present even if not attached to a network.
    
    This allows for probing of the device by expectant guests (such as
    OS's).  This is needed because sysbus (or AXI in Xilinx's real hw case)
    is not self identifying so the guest has no dynamic way of detecting
    device absence.
    
    Also allows for testing of the GEM in loopback mode with -net none.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 55649779a68ee3ff54b24c339b6fdbdccd1f0ed7.1388800598.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 17251c7..98e0958 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -49,9 +49,11 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     DeviceState *dev;
     SysBusDevice *s;
 
-    qemu_check_nic_model(nd, "cadence_gem");
     dev = qdev_create(NULL, "cadence_gem");
-    qdev_set_nic_properties(dev, nd);
+    if (nd->used) {
+        qemu_check_nic_model(nd, "cadence_gem");
+        qdev_set_nic_properties(dev, nd);
+    }
     qdev_init_nofail(dev);
     s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, base);
@@ -113,7 +115,6 @@ static void zynq_init(QEMUMachineInitArgs *args)
     DeviceState *dev;
     SysBusDevice *busdev;
     qemu_irq pic[64];
-    NICInfo *nd;
     Error *err = NULL;
     int n;
 
@@ -190,14 +191,8 @@ static void zynq_init(QEMUMachineInitArgs *args)
     sysbus_create_varargs("cadence_ttc", 0xF8002000,
             pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
 
-    for (n = 0; n < nb_nics; n++) {
-        nd = &nd_table[n];
-        if (n == 0) {
-            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
-        } else if (n == 1) {
-            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
-        }
-    }
+    gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
+    gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
 
     dev = qdev_create(NULL, "generic-sdhci");
     qdev_init_nofail(dev);
commit afb2530fe328079b3e4355fda9751a1dd9ef6ffb
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Jan 1 23:58:20 2014 -0800

    target-arm: remove raw_read|write duplication
    
    There is an inline duplication of the raw_read and raw_write function
    bodies. Fix by just calling raw_read/raw_write instead.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: e69281b7e1462b346cb313cf0b89eedc0568125f.1388649290.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index be52c1f..6f629f3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -142,11 +142,7 @@ static bool read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
     } else if (ri->readfn) {
         return (ri->readfn(env, ri, v) == 0);
     } else {
-        if (ri->type & ARM_CP_64BIT) {
-            *v = CPREG_FIELD64(env, ri);
-        } else {
-            *v = CPREG_FIELD32(env, ri);
-        }
+        raw_read(env, ri, v);
     }
     return true;
 }
@@ -167,11 +163,7 @@ static bool write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
     } else if (ri->writefn) {
         return (ri->writefn(env, ri, v) == 0);
     } else {
-        if (ri->type & ARM_CP_64BIT) {
-            CPREG_FIELD64(env, ri) = v;
-        } else {
-            CPREG_FIELD32(env, ri) = v;
-        }
+        raw_write(env, ri, v);
     }
     return true;
 }
commit a4f0cec6c9da10c5998fdd53845baf2ce6105830
Author: Sergey Fedorov <s.fedorov at samsung.com>
Date:   Fri Dec 20 10:33:11 2013 +0400

    target-arm: use c13_context field for CONTEXTIDR
    
    Use c13_context field instead of c13_fcse for CONTEXTIDR register
    definition.
    
    Signed-off-by: Sergey Fedorov <s.fedorov at samsung.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1387521191-15350-1-git-send-email-s.fedorov at samsung.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9afec28..be52c1f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -397,7 +397,7 @@ static const ARMCPRegInfo cp_reginfo[] = {
       .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
       .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
     { .name = "CONTEXTIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 1,
-      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_context),
       .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
     /* ??? This covers not just the impdef TLB lockdown registers but also
      * some v7VMSA registers relating to TEX remap, so it is overly broad.
commit 38acd64b1cc8b9589e155d16ba4a0ccf9dc95ae4
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:40 2014 +0000

    char/cadence_uart: Implement Tx flow control
    
    If the UART back-end blocks, buffer in the Tx FIFO to try again later.
    This stops the IO-thread busy waiting on char back-ends (which causes
    all sorts of performance problems).
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 4bea048b3ab38425701d82ccc1ab92545c26b79c.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 8a9ef81..1012f1a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -286,6 +286,34 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
     uart_update_status(s);
 }
 
+static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
+                                  void *opaque)
+{
+    UartState *s = opaque;
+    int ret;
+
+    /* instant drain the fifo when there's no back-end */
+    if (!s->chr) {
+        s->tx_count = 0;
+    }
+
+    if (!s->tx_count) {
+        return FALSE;
+    }
+
+    ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count);
+    s->tx_count -= ret;
+    memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count);
+
+    if (s->tx_count) {
+        int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT, cadence_uart_xmit, s);
+        assert(r);
+    }
+
+    uart_update_status(s);
+    return FALSE;
+}
+
 static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
 {
     if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
@@ -306,8 +334,7 @@ static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
     memcpy(s->tx_fifo + s->tx_count, buf, size);
     s->tx_count += size;
 
-    qemu_chr_fe_write_all(s->chr, s->tx_fifo, s->tx_count);
-    s->tx_count = 0;
+    cadence_uart_xmit(NULL, G_IO_OUT, s);
 }
 
 static void uart_receive(void *opaque, const uint8_t *buf, int size)
commit 1e5d8cacb7fe509aa793ad844105fbc4fe02e015
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:40 2014 +0000

    char/cadence_uart: Delete redundant rx rst logic
    
    uart_rx_reset() called immediately above already does this. Remove.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 05e30826496cf2579084ed801ac0b2c0d0a3071f.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index be32126..8a9ef81 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -438,8 +438,6 @@ static void cadence_uart_reset(DeviceState *dev)
     uart_rx_reset(s);
     uart_tx_reset(s);
 
-    s->rx_count = 0;
-    s->rx_wpos = 0;
     uart_update_status(s);
 }
 
commit 86baecc3e43510c3bef03a0d7e947221823864d3
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:40 2014 +0000

    char/cadence_uart: Use the TX fifo for transmission
    
    Populate the TxFIFO with the Tx data before sending. Prepares
    support for proper Tx flow control implementation.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: bdf7f8af2ef02839bea18665701bc2612f7baa6f.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 3bcaf29..be32126 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -292,7 +292,22 @@ static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
         return;
     }
 
-    qemu_chr_fe_write_all(s->chr, buf, size);
+    if (size > TX_FIFO_SIZE - s->tx_count) {
+        size = TX_FIFO_SIZE - s->tx_count;
+        /*
+         * This can only be a guest error via a bad tx fifo register push,
+         * as can_receive() should stop remote loop and echo modes ever getting
+         * us to here.
+         */
+        qemu_log_mask(LOG_GUEST_ERROR, "cadence_uart: TxFIFO overflow");
+        s->r[R_CISR] |= UART_INTR_ROVR;
+    }
+
+    memcpy(s->tx_fifo + s->tx_count, buf, size);
+    s->tx_count += size;
+
+    qemu_chr_fe_write_all(s->chr, s->tx_fifo, s->tx_count);
+    s->tx_count = 0;
 }
 
 static void uart_receive(void *opaque, const uint8_t *buf, int size)
commit d0ac820fe4152ea3a57fc3fa9f732cc9524017a4
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:39 2014 +0000

    char/cadence_uart: Fix can_receive logic
    
    The can_receive logic was only taking into account the RxFIFO
    occupancy. RxFIFO population is only used for the echo and normal modes
    however. Improve the logic to correctly return the true number of
    receivable characters based on the current mode:
    
    Normal mode: RxFIFO vacancy.
    Remote loopback: TxFIFO vacancy.
    Echo mode: The min of the TxFIFO and RxFIFO vacancies.
    Local Loopback: Return non-zero (to implement droppage)
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 36a58440c9ca5080151e95765c2c81342de8a8df.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 3eeadb1..3bcaf29 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -233,8 +233,16 @@ static void uart_parameters_setup(UartState *s)
 static int uart_can_receive(void *opaque)
 {
     UartState *s = (UartState *)opaque;
+    int ret = MAX(RX_FIFO_SIZE, TX_FIFO_SIZE);
+    uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
 
-    return RX_FIFO_SIZE - s->rx_count;
+    if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
+        ret = MIN(ret, RX_FIFO_SIZE - s->rx_count);
+    }
+    if (ch_mode == REMOTE_LOOPBACK || ch_mode == ECHO_MODE) {
+        ret = MIN(ret, TX_FIFO_SIZE - s->tx_count);
+    }
+    return ret;
 }
 
 static void uart_ctrl_update(UartState *s)
commit 2152e08ad12180f307bc5b838134ab745767d2e5
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:39 2014 +0000

    char/cadence_uart: Remove TX timer & add TX FIFO state
    
    This tx timer implementation is flawed. Despite the controller
    attempting to time the guest visable assertion of the TX-empty status
    bit (and corresponding interrupt) the controller is still transmitting
    characters instantaneously. There is also no sense of multiple character
    delay.
    
    The only side effect of this timer is assertion of tx-empty status. So
    just remove the timer completely and hold tx-empty as permanently
    asserted (its reset status). This matches the actual behaviour of
    instantaneous transmission.
    
    While we are VMSD version bumping, add the tx_fifo as device state to
    prepare for upcomming TxFIFO flow control. Implement the interrupt
    generation logic for the TxFIFO occupancy.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 7a208a7eb8d79d6429fe28b1396c3104371807b2.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 216eed7..3eeadb1 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -121,13 +121,14 @@ typedef struct {
     MemoryRegion iomem;
     uint32_t r[R_MAX];
     uint8_t rx_fifo[RX_FIFO_SIZE];
+    uint8_t tx_fifo[TX_FIFO_SIZE];
     uint32_t rx_wpos;
     uint32_t rx_count;
+    uint32_t tx_count;
     uint64_t char_tx_time;
     CharDriverState *chr;
     qemu_irq irq;
     QEMUTimer *fifo_trigger_handle;
-    QEMUTimer *tx_time_handle;
 } UartState;
 
 static void uart_update_status(UartState *s)
@@ -138,8 +139,12 @@ static void uart_update_status(UartState *s)
     s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
     s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
 
-    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
+    s->r[R_SR] |= s->tx_count == TX_FIFO_SIZE ? UART_SR_INTR_TFUL : 0;
+    s->r[R_SR] |= !s->tx_count ? UART_SR_INTR_TEMPTY : 0;
+    s->r[R_SR] |= s->tx_count >= s->r[R_TTRIG] ? UART_SR_TTRIG : 0;
+
     s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
+    s->r[R_CISR] |= s->r[R_SR] & UART_SR_TTRIG ? UART_INTR_TTRIG : 0;
     qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
 }
 
@@ -152,24 +157,6 @@ static void fifo_trigger_update(void *opaque)
     uart_update_status(s);
 }
 
-static void uart_tx_redo(UartState *s)
-{
-    uint64_t new_tx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
-    timer_mod(s->tx_time_handle, new_tx_time + s->char_tx_time);
-
-    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
-
-    uart_update_status(s);
-}
-
-static void uart_tx_write(void *opaque)
-{
-    UartState *s = (UartState *)opaque;
-
-    uart_tx_redo(s);
-}
-
 static void uart_rx_reset(UartState *s)
 {
     s->rx_wpos = 0;
@@ -181,6 +168,7 @@ static void uart_rx_reset(UartState *s)
 
 static void uart_tx_reset(UartState *s)
 {
+    s->tx_count = 0;
 }
 
 static void uart_send_breaks(UartState *s)
@@ -261,10 +249,6 @@ static void uart_ctrl_update(UartState *s)
 
     s->r[R_CR] &= ~(UART_CR_TXRST | UART_CR_RXRST);
 
-    if ((s->r[R_CR] & UART_CR_TX_EN) && !(s->r[R_CR] & UART_CR_TX_DIS)) {
-            uart_tx_redo(s);
-    }
-
     if (s->r[R_CR] & UART_CR_STARTBRK && !(s->r[R_CR] & UART_CR_STOPBRK)) {
         uart_send_breaks(s);
     }
@@ -447,9 +431,6 @@ static int cadence_uart_init(SysBusDevice *dev)
     s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
             (QEMUTimerCB *)fifo_trigger_update, s);
 
-    s->tx_time_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
-            (QEMUTimerCB *)uart_tx_write, s);
-
     s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
 
     s->chr = qemu_char_get_next_serial();
@@ -473,17 +454,18 @@ static int cadence_uart_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_cadence_uart = {
     .name = "cadence_uart",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
+    .minimum_version_id_old = 2,
     .post_load = cadence_uart_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
         VMSTATE_UINT8_ARRAY(rx_fifo, UartState, RX_FIFO_SIZE),
+        VMSTATE_UINT8_ARRAY(tx_fifo, UartState, RX_FIFO_SIZE),
         VMSTATE_UINT32(rx_count, UartState),
+        VMSTATE_UINT32(tx_count, UartState),
         VMSTATE_UINT32(rx_wpos, UartState),
         VMSTATE_TIMER(fifo_trigger_handle, UartState),
-        VMSTATE_TIMER(tx_time_handle, UartState),
         VMSTATE_END_OF_LIST()
     }
 };
commit 11a239a51ccbf27a22e2aa5f423ff1d6f5df65a7
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:39 2014 +0000

    char/cadence_uart: Define Missing SR/ISR fields
    
    Some (interrupt) status register bits relating to the TxFIFO path were
    not defined. Define them. This prepares support for proper Tx data path
    flow control.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 2068b963f0af8cc834c353944e9fa816d950b163.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index ddd7267..216eed7 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -34,6 +34,9 @@
 #define UART_SR_INTR_RFUL      0x00000004
 #define UART_SR_INTR_TEMPTY    0x00000008
 #define UART_SR_INTR_TFUL      0x00000010
+/* somewhat awkwardly, TTRIG is misaligned between SR and ISR */
+#define UART_SR_TTRIG          0x00002000
+#define UART_INTR_TTRIG        0x00000400
 /* bits fields in CSR that correlate to CISR. If any of these bits are set in
  * SR, then the same bit in CISR is set high too */
 #define UART_SR_TO_CISR_MASK   0x0000001F
@@ -43,6 +46,7 @@
 #define UART_INTR_PARE         0x00000080
 #define UART_INTR_TIMEOUT      0x00000100
 #define UART_INTR_DMSI         0x00000200
+#define UART_INTR_TOVR         0x00001000
 
 #define UART_SR_RACTIVE    0x00000400
 #define UART_SR_TACTIVE    0x00000800
commit 676f4c095d53841626b1ee2cbc7a53b4f6239e4e
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:38 2014 +0000

    char/cadence_uart: Simplify status generation
    
    The status register bits are always pure functions of other device
    state. Move the generation of these bits to the update_status()
    function to simplify. Makes developing much easier as theres now no need
    to recheck status bits on all the changes to rx/tx fifo state.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 321994929f789096975104f99c55732774be4cae.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index d6abc5b..ddd7267 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -128,6 +128,13 @@ typedef struct {
 
 static void uart_update_status(UartState *s)
 {
+    s->r[R_SR] = 0;
+
+    s->r[R_SR] |= s->rx_count == RX_FIFO_SIZE ? UART_SR_INTR_RFUL : 0;
+    s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
+    s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
+
+    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
     s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
     qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
 }
@@ -166,15 +173,10 @@ static void uart_rx_reset(UartState *s)
     if (s->chr) {
         qemu_chr_accept_input(s->chr);
     }
-
-    s->r[R_SR] |= UART_SR_INTR_REMPTY;
-    s->r[R_SR] &= ~UART_SR_INTR_RFUL;
 }
 
 static void uart_tx_reset(UartState *s)
 {
-    s->r[R_SR] |= UART_SR_INTR_TEMPTY;
-    s->r[R_SR] &= ~UART_SR_INTR_TFUL;
 }
 
 static void uart_send_breaks(UartState *s)
@@ -274,8 +276,6 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
         return;
     }
 
-    s->r[R_SR] &= ~UART_SR_INTR_REMPTY;
-
     if (s->rx_count == RX_FIFO_SIZE) {
         s->r[R_CISR] |= UART_INTR_ROVR;
     } else {
@@ -283,15 +283,6 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
             s->rx_fifo[s->rx_wpos] = buf[i];
             s->rx_wpos = (s->rx_wpos + 1) % RX_FIFO_SIZE;
             s->rx_count++;
-
-            if (s->rx_count == RX_FIFO_SIZE) {
-                s->r[R_SR] |= UART_SR_INTR_RFUL;
-                break;
-            }
-
-            if (s->rx_count >= s->r[R_RTRIG]) {
-                s->r[R_SR] |= UART_SR_INTR_RTRIG;
-            }
         }
         timer_mod(s->fifo_trigger_handle, new_rx_time +
                                                 (s->char_tx_time * 4));
@@ -339,26 +330,17 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
         return;
     }
 
-    s->r[R_SR] &= ~UART_SR_INTR_RFUL;
-
     if (s->rx_count) {
         uint32_t rx_rpos =
                 (RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE;
         *c = s->rx_fifo[rx_rpos];
         s->rx_count--;
 
-        if (!s->rx_count) {
-            s->r[R_SR] |= UART_SR_INTR_REMPTY;
-        }
         qemu_chr_accept_input(s->chr);
     } else {
         *c = 0;
-        s->r[R_SR] |= UART_SR_INTR_REMPTY;
     }
 
-    if (s->rx_count < s->r[R_RTRIG]) {
-        s->r[R_SR] &= ~UART_SR_INTR_RTRIG;
-    }
     uart_update_status(s);
 }
 
@@ -447,6 +429,7 @@ static void cadence_uart_reset(DeviceState *dev)
 
     s->rx_count = 0;
     s->rx_wpos = 0;
+    uart_update_status(s);
 }
 
 static int cadence_uart_init(SysBusDevice *dev)
commit 1e77c91e2422ffa366fa5a0a39a6e7cc24a102ca
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:38 2014 +0000

    char/cadence_uart: s/r_fifo/rx_fifo
    
    Rename this field to match the many other uses of "rx". Xilinx
    docmentation (UG585) also refers to this as "RxFIFO".
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 7386d7cee0ea175f7e53ed5ff045265528d34e32.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 7edc119..d6abc5b 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -116,7 +116,7 @@ typedef struct {
 
     MemoryRegion iomem;
     uint32_t r[R_MAX];
-    uint8_t r_fifo[RX_FIFO_SIZE];
+    uint8_t rx_fifo[RX_FIFO_SIZE];
     uint32_t rx_wpos;
     uint32_t rx_count;
     uint64_t char_tx_time;
@@ -280,7 +280,7 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
         s->r[R_CISR] |= UART_INTR_ROVR;
     } else {
         for (i = 0; i < size; i++) {
-            s->r_fifo[s->rx_wpos] = buf[i];
+            s->rx_fifo[s->rx_wpos] = buf[i];
             s->rx_wpos = (s->rx_wpos + 1) % RX_FIFO_SIZE;
             s->rx_count++;
 
@@ -344,7 +344,7 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
     if (s->rx_count) {
         uint32_t rx_rpos =
                 (RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE;
-        *c = s->r_fifo[rx_rpos];
+        *c = s->rx_fifo[rx_rpos];
         s->rx_count--;
 
         if (!s->rx_count) {
@@ -492,7 +492,7 @@ static const VMStateDescription vmstate_cadence_uart = {
     .post_load = cadence_uart_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
-        VMSTATE_UINT8_ARRAY(r_fifo, UartState, RX_FIFO_SIZE),
+        VMSTATE_UINT8_ARRAY(rx_fifo, UartState, RX_FIFO_SIZE),
         VMSTATE_UINT32(rx_count, UartState),
         VMSTATE_UINT32(rx_wpos, UartState),
         VMSTATE_TIMER(fifo_trigger_handle, UartState),
commit 823dd48761a668c8e787cb9cf07234b656a05926
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:38 2014 +0000

    char/cadence_uart: Fix reset.
    
    Don't reset the uart as an init step. Register the reset function as a
    proper reset fn instead.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: d82cd2e65e5a6f8b6deeecb6cced61f0bf3f8c89.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index fb9db89..7edc119 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -431,8 +431,10 @@ static const MemoryRegionOps uart_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void cadence_uart_reset(UartState *s)
+static void cadence_uart_reset(DeviceState *dev)
 {
+    UartState *s = CADENCE_UART(dev);
+
     s->r[R_CR] = 0x00000128;
     s->r[R_IMR] = 0;
     s->r[R_CISR] = 0;
@@ -465,8 +467,6 @@ static int cadence_uart_init(SysBusDevice *dev)
 
     s->chr = qemu_char_get_next_serial();
 
-    cadence_uart_reset(s);
-
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
                               uart_event, s);
@@ -508,6 +508,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
 
     sdc->init = cadence_uart_init;
     dc->vmsd = &vmstate_cadence_uart;
+    dc->reset = cadence_uart_reset;
 }
 
 static const TypeInfo cadence_uart_info = {
commit 589bfb6888385ae1767fe2f94528f2dacf59509a
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:37 2014 +0000

    char/cadence_uart: Add missing uart_update_state
    
    This should be rechecked on bus write accesses as such accesses may
    change the underlying state that generates the interrupt. Particular
    relevant for when the guest touches the interrupt status or mask.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1c250cd61b7b8de492fbc8b79b8370958a56d83b.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index a7b2f21..fb9db89 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -403,6 +403,7 @@ static void uart_write(void *opaque, hwaddr offset,
         uart_parameters_setup(s);
         break;
     }
+    uart_update_status(s);
 }
 
 static uint64_t uart_read(void *opaque, hwaddr offset,
commit 059ca2bf0d882349aa002e10e3769d25cb923eb4
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon Jan 6 10:16:37 2014 +0000

    char/cadence_uart: Mark struct fields as public/private
    
    As per current QOM conventions.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: a1e31bd62e9709ffb9b3efc6c120f83f30b7a660.1388626249.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index f18db53..a7b2f21 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -110,7 +110,9 @@
 #define CADENCE_UART(obj) OBJECT_CHECK(UartState, (obj), TYPE_CADENCE_UART)
 
 typedef struct {
+    /*< private >*/
     SysBusDevice parent_obj;
+    /*< public >*/
 
     MemoryRegion iomem;
     uint32_t r[R_MAX];
commit 4d3da0f3aa5a5d0cbdb17ad49f1baf3cf1bd95a1
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:51 2014 +0000

    target-arm: Give the FPSCR rounding modes names
    
    When setting rounding modes we currently just hardcode the numeric values
    for rounding modes in a big switch statement.
    
    With AArch64 support coming, we will need to refer to these rounding modes
    at different places throughout the code though, so let's better give them
    names so we don't get confused by accident.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, use names from ARM ARM.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 6fbbab2..f1307eb 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -487,6 +487,15 @@ static inline void vfp_set_fpcr(CPUARMState *env, uint32_t val)
     vfp_set_fpscr(env, new_fpscr);
 }
 
+enum arm_fprounding {
+    FPROUNDING_TIEEVEN,
+    FPROUNDING_POSINF,
+    FPROUNDING_NEGINF,
+    FPROUNDING_ZERO,
+    FPROUNDING_TIEAWAY,
+    FPROUNDING_ODD
+};
+
 enum arm_cpu_mode {
   ARM_CPU_MODE_USR = 0x10,
   ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d0b7c27..9afec28 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3815,16 +3815,16 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
     if (changed & (3 << 22)) {
         i = (val >> 22) & 3;
         switch (i) {
-        case 0:
+        case FPROUNDING_TIEEVEN:
             i = float_round_nearest_even;
             break;
-        case 1:
+        case FPROUNDING_POSINF:
             i = float_round_up;
             break;
-        case 2:
+        case FPROUNDING_NEGINF:
             i = float_round_down;
             break;
-        case 3:
+        case FPROUNDING_ZERO:
             i = float_round_to_zero;
             break;
         }
commit 5640ff62c9668651beae0a438540040fd9ee05b5
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:51 2014 +0000

    target-arm: A64: Add support for floating point cond select
    
    This adds decoding support for C3.6.24 FP conditional select.
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 44d8a09..c9fbf0f 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3304,6 +3304,20 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
     }
 }
 
+/* copy src FP register to dst FP register; type specifies single or double */
+static void gen_mov_fp2fp(DisasContext *s, int type, int dst, int src)
+{
+    if (type) {
+        TCGv_i64 v = read_fp_dreg(s, src);
+        write_fp_dreg(s, dst, v);
+        tcg_temp_free_i64(v);
+    } else {
+        TCGv_i32 v = read_fp_sreg(s, src);
+        write_fp_sreg(s, dst, v);
+        tcg_temp_free_i32(v);
+    }
+}
+
 /* C3.6.24 Floating point conditional select
  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
  * +---+---+---+-----------+------+---+------+------+-----+------+------+
@@ -3312,7 +3326,36 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_csel(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    unsigned int mos, type, rm, cond, rn, rd;
+    int label_continue = -1;
+
+    mos = extract32(insn, 29, 3);
+    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
+    rm = extract32(insn, 16, 5);
+    cond = extract32(insn, 12, 4);
+    rn = extract32(insn, 5, 5);
+    rd = extract32(insn, 0, 5);
+
+    if (mos || type > 1) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (cond < 0x0e) { /* not always */
+        int label_match = gen_new_label();
+        label_continue = gen_new_label();
+        arm_gen_test_cc(cond, label_match);
+        /* nomatch: */
+        gen_mov_fp2fp(s, type, rd, rm);
+        tcg_gen_br(label_continue);
+        gen_set_label(label_match);
+    }
+
+    gen_mov_fp2fp(s, type, rd, rn);
+
+    if (cond < 0x0e) { /* continue */
+        gen_set_label(label_continue);
+    }
 }
 
 /* C3.6.25 Floating point data-processing (1 source)
commit 513f1d762f12a4cfdb6cfd59db5f2fb434db60ec
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:51 2014 +0000

    target-arm: A64: Add support for floating point conditional compare
    
    This adds decoding support for C3.6.23 FP Conditional Compare.
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index dc9cc14..44d8a09 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3268,7 +3268,40 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    unsigned int mos, type, rm, cond, rn, op, nzcv;
+    TCGv_i64 tcg_flags;
+    int label_continue = -1;
+
+    mos = extract32(insn, 29, 3);
+    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
+    rm = extract32(insn, 16, 5);
+    cond = extract32(insn, 12, 4);
+    rn = extract32(insn, 5, 5);
+    op = extract32(insn, 4, 1);
+    nzcv = extract32(insn, 0, 4);
+
+    if (mos || type > 1) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (cond < 0x0e) { /* not always */
+        int label_match = gen_new_label();
+        label_continue = gen_new_label();
+        arm_gen_test_cc(cond, label_match);
+        /* nomatch: */
+        tcg_flags = tcg_const_i64(nzcv << 28);
+        gen_set_nzcv(tcg_flags);
+        tcg_temp_free_i64(tcg_flags);
+        tcg_gen_br(label_continue);
+        gen_set_label(label_match);
+    }
+
+    handle_fp_compare(s, type, rn, rm, false, op);
+
+    if (cond < 0x0e) {
+        gen_set_label(label_continue);
+    }
 }
 
 /* C3.6.24 Floating point conditional select
commit da7dafe7ee9372322f926834ca7c0532822ad415
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:50 2014 +0000

    target-arm: A64: Add support for floating point compare
    
    Add decoding support for C3.6.22 Floating-point compare.
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index d3f7067..4ce0d01 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -77,3 +77,48 @@ uint64_t HELPER(rbit64)(uint64_t x)
 
     return x;
 }
+
+/* Convert a softfloat float_relation_ (as returned by
+ * the float*_compare functions) to the correct ARM
+ * NZCV flag state.
+ */
+static inline uint32_t float_rel_to_flags(int res)
+{
+    uint64_t flags;
+    switch (res) {
+    case float_relation_equal:
+        flags = PSTATE_Z | PSTATE_C;
+        break;
+    case float_relation_less:
+        flags = PSTATE_N;
+        break;
+    case float_relation_greater:
+        flags = PSTATE_C;
+        break;
+    case float_relation_unordered:
+    default:
+        flags = PSTATE_C | PSTATE_V;
+        break;
+    }
+    return flags;
+}
+
+uint64_t HELPER(vfp_cmps_a64)(float32 x, float32 y, void *fp_status)
+{
+    return float_rel_to_flags(float32_compare_quiet(x, y, fp_status));
+}
+
+uint64_t HELPER(vfp_cmpes_a64)(float32 x, float32 y, void *fp_status)
+{
+    return float_rel_to_flags(float32_compare(x, y, fp_status));
+}
+
+uint64_t HELPER(vfp_cmpd_a64)(float64 x, float64 y, void *fp_status)
+{
+    return float_rel_to_flags(float64_compare_quiet(x, y, fp_status));
+}
+
+uint64_t HELPER(vfp_cmped_a64)(float64 x, float64 y, void *fp_status)
+{
+    return float_rel_to_flags(float64_compare(x, y, fp_status));
+}
diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h
index a163a94..bca19f3 100644
--- a/target-arm/helper-a64.h
+++ b/target-arm/helper-a64.h
@@ -22,3 +22,7 @@ DEF_HELPER_FLAGS_1(clz64, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_FLAGS_1(cls64, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_FLAGS_1(cls32, TCG_CALL_NO_RWG_SE, i32, i32)
 DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
+DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
+DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
+DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index bb36a66..dc9cc14 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3186,6 +3186,54 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
     }
 }
 
+static void handle_fp_compare(DisasContext *s, bool is_double,
+                              unsigned int rn, unsigned int rm,
+                              bool cmp_with_zero, bool signal_all_nans)
+{
+    TCGv_i64 tcg_flags = tcg_temp_new_i64();
+    TCGv_ptr fpst = get_fpstatus_ptr();
+
+    if (is_double) {
+        TCGv_i64 tcg_vn, tcg_vm;
+
+        tcg_vn = read_fp_dreg(s, rn);
+        if (cmp_with_zero) {
+            tcg_vm = tcg_const_i64(0);
+        } else {
+            tcg_vm = read_fp_dreg(s, rm);
+        }
+        if (signal_all_nans) {
+            gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+        } else {
+            gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+        }
+        tcg_temp_free_i64(tcg_vn);
+        tcg_temp_free_i64(tcg_vm);
+    } else {
+        TCGv_i32 tcg_vn, tcg_vm;
+
+        tcg_vn = read_fp_sreg(s, rn);
+        if (cmp_with_zero) {
+            tcg_vm = tcg_const_i32(0);
+        } else {
+            tcg_vm = read_fp_sreg(s, rm);
+        }
+        if (signal_all_nans) {
+            gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+        } else {
+            gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+        }
+        tcg_temp_free_i32(tcg_vn);
+        tcg_temp_free_i32(tcg_vm);
+    }
+
+    tcg_temp_free_ptr(fpst);
+
+    gen_set_nzcv(tcg_flags);
+
+    tcg_temp_free_i64(tcg_flags);
+}
+
 /* C3.6.22 Floating point compare
  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
@@ -3194,7 +3242,22 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_compare(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    unsigned int mos, type, rm, op, rn, opc, op2r;
+
+    mos = extract32(insn, 29, 3);
+    type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
+    rm = extract32(insn, 16, 5);
+    op = extract32(insn, 14, 2);
+    rn = extract32(insn, 5, 5);
+    opc = extract32(insn, 3, 2);
+    op2r = extract32(insn, 0, 3);
+
+    if (mos || op || op2r || type > 1) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
 }
 
 /* C3.6.23 Floating point conditional compare
commit 6163f868c9284a204ea108238f1812ad50c6bf17
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:50 2014 +0000

    target-arm: A64: Add fmov (scalar, immediate) instruction
    
    This patch adds emulation for the fmov instruction working on scalars
    with an immediate payload.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, rebase and use new infrastructure.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 84497dc..bb36a66 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3479,7 +3479,37 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int imm8 = extract32(insn, 13, 8);
+    int is_double = extract32(insn, 22, 2);
+    uint64_t imm;
+    TCGv_i64 tcg_res;
+
+    if (is_double > 1) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* The imm8 encodes the sign bit, enough bits to represent
+     * an exponent in the range 01....1xx to 10....0xx,
+     * and the most significant 4 bits of the mantissa; see
+     * VFPExpandImm() in the v8 ARM ARM.
+     */
+    if (is_double) {
+        imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
+            (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
+            extract32(imm8, 0, 6);
+        imm <<= 48;
+    } else {
+        imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
+            (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
+            (extract32(imm8, 0, 6) << 3);
+        imm <<= 16;
+    }
+
+    tcg_res = tcg_const_i64(imm);
+    write_fp_dreg(s, rd, tcg_res);
+    tcg_temp_free_i64(tcg_res);
 }
 
 /* C3.6.29 Floating point <-> fixed point conversions
commit 6a30667fb77601b47501172218c7eabd0086c375
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:50 2014 +0000

    target-arm: A64: Add "Floating-point data-processing (3 source)" insns
    
    This patch adds emulation for the "Floating-point data-processing (3 source)"
    group of instructions.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, merged single and double precision patches.
     Implement using muladd as suggested by Richard Henderson.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM: pull field decode up a level, use register accessors]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index c406e2a..84497dc 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3367,6 +3367,82 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
     }
 }
 
+/* C3.6.27 Floating-point data-processing (3 source) - single precision */
+static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
+                                  int rd, int rn, int rm, int ra)
+{
+    TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
+    TCGv_i32 tcg_res = tcg_temp_new_i32();
+    TCGv_ptr fpst = get_fpstatus_ptr();
+
+    tcg_op1 = read_fp_sreg(s, rn);
+    tcg_op2 = read_fp_sreg(s, rm);
+    tcg_op3 = read_fp_sreg(s, ra);
+
+    /* These are fused multiply-add, and must be done as one
+     * floating point operation with no rounding between the
+     * multiplication and addition steps.
+     * NB that doing the negations here as separate steps is
+     * correct : an input NaN should come out with its sign bit
+     * flipped if it is a negated-input.
+     */
+    if (o1 == true) {
+        gen_helper_vfp_negs(tcg_op3, tcg_op3);
+    }
+
+    if (o0 != o1) {
+        gen_helper_vfp_negs(tcg_op1, tcg_op1);
+    }
+
+    gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
+
+    write_fp_sreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i32(tcg_op1);
+    tcg_temp_free_i32(tcg_op2);
+    tcg_temp_free_i32(tcg_op3);
+    tcg_temp_free_i32(tcg_res);
+}
+
+/* C3.6.27 Floating-point data-processing (3 source) - double precision */
+static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
+                                  int rd, int rn, int rm, int ra)
+{
+    TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
+    TCGv_i64 tcg_res = tcg_temp_new_i64();
+    TCGv_ptr fpst = get_fpstatus_ptr();
+
+    tcg_op1 = read_fp_dreg(s, rn);
+    tcg_op2 = read_fp_dreg(s, rm);
+    tcg_op3 = read_fp_dreg(s, ra);
+
+    /* These are fused multiply-add, and must be done as one
+     * floating point operation with no rounding between the
+     * multiplication and addition steps.
+     * NB that doing the negations here as separate steps is
+     * correct : an input NaN should come out with its sign bit
+     * flipped if it is a negated-input.
+     */
+    if (o1 == true) {
+        gen_helper_vfp_negd(tcg_op3, tcg_op3);
+    }
+
+    if (o0 != o1) {
+        gen_helper_vfp_negd(tcg_op1, tcg_op1);
+    }
+
+    gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
+
+    write_fp_dreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i64(tcg_op1);
+    tcg_temp_free_i64(tcg_op2);
+    tcg_temp_free_i64(tcg_op3);
+    tcg_temp_free_i64(tcg_res);
+}
+
 /* C3.6.27 Floating point data-processing (3 source)
  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
  * +---+---+---+-----------+------+----+------+----+------+------+------+
@@ -3375,7 +3451,24 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_3src(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int type = extract32(insn, 22, 2);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int ra = extract32(insn, 10, 5);
+    int rm = extract32(insn, 16, 5);
+    bool o0 = extract32(insn, 15, 1);
+    bool o1 = extract32(insn, 21, 1);
+
+    switch (type) {
+    case 0:
+        handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
+        break;
+    case 1:
+        handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
+        break;
+    default:
+        unallocated_encoding(s);
+    }
 }
 
 /* C3.6.28 Floating point immediate
commit ec73d2e096df1848cbd4255ed2b69954498085aa
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:50 2014 +0000

    target-arm: A64: Add "Floating-point data-processing (2 source)" insns
    
    This patch adds emulation for the "Floating-point data-processing (2 source)"
    group of instructions.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, merge single and double precision patches. Rebase
     and update to new infrastructure. Incorporate FMIN/FMAX support patch by
     Michael Matz.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM:
     * added convenience accessors for FP s and d regs
     * pulled the field decode and opcode validity check up a level]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ba9573a..c406e2a 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -328,6 +328,60 @@ static inline int fp_reg_hi_offset(int regno)
     return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
 }
 
+/* Convenience accessors for reading and writing single and double
+ * FP registers. Writing clears the upper parts of the associated
+ * 128 bit vector register, as required by the architecture.
+ * Note that unlike the GP register accessors, the values returned
+ * by the read functions must be manually freed.
+ */
+static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
+{
+    TCGv_i64 v = tcg_temp_new_i64();
+
+    tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
+    return v;
+}
+
+static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
+{
+    TCGv_i32 v = tcg_temp_new_i32();
+
+    tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
+    return v;
+}
+
+static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
+{
+    TCGv_i64 tcg_zero = tcg_const_i64(0);
+
+    tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
+    tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
+    tcg_temp_free_i64(tcg_zero);
+}
+
+static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    tcg_gen_extu_i32_i64(tmp, v);
+    write_fp_dreg(s, reg, tmp);
+    tcg_temp_free_i64(tmp);
+}
+
+static TCGv_ptr get_fpstatus_ptr(void)
+{
+    TCGv_ptr statusptr = tcg_temp_new_ptr();
+    int offset;
+
+    /* In A64 all instructions (both FP and Neon) use the FPCR;
+     * there is no equivalent of the A32 Neon "standard FPSCR value"
+     * and all operations use vfp.fp_status.
+     */
+    offset = offsetof(CPUARMState, vfp.fp_status);
+    tcg_gen_addi_ptr(statusptr, cpu_env, offset);
+    return statusptr;
+}
+
 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
  * than the 32 bit equivalent.
  */
@@ -3176,6 +3230,112 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
+/* C3.6.26 Floating-point data-processing (2 source) - single precision */
+static void handle_fp_2src_single(DisasContext *s, int opcode,
+                                  int rd, int rn, int rm)
+{
+    TCGv_i32 tcg_op1;
+    TCGv_i32 tcg_op2;
+    TCGv_i32 tcg_res;
+    TCGv_ptr fpst;
+
+    tcg_res = tcg_temp_new_i32();
+    fpst = get_fpstatus_ptr();
+    tcg_op1 = read_fp_sreg(s, rn);
+    tcg_op2 = read_fp_sreg(s, rm);
+
+    switch (opcode) {
+    case 0x0: /* FMUL */
+        gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x1: /* FDIV */
+        gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x2: /* FADD */
+        gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x3: /* FSUB */
+        gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x4: /* FMAX */
+        gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x5: /* FMIN */
+        gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x6: /* FMAXNM */
+        gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x7: /* FMINNM */
+        gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x8: /* FNMUL */
+        gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
+        gen_helper_vfp_negs(tcg_res, tcg_res);
+        break;
+    }
+
+    write_fp_sreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i32(tcg_op1);
+    tcg_temp_free_i32(tcg_op2);
+    tcg_temp_free_i32(tcg_res);
+}
+
+/* C3.6.26 Floating-point data-processing (2 source) - double precision */
+static void handle_fp_2src_double(DisasContext *s, int opcode,
+                                  int rd, int rn, int rm)
+{
+    TCGv_i64 tcg_op1;
+    TCGv_i64 tcg_op2;
+    TCGv_i64 tcg_res;
+    TCGv_ptr fpst;
+
+    tcg_res = tcg_temp_new_i64();
+    fpst = get_fpstatus_ptr();
+    tcg_op1 = read_fp_dreg(s, rn);
+    tcg_op2 = read_fp_dreg(s, rm);
+
+    switch (opcode) {
+    case 0x0: /* FMUL */
+        gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x1: /* FDIV */
+        gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x2: /* FADD */
+        gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x3: /* FSUB */
+        gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x4: /* FMAX */
+        gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x5: /* FMIN */
+        gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x6: /* FMAXNM */
+        gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x7: /* FMINNM */
+        gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
+        break;
+    case 0x8: /* FNMUL */
+        gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
+        gen_helper_vfp_negd(tcg_res, tcg_res);
+        break;
+    }
+
+    write_fp_dreg(s, rd, tcg_res);
+
+    tcg_temp_free_ptr(fpst);
+    tcg_temp_free_i64(tcg_op1);
+    tcg_temp_free_i64(tcg_op2);
+    tcg_temp_free_i64(tcg_res);
+}
+
 /* C3.6.26 Floating point data-processing (2 source)
  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
@@ -3184,7 +3344,27 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
  */
 static void disas_fp_2src(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int type = extract32(insn, 22, 2);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int rm = extract32(insn, 16, 5);
+    int opcode = extract32(insn, 12, 4);
+
+    if (opcode > 8) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (type) {
+    case 0:
+        handle_fp_2src_single(s, opcode, rd, rn, rm);
+        break;
+    case 1:
+        handle_fp_2src_double(s, opcode, rd, rn, rm);
+        break;
+    default:
+        unallocated_encoding(s);
+    }
 }
 
 /* C3.6.27 Floating point data-processing (3 source)
commit f71a2ae50e728f775446302d84e509bf0af43899
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Jan 4 22:15:49 2014 +0000

    target-arm: Use VFP_BINOP macro for min, max, minnum, maxnum
    
    Use the VFP_BINOP macro to provide helpers for min, max, minnum
    and maxnum, rather than hand-rolling them. (The float64 max
    version is not used by A32 but will be needed for A64.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index f91e3fd..d0b7c27 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3864,6 +3864,10 @@ VFP_BINOP(add)
 VFP_BINOP(sub)
 VFP_BINOP(mul)
 VFP_BINOP(div)
+VFP_BINOP(min)
+VFP_BINOP(max)
+VFP_BINOP(minnum)
+VFP_BINOP(maxnum)
 #undef VFP_BINOP
 
 float32 VFP_HELPER(neg, s)(float32 a)
@@ -4317,28 +4321,3 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     float_status *fpst = fpstp;
     return float64_muladd(a, b, c, 0, fpst);
 }
-
-/* ARMv8 VMAXNM/VMINNM */
-float32 VFP_HELPER(maxnm, s)(float32 a, float32 b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float32_maxnum(a, b, fpst);
-}
-
-float64 VFP_HELPER(maxnm, d)(float64 a, float64 b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float64_maxnum(a, b, fpst);
-}
-
-float32 VFP_HELPER(minnm, s)(float32 a, float32 b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float32_minnum(a, b, fpst);
-}
-
-float64 VFP_HELPER(minnm, d)(float64 a, float64 b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float64_minnum(a, b, fpst);
-}
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 73d67dc..dd1160e 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -79,6 +79,14 @@ DEF_HELPER_3(vfp_muls, f32, f32, f32, ptr)
 DEF_HELPER_3(vfp_muld, f64, f64, f64, ptr)
 DEF_HELPER_3(vfp_divs, f32, f32, f32, ptr)
 DEF_HELPER_3(vfp_divd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_maxs, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_maxd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_mins, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_mind, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_maxnums, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_maxnumd, f64, f64, f64, ptr)
+DEF_HELPER_3(vfp_minnums, f32, f32, f32, ptr)
+DEF_HELPER_3(vfp_minnumd, f64, f64, f64, ptr)
 DEF_HELPER_1(vfp_negs, f32, f32)
 DEF_HELPER_1(vfp_negd, f64, f64)
 DEF_HELPER_1(vfp_abss, f32, f32)
@@ -132,11 +140,6 @@ DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
 
-DEF_HELPER_3(vfp_maxnmd, f64, f64, f64, ptr)
-DEF_HELPER_3(vfp_maxnms, f32, f32, f32, ptr)
-DEF_HELPER_3(vfp_minnmd, f64, f64, f64, ptr)
-DEF_HELPER_3(vfp_minnms, f32, f32, f32, ptr)
-
 DEF_HELPER_3(recps_f32, f32, f32, f32, env)
 DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
 DEF_HELPER_2(recpe_f32, f32, f32, env)
@@ -346,8 +349,6 @@ DEF_HELPER_2(neon_qneg_s8, i32, env, i32)
 DEF_HELPER_2(neon_qneg_s16, i32, env, i32)
 DEF_HELPER_2(neon_qneg_s32, i32, env, i32)
 
-DEF_HELPER_3(neon_min_f32, i32, i32, i32, ptr)
-DEF_HELPER_3(neon_max_f32, i32, i32, i32, ptr)
 DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
 DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)
 DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index b028cc2..be6fbd9 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1765,18 +1765,6 @@ uint32_t HELPER(neon_qneg_s32)(CPUARMState *env, uint32_t x)
 }
 
 /* NEON Float helpers.  */
-uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float32_val(float32_min(make_float32(a), make_float32(b), fpst));
-}
-
-uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b, void *fpstp)
-{
-    float_status *fpst = fpstp;
-    return float32_val(float32_max(make_float32(a), make_float32(b), fpst));
-}
-
 uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
 {
     float_status *fpst = fpstp;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 4387547..d04fc9f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2725,9 +2725,9 @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
         tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
         tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
         if (vmin) {
-            gen_helper_vfp_minnmd(dest, frn, frm, fpst);
+            gen_helper_vfp_minnumd(dest, frn, frm, fpst);
         } else {
-            gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
+            gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
         }
         tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
         tcg_temp_free_i64(frn);
@@ -2743,9 +2743,9 @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
         tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
         tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
         if (vmin) {
-            gen_helper_vfp_minnms(dest, frn, frm, fpst);
+            gen_helper_vfp_minnums(dest, frn, frm, fpst);
         } else {
-            gen_helper_vfp_maxnms(dest, frn, frm, fpst);
+            gen_helper_vfp_maxnums(dest, frn, frm, fpst);
         }
         tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
         tcg_temp_free_i32(frn);
@@ -5121,9 +5121,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
         {
             TCGv_ptr fpstatus = get_fpstatus_ptr(1);
             if (size == 0) {
-                gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
+                gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
             } else {
-                gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
+                gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
             }
             tcg_temp_free_ptr(fpstatus);
             break;
@@ -5133,9 +5133,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
                 /* VMAXNM/VMINNM */
                 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
                 if (size == 0) {
-                    gen_helper_vfp_maxnms(tmp, tmp, tmp2, fpstatus);
+                    gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
                 } else {
-                    gen_helper_vfp_minnms(tmp, tmp, tmp2, fpstatus);
+                    gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
                 }
                 tcg_temp_free_ptr(fpstatus);
             } else {
commit e2f90565e7b3e2824fffcfcbcecf86205a1f14e2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Jan 4 22:15:49 2014 +0000

    target-arm: A64: Fix vector register access on bigendian hosts
    
    The A64 128 bit vector registers are stored as a pair of
    uint64_t values in the register array. This means that if
    we're directly loading or storing a value of size less than
    64 bits we must adjust the offset appropriately to account
    for whether the host is bigendian or not. Provide utility
    functions to abstract away the offsetof() calculations for
    the FP registers.
    
    For do_fp_st() we can sidestep most of the issues for 64 bit
    and smaller reg-to-mem transfers by always doing a 64 bit
    load from the register and writing just the piece we need
    to memory.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 326f36d..ba9573a 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -308,6 +308,26 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
     return v;
 }
 
+/* Return the offset into CPUARMState of a slice (from
+ * the least significant end) of FP register Qn (ie
+ * Dn, Sn, Hn or Bn).
+ * (Note that this is not the same mapping as for A32; see cpu.h)
+ */
+static inline int fp_reg_offset(int regno, TCGMemOp size)
+{
+    int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
+#ifdef HOST_WORDS_BIGENDIAN
+    offs += (8 - (1 << size));
+#endif
+    return offs;
+}
+
+/* Offset of the high half of the 128 bit vector Qn */
+static inline int fp_reg_hi_offset(int regno)
+{
+    return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
+}
+
 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
  * than the 32 bit equivalent.
  */
@@ -538,31 +558,15 @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
 {
     /* This writes the bottom N bits of a 128 bit wide vector to memory */
-    int freg_offs = offsetof(CPUARMState, vfp.regs[srcidx * 2]);
     TCGv_i64 tmp = tcg_temp_new_i64();
-
+    tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
     if (size < 4) {
-        switch (size) {
-        case 0:
-            tcg_gen_ld8u_i64(tmp, cpu_env, freg_offs);
-            break;
-        case 1:
-            tcg_gen_ld16u_i64(tmp, cpu_env, freg_offs);
-            break;
-        case 2:
-            tcg_gen_ld32u_i64(tmp, cpu_env, freg_offs);
-            break;
-        case 3:
-            tcg_gen_ld_i64(tmp, cpu_env, freg_offs);
-            break;
-        }
         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
     } else {
         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
-        tcg_gen_ld_i64(tmp, cpu_env, freg_offs);
         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
         tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
-        tcg_gen_ld_i64(tmp, cpu_env, freg_offs + sizeof(float64));
+        tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
         tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
         tcg_temp_free_i64(tcg_hiaddr);
@@ -577,7 +581,6 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
 {
     /* This always zero-extends and writes to a full 128 bit wide vector */
-    int freg_offs = offsetof(CPUARMState, vfp.regs[destidx * 2]);
     TCGv_i64 tmplo = tcg_temp_new_i64();
     TCGv_i64 tmphi;
 
@@ -596,8 +599,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
         tcg_temp_free_i64(tcg_hiaddr);
     }
 
-    tcg_gen_st_i64(tmplo, cpu_env, freg_offs);
-    tcg_gen_st_i64(tmphi, cpu_env, freg_offs + sizeof(float64));
+    tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
+    tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
 
     tcg_temp_free_i64(tmplo);
     tcg_temp_free_i64(tmphi);
@@ -3224,7 +3227,6 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
      */
 
     if (itof) {
-        int freg_offs = offsetof(CPUARMState, vfp.regs[rd * 2]);
         TCGv_i64 tcg_rn = cpu_reg(s, rn);
 
         switch (type) {
@@ -3233,9 +3235,9 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
             /* 32 bit */
             TCGv_i64 tmp = tcg_temp_new_i64();
             tcg_gen_ext32u_i64(tmp, tcg_rn);
-            tcg_gen_st_i64(tmp, cpu_env, freg_offs);
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
             tcg_gen_movi_i64(tmp, 0);
-            tcg_gen_st_i64(tmp, cpu_env, freg_offs + sizeof(float64));
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
             tcg_temp_free_i64(tmp);
             break;
         }
@@ -3243,32 +3245,31 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
         {
             /* 64 bit */
             TCGv_i64 tmp = tcg_const_i64(0);
-            tcg_gen_st_i64(tcg_rn, cpu_env, freg_offs);
-            tcg_gen_st_i64(tmp, cpu_env, freg_offs + sizeof(float64));
+            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
+            tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
             tcg_temp_free_i64(tmp);
             break;
         }
         case 2:
             /* 64 bit to top half. */
-            tcg_gen_st_i64(tcg_rn, cpu_env, freg_offs + sizeof(float64));
+            tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
             break;
         }
     } else {
-        int freg_offs = offsetof(CPUARMState, vfp.regs[rn * 2]);
         TCGv_i64 tcg_rd = cpu_reg(s, rd);
 
         switch (type) {
         case 0:
             /* 32 bit */
-            tcg_gen_ld32u_i64(tcg_rd, cpu_env, freg_offs);
+            tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
             break;
-        case 2:
-            /* 64 bits from top half */
-            freg_offs += sizeof(float64);
-            /* fall through */
         case 1:
             /* 64 bit */
-            tcg_gen_ld_i64(tcg_rd, cpu_env, freg_offs);
+            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
+            break;
+        case 2:
+            /* 64 bits from top half */
+            tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
             break;
         }
     }
commit f6d8a31440c523de15f88a186b9e6daacab17054
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:49 2014 +0000

    target-arm: A64: Add support for dumping AArch64 VFP register state
    
    When dumping the current CPU state, we can also get a request
    to dump the FPU state along with the CPU's integer state.
    
    Add support to dump the VFP state when that flag is set, so that
    we can properly debug code that modifies floating point registers.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, rebased. Output all registers, two per-line.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 40c6fc4..326f36d 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -119,6 +119,22 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                 psr & PSTATE_C ? 'C' : '-',
                 psr & PSTATE_V ? 'V' : '-');
     cpu_fprintf(f, "\n");
+
+    if (flags & CPU_DUMP_FPU) {
+        int numvfpregs = 32;
+        for (i = 0; i < numvfpregs; i += 2) {
+            uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
+            uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
+            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
+                        i, vhi, vlo);
+            vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
+            vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
+            cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
+                        i + 1, vhi, vlo);
+        }
+        cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
+                    vfp_get_fpcr(env), vfp_get_fpsr(env));
+    }
 }
 
 static int get_mem_index(DisasContext *s)
commit 13a7f79dfea84ddb9ff1132bf87583bdda93182d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Jan 4 22:15:48 2014 +0000

    default-configs: Add config for aarch64-linux-user
    
    Add a config for aarch64-linux-user, thereby enabling it as
    a valid target.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/default-configs/aarch64-linux-user.mak b/default-configs/aarch64-linux-user.mak
new file mode 100644
index 0000000..3df7de5
--- /dev/null
+++ b/default-configs/aarch64-linux-user.mak
@@ -0,0 +1,3 @@
+# Default configuration for aarch64-linux-user
+
+CONFIG_GDBSTUB_XML=y
commit 08aef910d9398ba488455dbb553a8253dc24a333
Author: Alex Bennée <alex.bennee at linaro.org>
Date:   Sat Jan 4 22:15:48 2014 +0000

    .travis.yml: Add aarch64-* targets
    
    Now the AArch64 targets are in mainline we can include them in our
    Travis test matrix.
    
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/.travis.yml b/.travis.yml
index 90f1676..c7ff4da 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,6 +16,7 @@ env:
   matrix:
   - TARGETS=alpha-softmmu,alpha-linux-user
   - TARGETS=arm-softmmu,arm-linux-user
+  - TARGETS=aarch64-softmmu,aarch64-linux-user
   - TARGETS=cris-softmmu
   - TARGETS=i386-softmmu,x86_64-softmmu
   - TARGETS=lm32-softmmu
commit e0ee138bf241ca493afe1419d578584b8be05c29
Author: Will Newton <will.newton at linaro.org>
Date:   Sat Jan 4 22:15:48 2014 +0000

    linux-user: AArch64: Use correct values for FPSR/FPCR in sigcontext
    
    Use the helpers provided for getting the correct FPSR and FPCR
    values for the signal context.
    
    Signed-off-by: Will Newton <will.newton at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 4e7148a..6c74b18 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1189,8 +1189,8 @@ static int target_setup_sigframe(struct target_rt_sigframe *sf,
         __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
 #endif
     }
-    __put_user(/*env->fpsr*/0, &aux->fpsimd.fpsr);
-    __put_user(/*env->fpcr*/0, &aux->fpsimd.fpcr);
+    __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
+    __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr);
     __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic);
     __put_user(sizeof(struct target_fpsimd_context),
             &aux->fpsimd.head.size);
@@ -1209,7 +1209,7 @@ static int target_restore_sigframe(CPUARMState *env,
     int i;
     struct target_aux_context *aux =
         (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved;
-    uint32_t magic, size;
+    uint32_t magic, size, fpsr, fpcr;
     uint64_t pstate;
 
     target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
@@ -1235,6 +1235,10 @@ static int target_restore_sigframe(CPUARMState *env,
     for (i = 0; i < 32 * 2; i++) {
         __get_user(env->vfp.regs[i], &aux->fpsimd.vregs[i]);
     }
+    __get_user(fpsr, &aux->fpsimd.fpsr);
+    vfp_set_fpsr(env, fpsr);
+    __get_user(fpcr, &aux->fpsimd.fpcr);
+    vfp_set_fpcr(env, fpcr);
 
     return 0;
 }
commit 1b69f006bff89e5e4710dd04be85277aab8856bf
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:47 2014 +0000

    linux-user: AArch64: define TARGET_CLONE_BACKWARDS
    
    The AArch64 linux-user support was written before but merged after
    commit 4ce6243dc621 which cleaned up the handling of the clone()
    syscall argument order, so we failed to notice that AArch64 also needs
    TARGET_CLONE_BACKWARDS to be defined. Add this define so that clone
    and fork syscalls work correctly.
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h
index aef419e..18f44a8 100644
--- a/linux-user/aarch64/syscall.h
+++ b/linux-user/aarch64/syscall.h
@@ -7,3 +7,4 @@ struct target_pt_regs {
 
 #define UNAME_MACHINE "aarch64"
 #define UNAME_MINIMUM_RELEASE "3.8.0"
+#define TARGET_CLONE_BACKWARDS
commit fa2ef212dff8556ea92c4aef54b57efec69ca6fe
Author: Michael Matz <matz at suse.de>
Date:   Sat Jan 4 22:15:47 2014 +0000

    target-arm: A64: support for ld/st/cl exclusive
    
    This implement exclusive loads/stores for aarch64 along the lines of
    arm32 and ppc implementations. The exclusive load remembers the address
    and loaded value. The exclusive store throws an an exception which uses
    those values to check for equality in a proper exclusive region.
    
    This is not actually the architecture mandated semantics (for either
    AArch32 or AArch64) but it is close enough for typical guest code
    sequences to work correctly, and saves us from having to monitor all
    guest stores. It's fairly easy to come up with test cases where we
    don't behave like hardware - we don't for example model cache line
    behaviour. However in the common patterns this works, and the existing
    32 bit ARM exclusive access implementation has the same limitations.
    
    AArch64 also implements new acquire/release loads/stores (which may be
    either exclusive or non-exclusive). These imposes extra ordering
    constraints on memory operations (ie they act as if they have an implicit
    barrier built into them). As TCG is single-threaded all our barriers
    are no-ops, so these just behave like normal loads and stores.
    
    Signed-off-by: Michael Matz <matz at suse.de>
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index 20f9832..cabc9e1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -585,8 +585,8 @@ do_kernel_trap(CPUARMState *env)
 
     return 0;
 }
-#endif
 
+/* Store exclusive handling for AArch32 */
 static int do_strex(CPUARMState *env)
 {
     uint64_t val;
@@ -670,7 +670,6 @@ done:
     return segv;
 }
 
-#ifdef TARGET_ABI32
 void cpu_loop(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
@@ -885,6 +884,122 @@ void cpu_loop(CPUARMState *env)
 
 #else
 
+/*
+ * Handle AArch64 store-release exclusive
+ *
+ * rs = gets the status result of store exclusive
+ * rt = is the register that is stored
+ * rt2 = is the second register store (in STP)
+ *
+ */
+static int do_strex_a64(CPUARMState *env)
+{
+    uint64_t val;
+    int size;
+    bool is_pair;
+    int rc = 1;
+    int segv = 0;
+    uint64_t addr;
+    int rs, rt, rt2;
+
+    start_exclusive();
+    /* size | is_pair << 2 | (rs << 4) | (rt << 9) | (rt2 << 14)); */
+    size = extract32(env->exclusive_info, 0, 2);
+    is_pair = extract32(env->exclusive_info, 2, 1);
+    rs = extract32(env->exclusive_info, 4, 5);
+    rt = extract32(env->exclusive_info, 9, 5);
+    rt2 = extract32(env->exclusive_info, 14, 5);
+
+    addr = env->exclusive_addr;
+
+    if (addr != env->exclusive_test) {
+        goto finish;
+    }
+
+    switch (size) {
+    case 0:
+        segv = get_user_u8(val, addr);
+        break;
+    case 1:
+        segv = get_user_u16(val, addr);
+        break;
+    case 2:
+        segv = get_user_u32(val, addr);
+        break;
+    case 3:
+        segv = get_user_u64(val, addr);
+        break;
+    default:
+        abort();
+    }
+    if (segv) {
+        env->cp15.c6_data = addr;
+        goto error;
+    }
+    if (val != env->exclusive_val) {
+        goto finish;
+    }
+    if (is_pair) {
+        if (size == 2) {
+            segv = get_user_u32(val, addr + 4);
+        } else {
+            segv = get_user_u64(val, addr + 8);
+        }
+        if (segv) {
+            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+            goto error;
+        }
+        if (val != env->exclusive_high) {
+            goto finish;
+        }
+    }
+    val = env->xregs[rt];
+    switch (size) {
+    case 0:
+        segv = put_user_u8(val, addr);
+        break;
+    case 1:
+        segv = put_user_u16(val, addr);
+        break;
+    case 2:
+        segv = put_user_u32(val, addr);
+        break;
+    case 3:
+        segv = put_user_u64(val, addr);
+        break;
+    }
+    if (segv) {
+        goto error;
+    }
+    if (is_pair) {
+        val = env->xregs[rt2];
+        if (size == 2) {
+            segv = put_user_u32(val, addr + 4);
+        } else {
+            segv = put_user_u64(val, addr + 8);
+        }
+        if (segv) {
+            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+            goto error;
+        }
+    }
+    rc = 0;
+finish:
+    env->pc += 4;
+    /* rs == 31 encodes a write to the ZR, thus throwing away
+     * the status return. This is rather silly but valid.
+     */
+    if (rs < 31) {
+        env->xregs[rs] = rc;
+    }
+error:
+    /* instruction faulted, PC does not advance */
+    /* either way a strex releases any exclusive lock we have */
+    env->exclusive_addr = -1;
+    end_exclusive();
+    return segv;
+}
+
 /* AArch64 main loop */
 void cpu_loop(CPUARMState *env)
 {
@@ -944,7 +1059,7 @@ void cpu_loop(CPUARMState *env)
             }
             break;
         case EXCP_STREX:
-            if (do_strex(env)) {
+            if (do_strex_a64(env)) {
                 addr = env->cp15.c6_data;
                 goto do_segv;
             }
@@ -956,6 +1071,12 @@ void cpu_loop(CPUARMState *env)
             abort();
         }
         process_pending_signals(env);
+        /* Exception return on AArch64 always clears the exclusive monitor,
+         * so any return to running guest code implies this.
+         * A strex (successful or otherwise) also clears the monitor, so
+         * we don't need to specialcase EXCP_STREX.
+         */
+        env->exclusive_addr = -1;
     }
 }
 #endif /* ndef TARGET_ABI32 */
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 6197441..40c6fc4 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -38,6 +38,15 @@ static TCGv_i64 cpu_X[32];
 static TCGv_i64 cpu_pc;
 static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
 
+/* Load/store exclusive handling */
+static TCGv_i64 cpu_exclusive_addr;
+static TCGv_i64 cpu_exclusive_val;
+static TCGv_i64 cpu_exclusive_high;
+#ifdef CONFIG_USER_ONLY
+static TCGv_i64 cpu_exclusive_test;
+static TCGv_i32 cpu_exclusive_info;
+#endif
+
 static const char *regnames[] = {
     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
@@ -70,6 +79,19 @@ void a64_translate_init(void)
     cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
     cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
     cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
+
+    cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
+    cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, exclusive_val), "exclusive_val");
+    cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, exclusive_high), "exclusive_high");
+#ifdef CONFIG_USER_ONLY
+    cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
+        offsetof(CPUARMState, exclusive_test), "exclusive_test");
+    cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
+        offsetof(CPUARMState, exclusive_info), "exclusive_info");
+#endif
 }
 
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
@@ -767,6 +789,11 @@ static void handle_hint(DisasContext *s, uint32_t insn,
     }
 }
 
+static void gen_clrex(DisasContext *s, uint32_t insn)
+{
+    tcg_gen_movi_i64(cpu_exclusive_addr, -1);
+}
+
 /* CLREX, DSB, DMB, ISB */
 static void handle_sync(DisasContext *s, uint32_t insn,
                         unsigned int op1, unsigned int op2, unsigned int crm)
@@ -778,7 +805,7 @@ static void handle_sync(DisasContext *s, uint32_t insn,
 
     switch (op2) {
     case 2: /* CLREX */
-        unsupported_encoding(s, insn);
+        gen_clrex(s, insn);
         return;
     case 4: /* DSB */
     case 5: /* DMB */
@@ -1106,10 +1133,133 @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Load/store exclusive */
+/*
+ * Load/Store exclusive instructions are implemented by remembering
+ * the value/address loaded, and seeing if these are the same
+ * when the store is performed. This is not actually the architecturally
+ * mandated semantics, but it works for typical guest code sequences
+ * and avoids having to monitor regular stores.
+ *
+ * In system emulation mode only one CPU will be running at once, so
+ * this sequence is effectively atomic.  In user emulation mode we
+ * throw an exception and handle the atomic operation elsewhere.
+ */
+static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
+                               TCGv_i64 addr, int size, bool is_pair)
+{
+    TCGv_i64 tmp = tcg_temp_new_i64();
+    TCGMemOp memop = MO_TE + size;
+
+    g_assert(size <= 3);
+    tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
+
+    if (is_pair) {
+        TCGv_i64 addr2 = tcg_temp_new_i64();
+        TCGv_i64 hitmp = tcg_temp_new_i64();
+
+        g_assert(size >= 2);
+        tcg_gen_addi_i64(addr2, addr, 1 << size);
+        tcg_gen_qemu_ld_i64(hitmp, addr2, get_mem_index(s), memop);
+        tcg_temp_free_i64(addr2);
+        tcg_gen_mov_i64(cpu_exclusive_high, hitmp);
+        tcg_gen_mov_i64(cpu_reg(s, rt2), hitmp);
+        tcg_temp_free_i64(hitmp);
+    }
+
+    tcg_gen_mov_i64(cpu_exclusive_val, tmp);
+    tcg_gen_mov_i64(cpu_reg(s, rt), tmp);
+
+    tcg_temp_free_i64(tmp);
+    tcg_gen_mov_i64(cpu_exclusive_addr, addr);
+}
+
+#ifdef CONFIG_USER_ONLY
+static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
+                                TCGv_i64 addr, int size, int is_pair)
+{
+    tcg_gen_mov_i64(cpu_exclusive_test, addr);
+    tcg_gen_movi_i32(cpu_exclusive_info,
+                     size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
+    gen_exception_insn(s, 4, EXCP_STREX);
+}
+#else
+static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
+                                TCGv_i64 addr, int size, int is_pair)
+{
+    qemu_log_mask(LOG_UNIMP,
+                  "%s:%d: system mode store_exclusive unsupported "
+                  "at pc=%016" PRIx64 "\n",
+                  __FILE__, __LINE__, s->pc - 4);
+}
+#endif
+
+/* C3.3.6 Load/store exclusive
+ *
+ *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
+ * +-----+-------------+----+---+----+------+----+-------+------+------+
+ * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
+ * +-----+-------------+----+---+----+------+----+-------+------+------+
+ *
+ *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
+ *   L: 0 -> store, 1 -> load
+ *  o2: 0 -> exclusive, 1 -> not
+ *  o1: 0 -> single register, 1 -> register pair
+ *  o0: 1 -> load-acquire/store-release, 0 -> not
+ *
+ *  o0 == 0 AND o2 == 1 is un-allocated
+ *  o1 == 1 is un-allocated except for 32 and 64 bit sizes
+ */
 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int rt2 = extract32(insn, 10, 5);
+    int is_lasr = extract32(insn, 15, 1);
+    int rs = extract32(insn, 16, 5);
+    int is_pair = extract32(insn, 21, 1);
+    int is_store = !extract32(insn, 22, 1);
+    int is_excl = !extract32(insn, 23, 1);
+    int size = extract32(insn, 30, 2);
+    TCGv_i64 tcg_addr;
+
+    if ((!is_excl && !is_lasr) ||
+        (is_pair && size < 2)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+    tcg_addr = read_cpu_reg_sp(s, rn, 1);
+
+    /* Note that since TCG is single threaded load-acquire/store-release
+     * semantics require no extra if (is_lasr) { ... } handling.
+     */
+
+    if (is_excl) {
+        if (!is_store) {
+            gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
+        } else {
+            gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
+        }
+    } else {
+        TCGv_i64 tcg_rt = cpu_reg(s, rt);
+        if (is_store) {
+            do_gpr_st(s, tcg_rt, tcg_addr, size);
+        } else {
+            do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false);
+        }
+        if (is_pair) {
+            TCGv_i64 tcg_rt2 = cpu_reg(s, rt);
+            tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
+            if (is_store) {
+                do_gpr_st(s, tcg_rt2, tcg_addr, size);
+            } else {
+                do_gpr_ld(s, tcg_rt2, tcg_addr, size, false, false);
+            }
+        }
+    }
 }
 
 /*
commit 03d05e2d0765512fb960192b6e9f9a41c47282bd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Sat Jan 4 22:15:47 2014 +0000

    target-arm: Widen exclusive-access support struct fields to 64 bits
    
    In preparation for adding support for A64 load/store exclusive instructions,
    widen the fields in the CPU state struct that deal with address and data values
    for exclusives from 32 to 64 bits. Although in practice AArch64 and AArch32
    exclusive accesses will be generally separate there are some odd theoretical
    corner cases (eg you should be able to do the exclusive load in AArch32, take
    an exception to AArch64 and successfully do the store exclusive there), and it's
    also easier to reason about.
    
    The changes in semantics for the variables are:
     exclusive_addr  -> extended to 64 bits; -1ULL for "monitor lost",
       otherwise always < 2^32 for AArch32
     exclusive_val   -> extended to 64 bits. 64 bit exclusives in AArch32 now
       use the high half of exclusive_val instead of a separate exclusive_high
     exclusive_high  -> is no longer used in AArch32; extended to 64 bits as
       it will be needed for AArch64's pair-of-64-bit-values exclusives.
     exclusive_test  -> extended to 64 bits, as it is an address. Since this is
       a linux-user-only field, in arm-linux-user it will always have the top
       32 bits zero.
     exclusive_info  -> stays 32 bits, as it is neither data nor address, but
       simply holds register indexes etc. AArch64 will be able to fit all its
       information into 32 bits as well.
    
    Note that the refactoring of gen_store_exclusive() coincidentally fixes
    a minor bug where ldrexd would incorrectly update the first CPU register
    even if the load for the second register faulted.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index c0df8b5..20f9832 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -589,16 +589,21 @@ do_kernel_trap(CPUARMState *env)
 
 static int do_strex(CPUARMState *env)
 {
-    uint32_t val;
+    uint64_t val;
     int size;
     int rc = 1;
     int segv = 0;
     uint32_t addr;
     start_exclusive();
-    addr = env->exclusive_addr;
-    if (addr != env->exclusive_test) {
+    if (env->exclusive_addr != env->exclusive_test) {
         goto fail;
     }
+    /* We know we're always AArch32 so the address is in uint32_t range
+     * unless it was the -1 exclusive-monitor-lost value (which won't
+     * match exclusive_test above).
+     */
+    assert(extract64(env->exclusive_addr, 32, 32) == 0);
+    addr = env->exclusive_addr;
     size = env->exclusive_info & 0xf;
     switch (size) {
     case 0:
@@ -618,19 +623,19 @@ static int do_strex(CPUARMState *env)
         env->cp15.c6_data = addr;
         goto done;
     }
-    if (val != env->exclusive_val) {
-        goto fail;
-    }
     if (size == 3) {
-        segv = get_user_u32(val, addr + 4);
+        uint32_t valhi;
+        segv = get_user_u32(valhi, addr + 4);
         if (segv) {
             env->cp15.c6_data = addr + 4;
             goto done;
         }
-        if (val != env->exclusive_high) {
-            goto fail;
-        }
+        val = deposit64(val, 32, 32, valhi);
+    }
+    if (val != env->exclusive_val) {
+        goto fail;
     }
+
     val = env->regs[(env->exclusive_info >> 8) & 0xf];
     switch (size) {
     case 0:
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 983aa31..6fbbab2 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -278,11 +278,11 @@ typedef struct CPUARMState {
         float_status fp_status;
         float_status standard_fp_status;
     } vfp;
-    uint32_t exclusive_addr;
-    uint32_t exclusive_val;
-    uint32_t exclusive_high;
+    uint64_t exclusive_addr;
+    uint64_t exclusive_val;
+    uint64_t exclusive_high;
 #if defined(CONFIG_USER_ONLY)
-    uint32_t exclusive_test;
+    uint64_t exclusive_test;
     uint32_t exclusive_info;
 #endif
 
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 74f010f..8f9e7d4 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,9 +222,9 @@ static int cpu_post_load(void *opaque, int version_id)
 
 const VMStateDescription vmstate_arm_cpu = {
     .name = "cpu",
-    .version_id = 13,
-    .minimum_version_id = 13,
-    .minimum_version_id_old = 13,
+    .version_id = 14,
+    .minimum_version_id = 14,
+    .minimum_version_id_old = 14,
     .pre_save = cpu_pre_save,
     .post_load = cpu_post_load,
     .fields = (VMStateField[]) {
@@ -253,9 +253,9 @@ const VMStateDescription vmstate_arm_cpu = {
         VMSTATE_VARRAY_INT32(cpreg_vmstate_values, ARMCPU,
                              cpreg_vmstate_array_len,
                              0, vmstate_info_uint64, uint64_t),
-        VMSTATE_UINT32(env.exclusive_addr, ARMCPU),
-        VMSTATE_UINT32(env.exclusive_val, ARMCPU),
-        VMSTATE_UINT32(env.exclusive_high, ARMCPU),
+        VMSTATE_UINT64(env.exclusive_addr, ARMCPU),
+        VMSTATE_UINT64(env.exclusive_val, ARMCPU),
+        VMSTATE_UINT64(env.exclusive_high, ARMCPU),
         VMSTATE_UINT64(env.features, ARMCPU),
         VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
         VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 8bfe950..4387547 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -61,11 +61,10 @@ TCGv_ptr cpu_env;
 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
 static TCGv_i32 cpu_R[16];
 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
-static TCGv_i32 cpu_exclusive_addr;
-static TCGv_i32 cpu_exclusive_val;
-static TCGv_i32 cpu_exclusive_high;
+static TCGv_i64 cpu_exclusive_addr;
+static TCGv_i64 cpu_exclusive_val;
 #ifdef CONFIG_USER_ONLY
-static TCGv_i32 cpu_exclusive_test;
+static TCGv_i64 cpu_exclusive_test;
 static TCGv_i32 cpu_exclusive_info;
 #endif
 
@@ -96,14 +95,12 @@ void arm_translate_init(void)
     cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
     cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
 
-    cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
+    cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
         offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
-    cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
+    cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
         offsetof(CPUARMState, exclusive_val), "exclusive_val");
-    cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
-        offsetof(CPUARMState, exclusive_high), "exclusive_high");
 #ifdef CONFIG_USER_ONLY
-    cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
+    cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
         offsetof(CPUARMState, exclusive_test), "exclusive_test");
     cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
         offsetof(CPUARMState, exclusive_info), "exclusive_info");
@@ -6758,30 +6755,34 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
     default:
         abort();
     }
-    tcg_gen_mov_i32(cpu_exclusive_val, tmp);
-    store_reg(s, rt, tmp);
+
     if (size == 3) {
         TCGv_i32 tmp2 = tcg_temp_new_i32();
+        TCGv_i32 tmp3 = tcg_temp_new_i32();
+
         tcg_gen_addi_i32(tmp2, addr, 4);
-        tmp = tcg_temp_new_i32();
-        gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
+        gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
         tcg_temp_free_i32(tmp2);
-        tcg_gen_mov_i32(cpu_exclusive_high, tmp);
-        store_reg(s, rt2, tmp);
+        tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
+        store_reg(s, rt2, tmp3);
+    } else {
+        tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
     }
-    tcg_gen_mov_i32(cpu_exclusive_addr, addr);
+
+    store_reg(s, rt, tmp);
+    tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
 }
 
 static void gen_clrex(DisasContext *s)
 {
-    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+    tcg_gen_movi_i64(cpu_exclusive_addr, -1);
 }
 
 #ifdef CONFIG_USER_ONLY
 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
                                 TCGv_i32 addr, int size)
 {
-    tcg_gen_mov_i32(cpu_exclusive_test, addr);
+    tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
     tcg_gen_movi_i32(cpu_exclusive_info,
                      size | (rd << 4) | (rt << 8) | (rt2 << 12));
     gen_exception_insn(s, 4, EXCP_STREX);
@@ -6791,6 +6792,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
                                 TCGv_i32 addr, int size)
 {
     TCGv_i32 tmp;
+    TCGv_i64 val64, extaddr;
     int done_label;
     int fail_label;
 
@@ -6802,7 +6804,11 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
        } */
     fail_label = gen_new_label();
     done_label = gen_new_label();
-    tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
+    extaddr = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(extaddr, addr);
+    tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
+    tcg_temp_free_i64(extaddr);
+
     tmp = tcg_temp_new_i32();
     switch (size) {
     case 0:
@@ -6818,17 +6824,24 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     default:
         abort();
     }
-    tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
-    tcg_temp_free_i32(tmp);
+
+    val64 = tcg_temp_new_i64();
     if (size == 3) {
         TCGv_i32 tmp2 = tcg_temp_new_i32();
+        TCGv_i32 tmp3 = tcg_temp_new_i32();
         tcg_gen_addi_i32(tmp2, addr, 4);
-        tmp = tcg_temp_new_i32();
-        gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
+        gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
         tcg_temp_free_i32(tmp2);
-        tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
-        tcg_temp_free_i32(tmp);
+        tcg_gen_concat_i32_i64(val64, tmp, tmp3);
+        tcg_temp_free_i32(tmp3);
+    } else {
+        tcg_gen_extu_i32_i64(val64, tmp);
     }
+    tcg_temp_free_i32(tmp);
+
+    tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
+    tcg_temp_free_i64(val64);
+
     tmp = load_reg(s, rt);
     switch (size) {
     case 0:
@@ -6856,7 +6869,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
     gen_set_label(fail_label);
     tcg_gen_movi_i32(cpu_R[rd], 1);
     gen_set_label(done_label);
-    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+    tcg_gen_movi_i64(cpu_exclusive_addr, -1);
 }
 #endif
 
commit 32b64e860d6e0887b3d2ad36a940c362646146f4
Author: Alexander Graf <agraf at suse.de>
Date:   Sat Jan 4 22:15:46 2014 +0000

    target-arm: aarch64: add support for ld lit
    
    Adds support for Load Register (literal), both normal
    and SIMD/FP forms.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Alex Bennée <alex.bennee at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 538d69e..6197441 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1112,10 +1112,53 @@ static void disas_ldst_excl(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
-/* Load register (literal) */
+/*
+ * C3.3.5 Load register (literal)
+ *
+ *  31 30 29   27  26 25 24 23                5 4     0
+ * +-----+-------+---+-----+-------------------+-------+
+ * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
+ * +-----+-------+---+-----+-------------------+-------+
+ *
+ * V: 1 -> vector (simd/fp)
+ * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
+ *                   10-> 32 bit signed, 11 -> prefetch
+ * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
+ */
 static void disas_ld_lit(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rt = extract32(insn, 0, 5);
+    int64_t imm = sextract32(insn, 5, 19) << 2;
+    bool is_vector = extract32(insn, 26, 1);
+    int opc = extract32(insn, 30, 2);
+    bool is_signed = false;
+    int size = 2;
+    TCGv_i64 tcg_rt, tcg_addr;
+
+    if (is_vector) {
+        if (opc == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        size = 2 + opc;
+    } else {
+        if (opc == 3) {
+            /* PRFM (literal) : prefetch */
+            return;
+        }
+        size = 2 + extract32(opc, 0, 1);
+        is_signed = extract32(opc, 1, 1);
+    }
+
+    tcg_rt = cpu_reg(s, rt);
+
+    tcg_addr = tcg_const_i64((s->pc - 4) + imm);
+    if (is_vector) {
+        do_fp_ld(s, rt, tcg_addr, size);
+    } else {
+        do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
+    }
+    tcg_temp_free_i64(tcg_addr);
 }
 
 /*
commit 750813cfaa971bd8679d9f77b8bd21d316871f51
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:46 2014 +0000

    target-arm: A64: add support for conditional compare insns
    
    this patch adds support for C3.5.4 - C3.5.5
    Conditional compare (both immediate and register)
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 9f508b9..538d69e 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -2483,16 +2483,67 @@ static void disas_adc_sbc(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Conditional compare (immediate) */
-static void disas_cc_imm(DisasContext *s, uint32_t insn)
+/* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
+ *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
+ * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
+ * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
+ * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
+ *        [1]                             y                [0]       [0]
+ */
+static void disas_cc(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
-}
+    unsigned int sf, op, y, cond, rn, nzcv, is_imm;
+    int label_continue = -1;
+    TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
 
-/* Conditional compare (register) */
-static void disas_cc_reg(DisasContext *s, uint32_t insn)
-{
-    unsupported_encoding(s, insn);
+    if (!extract32(insn, 29, 1)) {
+        unallocated_encoding(s);
+        return;
+    }
+    if (insn & (1 << 10 | 1 << 4)) {
+        unallocated_encoding(s);
+        return;
+    }
+    sf = extract32(insn, 31, 1);
+    op = extract32(insn, 30, 1);
+    is_imm = extract32(insn, 11, 1);
+    y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
+    cond = extract32(insn, 12, 4);
+    rn = extract32(insn, 5, 5);
+    nzcv = extract32(insn, 0, 4);
+
+    if (cond < 0x0e) { /* not always */
+        int label_match = gen_new_label();
+        label_continue = gen_new_label();
+        arm_gen_test_cc(cond, label_match);
+        /* nomatch: */
+        tcg_tmp = tcg_temp_new_i64();
+        tcg_gen_movi_i64(tcg_tmp, nzcv << 28);
+        gen_set_nzcv(tcg_tmp);
+        tcg_temp_free_i64(tcg_tmp);
+        tcg_gen_br(label_continue);
+        gen_set_label(label_match);
+    }
+    /* match, or condition is always */
+    if (is_imm) {
+        tcg_y = new_tmp_a64(s);
+        tcg_gen_movi_i64(tcg_y, y);
+    } else {
+        tcg_y = cpu_reg(s, y);
+    }
+    tcg_rn = cpu_reg(s, rn);
+
+    tcg_tmp = tcg_temp_new_i64();
+    if (op) {
+        gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
+    } else {
+        gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
+    }
+    tcg_temp_free_i64(tcg_tmp);
+
+    if (cond < 0x0e) { /* continue */
+        gen_set_label(label_continue);
+    }
 }
 
 /* C3.5.6 Conditional select
@@ -2846,11 +2897,7 @@ static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
             disas_adc_sbc(s, insn);
             break;
         case 0x2: /* Conditional compare */
-            if (insn & (1 << 11)) { /* (immediate) */
-                disas_cc_imm(s, insn);
-            } else {            /* (register) */
-                disas_cc_reg(s, insn);
-            }
+            disas_cc(s, insn); /* both imm and reg forms */
             break;
         case 0x4: /* Conditional select */
             disas_cond_select(s, insn);
commit 643dbb07d26d100487ea87153d5222674bf482d8
Author: Claudio Fontana <claudio.fontana at linaro.org>
Date:   Sat Jan 4 22:15:46 2014 +0000

    target-arm: A64: add support for add/sub with carry
    
    This patch adds support for C3.5.3 Add/subtract (with carry):
    instructions ADC, ADCS, SBC, SBCS.
    
    Signed-off-by: Claudio Fontana <claudio.fontana at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index c8ed799..9f508b9 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -393,6 +393,71 @@ static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
     }
 }
 
+/* dest = T0 + T1 + CF; do not compute flags. */
+static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
+{
+    TCGv_i64 flag = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(flag, cpu_CF);
+    tcg_gen_add_i64(dest, t0, t1);
+    tcg_gen_add_i64(dest, dest, flag);
+    tcg_temp_free_i64(flag);
+
+    if (!sf) {
+        tcg_gen_ext32u_i64(dest, dest);
+    }
+}
+
+/* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
+static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
+{
+    if (sf) {
+        TCGv_i64 result, cf_64, vf_64, tmp;
+        result = tcg_temp_new_i64();
+        cf_64 = tcg_temp_new_i64();
+        vf_64 = tcg_temp_new_i64();
+        tmp = tcg_const_i64(0);
+
+        tcg_gen_extu_i32_i64(cf_64, cpu_CF);
+        tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
+        tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
+        tcg_gen_trunc_i64_i32(cpu_CF, cf_64);
+        gen_set_NZ64(result);
+
+        tcg_gen_xor_i64(vf_64, result, t0);
+        tcg_gen_xor_i64(tmp, t0, t1);
+        tcg_gen_andc_i64(vf_64, vf_64, tmp);
+        tcg_gen_shri_i64(vf_64, vf_64, 32);
+        tcg_gen_trunc_i64_i32(cpu_VF, vf_64);
+
+        tcg_gen_mov_i64(dest, result);
+
+        tcg_temp_free_i64(tmp);
+        tcg_temp_free_i64(vf_64);
+        tcg_temp_free_i64(cf_64);
+        tcg_temp_free_i64(result);
+    } else {
+        TCGv_i32 t0_32, t1_32, tmp;
+        t0_32 = tcg_temp_new_i32();
+        t1_32 = tcg_temp_new_i32();
+        tmp = tcg_const_i32(0);
+
+        tcg_gen_trunc_i64_i32(t0_32, t0);
+        tcg_gen_trunc_i64_i32(t1_32, t1);
+        tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
+        tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
+
+        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
+        tcg_gen_xor_i32(tmp, t0_32, t1_32);
+        tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
+        tcg_gen_extu_i32_i64(dest, cpu_NF);
+
+        tcg_temp_free_i32(tmp);
+        tcg_temp_free_i32(t1_32);
+        tcg_temp_free_i32(t0_32);
+    }
+}
+
 /*
  * Load/Store generators
  */
@@ -2376,10 +2441,46 @@ static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_tmp);
 }
 
-/* Add/subtract (with carry) */
+/* C3.5.3 - Add/subtract (with carry)
+ *  31 30 29 28 27 26 25 24 23 22 21  20  16  15   10  9    5 4   0
+ * +--+--+--+------------------------+------+---------+------+-----+
+ * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | opcode2 |  Rn  |  Rd |
+ * +--+--+--+------------------------+------+---------+------+-----+
+ *                                            [000000]
+ */
+
 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    unsigned int sf, op, setflags, rm, rn, rd;
+    TCGv_i64 tcg_y, tcg_rn, tcg_rd;
+
+    if (extract32(insn, 10, 6) != 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    sf = extract32(insn, 31, 1);
+    op = extract32(insn, 30, 1);
+    setflags = extract32(insn, 29, 1);
+    rm = extract32(insn, 16, 5);
+    rn = extract32(insn, 5, 5);
+    rd = extract32(insn, 0, 5);
+
+    tcg_rd = cpu_reg(s, rd);
+    tcg_rn = cpu_reg(s, rn);
+
+    if (op) {
+        tcg_y = new_tmp_a64(s);
+        tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
+    } else {
+        tcg_y = cpu_reg(s, rm);
+    }
+
+    if (setflags) {
+        gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
+    } else {
+        gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
+    }
 }
 
 /* Conditional compare (immediate) */
commit 7826163492b306d99680f9fd5e46720404d902f0
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 09:38:07 2013 +1000

    target-i386: Tidy ljmp
    
    Remove an unnecessary move opcode.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index ed3e6ce..b0f2279 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4961,8 +4961,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                           tcg_const_i32(s->pc - pc_start));
             } else {
                 gen_op_movl_seg_T0_vm(R_CS);
-                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
-                gen_op_jmp_v(cpu_T[0]);
+                gen_op_jmp_v(cpu_T[1]);
             }
             gen_eob(s);
             break;
commit 74bdfbda5537452c59db64fab42179f01d0436b9
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 09:33:53 2013 +1000

    target-i386: Rename gen_op_jmp_T0 to gen_op_jmp_v
    
    And make the destination argument explicit.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index ac78fd2..ed3e6ce 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -398,9 +398,9 @@ static void gen_add_A0_im(DisasContext *s, int val)
         gen_op_addl_A0_im(val);
 }
 
-static inline void gen_op_jmp_T0(void)
+static inline void gen_op_jmp_v(TCGv dest)
 {
-    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
+    tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
 }
 
 static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
@@ -495,7 +495,7 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
 static inline void gen_jmp_im(target_ulong pc)
 {
     tcg_gen_movi_tl(cpu_tmp0, pc);
-    tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, eip));
+    gen_op_jmp_v(cpu_tmp0);
 }
 
 static inline void gen_string_movl_A0_ESI(DisasContext *s)
@@ -4918,7 +4918,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             next_eip = s->pc - s->cs_base;
             tcg_gen_movi_tl(cpu_T[1], next_eip);
             gen_push_v(s, cpu_T[1]);
-            gen_op_jmp_T0();
+            gen_op_jmp_v(cpu_T[0]);
             gen_eob(s);
             break;
         case 3: /* lcall Ev */
@@ -4945,7 +4945,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (dflag == MO_16) {
                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
             }
-            gen_op_jmp_T0();
+            gen_op_jmp_v(cpu_T[0]);
             gen_eob(s);
             break;
         case 5: /* ljmp Ev */
@@ -4962,7 +4962,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             } else {
                 gen_op_movl_seg_T0_vm(R_CS);
                 tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
-                gen_op_jmp_T0();
+                gen_op_jmp_v(cpu_T[0]);
             }
             gen_eob(s);
             break;
@@ -6358,14 +6358,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         ot = gen_pop_T0(s);
         gen_stack_update(s, val + (1 << ot));
         /* Note that gen_pop_T0 uses a zero-extending load.  */
-        gen_op_jmp_T0();
+        gen_op_jmp_v(cpu_T[0]);
         gen_eob(s);
         break;
     case 0xc3: /* ret */
         ot = gen_pop_T0(s);
         gen_pop_update(s, ot);
         /* Note that gen_pop_T0 uses a zero-extending load.  */
-        gen_op_jmp_T0();
+        gen_op_jmp_v(cpu_T[0]);
         gen_eob(s);
         break;
     case 0xca: /* lret im */
@@ -6383,7 +6383,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
             /* NOTE: keeping EIP updated is not a problem in case of
                exception */
-            gen_op_jmp_T0();
+            gen_op_jmp_v(cpu_T[0]);
             /* pop selector */
             gen_op_addl_A0_im(1 << dflag);
             gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
commit 830a19a425e7b513cd08eb1f8aa58dfc7e9d0d48
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 09:13:27 2013 +1000

    target-i386: Tidy some size computation
    
    Clean up relics of multiple size domains: - MO_16 + 1 => - 1 + 1 => 0.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 69c25fd..ac78fd2 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4923,7 +4923,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 3: /* lcall Ev */
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
-            gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
+            gen_add_A0_im(s, 1 << ot);
             gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_lcall:
             if (s->pe && !s->vm86) {
@@ -4950,7 +4950,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 5: /* ljmp Ev */
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
-            gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
+            gen_add_A0_im(s, 1 << ot);
             gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_ljmp:
             if (s->pe && !s->vm86) {
@@ -5578,7 +5578,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto illegal_op;
         gen_lea_modrm(env, s, modrm);
         gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
-        gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
+        gen_add_A0_im(s, 1 << ot);
         /* load the segment first to handle exceptions properly */
         gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
commit 33b7891bd5ea08e22aac755a145cb5c9afd2f86c
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 08:54:33 2013 +1000

    target-i386: Remove gen_op_mov_reg_A0
    
    Replace with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 2b6d777..69c25fd 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -358,11 +358,6 @@ static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
     }
 }
 
-static inline void gen_op_mov_reg_A0(TCGMemOp size, int reg)
-{
-    gen_op_mov_reg_v(size, reg, cpu_A0);
-}
-
 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
 {
     if (ot == MO_8 && byte_reg_is_xH(reg)) {
@@ -5458,7 +5453,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         s->addseg = 0;
         gen_lea_modrm(env, s, modrm);
         s->addseg = val;
-        gen_op_mov_reg_A0(ot, reg);
+        gen_op_mov_reg_v(ot, reg, cpu_A0);
         break;
 
     case 0xa0: /* mov EAX, Ov */
commit c56baccf67c0251ce4480ecc6f72e3511add8b5e
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 08:52:13 2013 +1000

    target-i386: Remove gen_op_mov_TN_reg
    
    Replace with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index e7a7ce5..2b6d777 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -373,11 +373,6 @@ static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
     }
 }
 
-static inline void gen_op_mov_TN_reg(TCGMemOp ot, int t_index, int reg)
-{
-    gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
-}
-
 static inline void gen_op_movl_A0_reg(int reg)
 {
     tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]);
@@ -1136,7 +1131,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
 
 static inline void gen_stos(DisasContext *s, TCGMemOp ot)
 {
-    gen_op_mov_TN_reg(MO_32, 0, R_EAX);
+    gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
     gen_string_movl_A0_EDI(s);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
@@ -1313,7 +1308,7 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
 static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
 {
     if (d != OR_TMP0) {
-        gen_op_mov_TN_reg(ot, 0, d);
+        gen_op_mov_v_reg(ot, cpu_T[0], d);
     } else {
         gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
     }
@@ -1379,7 +1374,7 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
 static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
 {
     if (d != OR_TMP0) {
-        gen_op_mov_TN_reg(ot, 0, d);
+        gen_op_mov_v_reg(ot, cpu_T[0], d);
     } else {
         gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
     }
@@ -1449,7 +1444,7 @@ static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
     if (op1 == OR_TMP0) {
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
     }
 
     tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
@@ -1485,7 +1480,7 @@ static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
     if (op1 == OR_TMP0)
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     else
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
 
     op2 &= mask;
     if (op2 != 0) {
@@ -1533,7 +1528,7 @@ static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
     if (op1 == OR_TMP0) {
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
     }
 
     tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
@@ -1619,7 +1614,7 @@ static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
     if (op1 == OR_TMP0) {
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
     }
 
     op2 &= mask;
@@ -1697,7 +1692,7 @@ static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
     if (op1 == OR_TMP0)
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     else
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
     
     if (is_right) {
         switch (ot) {
@@ -1753,7 +1748,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
     if (op1 == OR_TMP0) {
         gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
-        gen_op_mov_TN_reg(ot, 0, op1);
+        gen_op_mov_v_reg(ot, cpu_T[0], op1);
     }
 
     count = tcg_temp_new();
@@ -1827,7 +1822,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
 static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
 {
     if (s != OR_TMP1)
-        gen_op_mov_TN_reg(ot, 1, s);
+        gen_op_mov_v_reg(ot, cpu_T[1], s);
     switch(op) {
     case OP_ROL:
         gen_rot_rm_T1(s1, ot, d, 0);
@@ -2157,10 +2152,10 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
     if (mod == 3) {
         if (is_store) {
             if (reg != OR_TMP0)
-                gen_op_mov_TN_reg(ot, 0, reg);
+                gen_op_mov_v_reg(ot, cpu_T[0], reg);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
-            gen_op_mov_TN_reg(ot, 0, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], rm);
             if (reg != OR_TMP0)
                 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         }
@@ -2168,7 +2163,7 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
         gen_lea_modrm(env, s, modrm);
         if (is_store) {
             if (reg != OR_TMP0)
-                gen_op_mov_TN_reg(ot, 0, reg);
+                gen_op_mov_v_reg(ot, cpu_T[0], reg);
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
@@ -2450,7 +2445,7 @@ static void gen_pusha(DisasContext *s)
     if (s->addseg)
         gen_op_addl_A0_seg(s, R_SS);
     for(i = 0;i < 8; i++) {
-        gen_op_mov_TN_reg(MO_32, 0, 7 - i);
+        gen_op_mov_v_reg(MO_32, cpu_T[0], 7 - i);
         gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
         gen_op_addl_A0_im(1 << s->dflag);
     }
@@ -2492,7 +2487,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
 
         /* push bp */
-        gen_op_mov_TN_reg(MO_32, 0, R_EBP);
+        gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
         gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         if (level) {
             /* XXX: must save state */
@@ -2514,7 +2509,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         if (s->addseg)
             gen_op_addl_A0_seg(s, R_SS);
         /* push bp */
-        gen_op_mov_TN_reg(MO_32, 0, R_EBP);
+        gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
         gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         if (level) {
             /* XXX: must save state */
@@ -4143,7 +4138,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     break;
                 case 0x20: /* pinsrb */
                     if (mod == 3) {
-                        gen_op_mov_TN_reg(MO_32, 0, rm);
+                        gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
                     } else {
                         tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
                                            s->mem_index, MO_UB);
@@ -4599,7 +4594,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 } else {
                     opreg = rm;
                 }
-                gen_op_mov_TN_reg(ot, 1, reg);
+                gen_op_mov_v_reg(ot, cpu_T[1], reg);
                 gen_op(s, op, ot, opreg);
                 break;
             case 1: /* OP Gv, Ev */
@@ -4613,7 +4608,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 } else if (op == OP_XORL && rm == reg) {
                     goto xor_zero;
                 } else {
-                    gen_op_mov_TN_reg(ot, 1, rm);
+                    gen_op_mov_v_reg(ot, cpu_T[1], rm);
                 }
                 gen_op(s, op, ot, reg);
                 break;
@@ -4693,7 +4688,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_lea_modrm(env, s, modrm);
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
-            gen_op_mov_TN_reg(ot, 0, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], rm);
         }
 
         switch(op) {
@@ -4724,7 +4719,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 4: /* mul */
             switch(ot) {
             case MO_8:
-                gen_op_mov_TN_reg(MO_8, 1, R_EAX);
+                gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
                 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
@@ -4735,7 +4730,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 set_cc_op(s, CC_OP_MULB);
                 break;
             case MO_16:
-                gen_op_mov_TN_reg(MO_16, 1, R_EAX);
+                gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
@@ -4773,7 +4768,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 5: /* imul */
             switch(ot) {
             case MO_8:
-                gen_op_mov_TN_reg(MO_8, 1, R_EAX);
+                gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
                 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
@@ -4785,7 +4780,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 set_cc_op(s, CC_OP_MULB);
                 break;
             case MO_16:
-                gen_op_mov_TN_reg(MO_16, 1, R_EAX);
+                gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
                 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
@@ -4902,7 +4897,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (op >= 2 && op != 3 && op != 5)
                 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
-            gen_op_mov_TN_reg(ot, 0, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], rm);
         }
 
         switch(op) {
@@ -4992,7 +4987,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = ((modrm >> 3) & 7) | rex_r;
 
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
-        gen_op_mov_TN_reg(ot, 1, reg);
+        gen_op_mov_v_reg(ot, cpu_T[1], reg);
         gen_op_testl_T0_T1_cc();
         set_cc_op(s, CC_OP_LOGICB + ot);
         break;
@@ -5002,7 +4997,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         ot = mo_b_d(b, dflag);
         val = insn_get(env, s, ot);
 
-        gen_op_mov_TN_reg(ot, 0, OR_EAX);
+        gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
         tcg_gen_movi_tl(cpu_T[1], val);
         gen_op_testl_T0_T1_cc();
         set_cc_op(s, CC_OP_LOGICB + ot);
@@ -5012,18 +5007,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         switch (dflag) {
 #ifdef TARGET_X86_64
         case MO_64:
-            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
+            gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
             break;
 #endif
         case MO_32:
-            gen_op_mov_TN_reg(MO_16, 0, R_EAX);
+            gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
             break;
         case MO_16:
-            gen_op_mov_TN_reg(MO_8, 0, R_EAX);
+            gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
             tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
             break;
@@ -5035,19 +5030,19 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         switch (dflag) {
 #ifdef TARGET_X86_64
         case MO_64:
-            gen_op_mov_TN_reg(MO_64, 0, R_EAX);
+            gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
             gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
             break;
 #endif
         case MO_32:
-            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
+            gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
             gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
             break;
         case MO_16:
-            gen_op_mov_TN_reg(MO_16, 0, R_EAX);
+            gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
             gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
@@ -5074,7 +5069,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             val = (int8_t)insn_get(env, s, MO_8);
             tcg_gen_movi_tl(cpu_T[1], val);
         } else {
-            gen_op_mov_TN_reg(ot, 1, reg);
+            gen_op_mov_v_reg(ot, cpu_T[1], reg);
         }
         switch (ot) {
 #ifdef TARGET_X86_64
@@ -5117,14 +5112,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         mod = (modrm >> 6) & 3;
         if (mod == 3) {
             rm = (modrm & 7) | REX_B(s);
-            gen_op_mov_TN_reg(ot, 0, reg);
-            gen_op_mov_TN_reg(ot, 1, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], reg);
+            gen_op_mov_v_reg(ot, cpu_T[1], rm);
             tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
             gen_op_mov_reg_v(ot, reg, cpu_T[1]);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             gen_lea_modrm(env, s, modrm);
-            gen_op_mov_TN_reg(ot, 0, reg);
+            gen_op_mov_v_reg(ot, cpu_T[0], reg);
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
@@ -5218,7 +5213,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /**************************/
         /* push/pop */
     case 0x50 ... 0x57: /* push */
-        gen_op_mov_TN_reg(MO_32, 0, (b & 7) | REX_B(s));
+        gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
         gen_push_v(s, cpu_T[0]);
         break;
     case 0x58 ... 0x5f: /* pop */
@@ -5276,13 +5271,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xc9: /* leave */
         /* XXX: exception not precise (ESP is updated before potential exception) */
         if (CODE64(s)) {
-            gen_op_mov_TN_reg(MO_64, 0, R_EBP);
+            gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
             gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
         } else if (s->ss32) {
-            gen_op_mov_TN_reg(MO_32, 0, R_EBP);
+            gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
             gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
         } else {
-            gen_op_mov_TN_reg(MO_16, 0, R_EBP);
+            gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
             gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
         }
         ot = gen_pop_T0(s);
@@ -5425,7 +5420,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
 
             if (mod == 3) {
-                gen_op_mov_TN_reg(ot, 0, rm);
+                gen_op_mov_v_reg(ot, cpu_T[0], rm);
                 switch (s_ot) {
                 case MO_UB:
                     tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
@@ -5491,7 +5486,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
             } else {
-                gen_op_mov_TN_reg(ot, 0, R_EAX);
+                gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
                 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             }
         }
@@ -5546,13 +5541,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod == 3) {
             rm = (modrm & 7) | REX_B(s);
         do_xchg_reg:
-            gen_op_mov_TN_reg(ot, 0, reg);
-            gen_op_mov_TN_reg(ot, 1, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], reg);
+            gen_op_mov_v_reg(ot, cpu_T[1], rm);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         } else {
             gen_lea_modrm(env, s, modrm);
-            gen_op_mov_TN_reg(ot, 0, reg);
+            gen_op_mov_v_reg(ot, cpu_T[0], reg);
             /* for xchg, lock is implicit */
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_lock();
@@ -5672,7 +5667,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             opreg = rm;
         }
-        gen_op_mov_TN_reg(ot, 1, reg);
+        gen_op_mov_v_reg(ot, cpu_T[1], reg);
 
         if (shift) {
             TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
@@ -6313,7 +6308,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         val = cpu_ldub_code(env, s->pc++);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
-        gen_op_mov_TN_reg(ot, 1, R_EAX);
+        gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
 
         if (use_icount)
             gen_io_start();
@@ -6347,7 +6342,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
-        gen_op_mov_TN_reg(ot, 1, R_EAX);
+        gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
 
         if (use_icount)
             gen_io_start();
@@ -6603,7 +6598,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x9e: /* sahf */
         if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
             goto illegal_op;
-        gen_op_mov_TN_reg(MO_8, 0, R_AH);
+        gen_op_mov_v_reg(MO_8, cpu_T[0], R_AH);
         gen_compute_eflags(s);
         tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -6651,7 +6646,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_lea_modrm(env, s, modrm);
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
-            gen_op_mov_TN_reg(ot, 0, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], rm);
         }
         /* load shift */
         val = cpu_ldub_code(env, s->pc++);
@@ -6677,7 +6672,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
-        gen_op_mov_TN_reg(MO_32, 1, reg);
+        gen_op_mov_v_reg(MO_32, cpu_T[1], reg);
         if (mod != 3) {
             gen_lea_modrm(env, s, modrm);
             /* specific case: we need to add a displacement */
@@ -6687,7 +6682,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
-            gen_op_mov_TN_reg(ot, 0, rm);
+            gen_op_mov_v_reg(ot, cpu_T[0], rm);
         }
     bt_op:
         tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
@@ -6935,7 +6930,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
-        gen_op_mov_TN_reg(ot, 0, reg);
+        gen_op_mov_v_reg(ot, cpu_T[0], reg);
         gen_lea_modrm(env, s, modrm);
         gen_jmp_im(pc_start - s->cs_base);
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -6949,13 +6944,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = (b & 7) | REX_B(s);
 #ifdef TARGET_X86_64
         if (dflag == MO_64) {
-            gen_op_mov_TN_reg(MO_64, 0, reg);
+            gen_op_mov_v_reg(MO_64, cpu_T[0], reg);
             tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
         } else
 #endif
         {
-            gen_op_mov_TN_reg(MO_32, 0, reg);
+            gen_op_mov_v_reg(MO_32, cpu_T[0], reg);
             tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
@@ -7455,7 +7450,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
 
             if (mod == 3) {
-                gen_op_mov_TN_reg(MO_32, 0, rm);
+                gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
                 /* sign extend */
                 if (d_ot == MO_64) {
                     tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
@@ -7595,7 +7590,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
                 if (b & 2) {
-                    gen_op_mov_TN_reg(ot, 0, rm);
+                    gen_op_mov_v_reg(ot, cpu_T[0], rm);
                     gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
                                          cpu_T[0]);
                     gen_jmp_im(s->pc - s->cs_base);
@@ -7632,7 +7627,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             if (b & 2) {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
-                gen_op_mov_TN_reg(ot, 0, rm);
+                gen_op_mov_v_reg(ot, cpu_T[0], rm);
                 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
commit fd5185ecccb1ee0893dcd37324e8db96f876f866
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 08:46:59 2013 +1000

    target-i386: Remove gen_op_addl_T0_T1
    
    Replace with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 46bc615..e7a7ce5 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -408,11 +408,6 @@ static void gen_add_A0_im(DisasContext *s, int val)
         gen_op_addl_A0_im(val);
 }
 
-static inline void gen_op_addl_T0_T1(void)
-{
-    tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-}
-
 static inline void gen_op_jmp_T0(void)
 {
     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
@@ -1340,7 +1335,7 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
         set_cc_op(s1, CC_OP_SBBB + ot);
         break;
     case OP_ADDL:
-        gen_op_addl_T0_T1();
+        tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
         gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update2_cc();
         set_cc_op(s1, CC_OP_ADDB + ot);
@@ -5124,14 +5119,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_mov_TN_reg(ot, 1, rm);
-            gen_op_addl_T0_T1();
+            tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
             gen_op_mov_reg_v(ot, reg, cpu_T[1]);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             gen_lea_modrm(env, s, modrm);
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
-            gen_op_addl_T0_T1();
+            tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         }
commit 68773f84dcedf5971bf756d0b13fa7c99049ed21
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 08:43:50 2013 +1000

    target-i386: Remove gen_op_mov_reg_T1
    
    Replace with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8553b71..46bc615 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -358,11 +358,6 @@ static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
     }
 }
 
-static inline void gen_op_mov_reg_T1(TCGMemOp ot, int reg)
-{
-    gen_op_mov_reg_v(ot, reg, cpu_T[1]);
-}
-
 static inline void gen_op_mov_reg_A0(TCGMemOp size, int reg)
 {
     gen_op_mov_reg_v(size, reg, cpu_A0);
@@ -2464,7 +2459,7 @@ static void gen_pusha(DisasContext *s)
         gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
         gen_op_addl_A0_im(1 << s->dflag);
     }
-    gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
+    gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
 }
 
 /* NOTE: wrap around in 16 bit not fully handled */
@@ -2486,7 +2481,7 @@ static void gen_popa(DisasContext *s)
         }
         gen_op_addl_A0_im(1 << s->dflag);
     }
-    gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
+    gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
 }
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
@@ -2510,9 +2505,9 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
                                      tcg_const_i32((ot == MO_64)),
                                      cpu_T[1]);
         }
-        gen_op_mov_reg_T1(ot, R_EBP);
+        gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_T1(MO_64, R_ESP);
+        gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[1]);
     } else
 #endif
     {
@@ -2532,9 +2527,9 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
                                    tcg_const_i32(s->dflag - 1),
                                    cpu_T[1]);
         }
-        gen_op_mov_reg_T1(ot, R_EBP);
+        gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
+        gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
     }
 }
 
@@ -5130,7 +5125,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_mov_TN_reg(ot, 1, rm);
             gen_op_addl_T0_T1();
-            gen_op_mov_reg_T1(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[1]);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             gen_lea_modrm(env, s, modrm);
@@ -5138,7 +5133,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_op_addl_T0_T1();
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
-            gen_op_mov_reg_T1(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         }
         gen_op_update2_cc();
         set_cc_op(s, CC_OP_ADDB + ot);
@@ -5559,7 +5554,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_mov_TN_reg(ot, 1, rm);
             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
-            gen_op_mov_reg_T1(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         } else {
             gen_lea_modrm(env, s, modrm);
             gen_op_mov_TN_reg(ot, 0, reg);
@@ -5570,7 +5565,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_unlock();
-            gen_op_mov_reg_T1(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         }
         break;
     case 0xc4: /* les Gv */
@@ -5603,7 +5598,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
         /* then put the data */
-        gen_op_mov_reg_T1(ot, reg);
+        gen_op_mov_reg_v(ot, reg, cpu_T[1]);
         if (s->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
@@ -6311,7 +6306,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_io_start();
         tcg_gen_movi_i32(cpu_tmp2_i32, val);
         gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
-        gen_op_mov_reg_T1(ot, R_EAX);
+        gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
         if (use_icount) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
@@ -6345,7 +6340,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_io_start();
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
         gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
-        gen_op_mov_reg_T1(ot, R_EAX);
+        gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
         if (use_icount) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
commit 480a762d1795487e893918c5eb47124f275b4312
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 7 08:41:38 2013 +1000

    target-i386: Remove gen_op_mov_reg_T0
    
    Replace with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 5a594b9..8553b71 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -358,11 +358,6 @@ static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
     }
 }
 
-static inline void gen_op_mov_reg_T0(TCGMemOp ot, int reg)
-{
-    gen_op_mov_reg_v(ot, reg, cpu_T[0]);
-}
-
 static inline void gen_op_mov_reg_T1(TCGMemOp ot, int reg)
 {
     gen_op_mov_reg_v(ot, reg, cpu_T[1]);
@@ -513,7 +508,7 @@ static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
     if (d == OR_TMP0) {
         gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
     } else {
-        gen_op_mov_reg_T0(idx, d);
+        gen_op_mov_reg_v(idx, d, cpu_T[0]);
     }
 }
 
@@ -1162,7 +1157,7 @@ static inline void gen_lods(DisasContext *s, TCGMemOp ot)
 {
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
-    gen_op_mov_reg_T0(ot, R_EAX);
+    gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_ESI);
 }
@@ -2173,11 +2168,11 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
         if (is_store) {
             if (reg != OR_TMP0)
                 gen_op_mov_TN_reg(ot, 0, reg);
-            gen_op_mov_reg_T0(ot, rm);
+            gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
             if (reg != OR_TMP0)
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         }
     } else {
         gen_lea_modrm(env, s, modrm);
@@ -2188,7 +2183,7 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
         } else {
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
             if (reg != OR_TMP0)
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         }
     }
 }
@@ -2297,7 +2292,7 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
 
     tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
                        cpu_T[0], cpu_regs[reg]);
-    gen_op_mov_reg_T0(ot, reg);
+    gen_op_mov_reg_v(ot, reg, cpu_T[0]);
 
     if (cc.mask != -1) {
         tcg_temp_free(cc.reg);
@@ -2487,7 +2482,7 @@ static void gen_popa(DisasContext *s)
         /* ESP is not reloaded */
         if (i != 3) {
             gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
-            gen_op_mov_reg_T0(s->dflag, 7 - i);
+            gen_op_mov_reg_v(s->dflag, 7 - i, cpu_T[0]);
         }
         gen_op_addl_A0_im(1 << s->dflag);
     }
@@ -3553,7 +3548,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 goto illegal_op;
 #endif
             }
-            gen_op_mov_reg_T0(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[0]);
             break;
         case 0xc4: /* pinsrw */
         case 0x1c4:
@@ -3588,7 +3583,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                                 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
             }
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_op_mov_reg_T0(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[0]);
             break;
         case 0x1d6: /* movq ea, xmm */
             if (mod != 3) {
@@ -3739,7 +3734,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                                  cpu_T[0], tcg_const_i32(8 << ot));
 
                 ot = mo_64_32(s->dflag);
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 break;
 
             case 0x1f0: /* crc32 or movbe */
@@ -3766,7 +3761,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 if ((b & 1) == 0) {
                     tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
                                        s->mem_index, ot | MO_BE);
-                    gen_op_mov_reg_T0(ot, reg);
+                    gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 } else {
                     tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
                                        s->mem_index, ot | MO_BE);
@@ -3782,7 +3777,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 gen_op_update1_cc();
                 set_cc_op(s, CC_OP_LOGICB + ot);
                 break;
@@ -3821,7 +3816,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
                     tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
 
-                    gen_op_mov_reg_T0(ot, reg);
+                    gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                     gen_op_update1_cc();
                     set_cc_op(s, CC_OP_LOGICB + ot);
                 }
@@ -3849,7 +3844,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 tcg_gen_movi_tl(cpu_A0, -1);
                 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
                 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 gen_op_update1_cc();
                 set_cc_op(s, CC_OP_BMILGB + ot);
                 break;
@@ -4023,7 +4018,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     }
                     tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
                 }
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 break;
 
             case 0x0f3:
@@ -4042,7 +4037,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 case 1: /* blsr By,Ey */
                     tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
                     tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                    gen_op_mov_reg_T0(ot, s->vex_v);
+                    gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
                     gen_op_update2_cc();
                     set_cc_op(s, CC_OP_BMILGB + ot);
                     break;
@@ -4103,7 +4098,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                                             xmm_regs[reg].XMM_B(val & 15)));
                     if (mod == 3) {
-                        gen_op_mov_reg_T0(ot, rm);
+                        gen_op_mov_reg_v(ot, rm, cpu_T[0]);
                     } else {
                         tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
                                            s->mem_index, MO_UB);
@@ -4113,7 +4108,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                                             xmm_regs[reg].XMM_W(val & 7)));
                     if (mod == 3) {
-                        gen_op_mov_reg_T0(ot, rm);
+                        gen_op_mov_reg_v(ot, rm, cpu_T[0]);
                     } else {
                         tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
                                            s->mem_index, MO_LEUW);
@@ -4150,7 +4145,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                                             xmm_regs[reg].XMM_L(val & 3)));
                     if (mod == 3) {
-                        gen_op_mov_reg_T0(ot, rm);
+                        gen_op_mov_reg_v(ot, rm, cpu_T[0]);
                     } else {
                         tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
                                            s->mem_index, MO_LEUL);
@@ -4284,7 +4279,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
                     tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
                 }
-                gen_op_mov_reg_T0(ot, reg);
+                gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                 break;
 
             default:
@@ -4609,7 +4604,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     /* xor reg, reg optimisation */
                     set_cc_op(s, CC_OP_CLR);
                     tcg_gen_movi_tl(cpu_T[0], 0);
-                    gen_op_mov_reg_T0(ot, reg);
+                    gen_op_mov_reg_v(ot, reg, cpu_T[0]);
                     break;
                 } else {
                     opreg = rm;
@@ -4723,7 +4718,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (mod != 3) {
                 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             } else {
-                gen_op_mov_reg_T0(ot, rm);
+                gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             }
             break;
         case 3: /* neg */
@@ -4731,7 +4726,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (mod != 3) {
                 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             } else {
-                gen_op_mov_reg_T0(ot, rm);
+                gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             }
             gen_op_update_neg_cc();
             set_cc_op(s, CC_OP_SUBB + ot);
@@ -4744,7 +4739,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(MO_16, R_EAX);
+                gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
                 set_cc_op(s, CC_OP_MULB);
@@ -4755,10 +4750,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(MO_16, R_EAX);
+                gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
-                gen_op_mov_reg_T0(MO_16, R_EDX);
+                gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
                 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
                 set_cc_op(s, CC_OP_MULW);
                 break;
@@ -4793,7 +4788,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(MO_16, R_EAX);
+                gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
@@ -4805,12 +4800,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(MO_16, R_EAX);
+                gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
-                gen_op_mov_reg_T0(MO_16, R_EDX);
+                gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
                 set_cc_op(s, CC_OP_MULW);
                 break;
             default:
@@ -5029,18 +5024,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case MO_64:
             gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(MO_64, R_EAX);
+            gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
             break;
 #endif
         case MO_32:
             gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(MO_32, R_EAX);
+            gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
             break;
         case MO_16:
             gen_op_mov_TN_reg(MO_8, 0, R_EAX);
             tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(MO_16, R_EAX);
+            gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
             break;
         default:
             tcg_abort();
@@ -5052,20 +5047,20 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case MO_64:
             gen_op_mov_TN_reg(MO_64, 0, R_EAX);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
-            gen_op_mov_reg_T0(MO_64, R_EDX);
+            gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
             break;
 #endif
         case MO_32:
             gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
-            gen_op_mov_reg_T0(MO_32, R_EDX);
+            gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
             break;
         case MO_16:
             gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
-            gen_op_mov_reg_T0(MO_16, R_EDX);
+            gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
             break;
         default:
             tcg_abort();
@@ -5119,7 +5114,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
             tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
             tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
-            gen_op_mov_reg_T0(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[0]);
             break;
         }
         set_cc_op(s, CC_OP_MULB + ot);
@@ -5136,7 +5131,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_TN_reg(ot, 1, rm);
             gen_op_addl_T0_T1();
             gen_op_mov_reg_T1(ot, reg);
-            gen_op_mov_reg_T0(ot, rm);
+            gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             gen_lea_modrm(env, s, modrm);
             gen_op_mov_TN_reg(ot, 0, reg);
@@ -5240,7 +5235,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         ot = gen_pop_T0(s);
         /* NOTE: order is important for pop %sp */
         gen_pop_update(s, ot);
-        gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
+        gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
         break;
     case 0x60: /* pusha */
         if (CODE64(s))
@@ -5270,7 +5265,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             /* NOTE: order is important for pop %sp */
             gen_pop_update(s, ot);
             rm = (modrm & 7) | REX_B(s);
-            gen_op_mov_reg_T0(ot, rm);
+            gen_op_mov_reg_v(ot, rm, cpu_T[0]);
         } else {
             /* NOTE: order is important too for MMU exceptions */
             s->popl_esp_hack = 1 << ot;
@@ -5292,16 +5287,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /* XXX: exception not precise (ESP is updated before potential exception) */
         if (CODE64(s)) {
             gen_op_mov_TN_reg(MO_64, 0, R_EBP);
-            gen_op_mov_reg_T0(MO_64, R_ESP);
+            gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
         } else if (s->ss32) {
             gen_op_mov_TN_reg(MO_32, 0, R_EBP);
-            gen_op_mov_reg_T0(MO_32, R_ESP);
+            gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
         } else {
             gen_op_mov_TN_reg(MO_16, 0, R_EBP);
-            gen_op_mov_reg_T0(MO_16, R_ESP);
+            gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
         }
         ot = gen_pop_T0(s);
-        gen_op_mov_reg_T0(ot, R_EBP);
+        gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
         gen_pop_update(s, ot);
         break;
     case 0x06: /* push es */
@@ -5376,7 +5371,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod != 3) {
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         } else {
-            gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
+            gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
         }
         break;
     case 0x8a:
@@ -5386,7 +5381,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = ((modrm >> 3) & 7) | rex_r;
 
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
-        gen_op_mov_reg_T0(ot, reg);
+        gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         break;
     case 0x8e: /* mov seg, Gv */
         modrm = cpu_ldub_code(env, s->pc++);
@@ -5456,11 +5451,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
                     break;
                 }
-                gen_op_mov_reg_T0(d_ot, reg);
+                gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
             } else {
                 gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
-                gen_op_mov_reg_T0(d_ot, reg);
+                gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
             }
         }
         break;
@@ -5504,7 +5499,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_add_A0_ds_seg(s);
             if ((b & 2) == 0) {
                 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
-                gen_op_mov_reg_T0(ot, R_EAX);
+                gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
             } else {
                 gen_op_mov_TN_reg(ot, 0, R_EAX);
                 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
@@ -5518,12 +5513,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_extu(s->aflag, cpu_A0);
         gen_add_A0_ds_seg(s);
         gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
-        gen_op_mov_reg_T0(MO_8, R_EAX);
+        gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
         break;
     case 0xb0 ... 0xb7: /* mov R, Ib */
         val = insn_get(env, s, MO_8);
         tcg_gen_movi_tl(cpu_T[0], val);
-        gen_op_mov_reg_T0(MO_8, (b & 7) | REX_B(s));
+        gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
         break;
     case 0xb8 ... 0xbf: /* mov R, Iv */
 #ifdef TARGET_X86_64
@@ -5534,7 +5529,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             s->pc += 8;
             reg = (b & 7) | REX_B(s);
             tcg_gen_movi_tl(cpu_T[0], tmp);
-            gen_op_mov_reg_T0(MO_64, reg);
+            gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
         } else
 #endif
         {
@@ -5542,7 +5537,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             val = insn_get(env, s, ot);
             reg = (b & 7) | REX_B(s);
             tcg_gen_movi_tl(cpu_T[0], val);
-            gen_op_mov_reg_T0(ot, reg);
+            gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         }
         break;
 
@@ -5563,7 +5558,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         do_xchg_reg:
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_mov_TN_reg(ot, 1, rm);
-            gen_op_mov_reg_T0(ot, rm);
+            gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             gen_op_mov_reg_T1(ot, reg);
         } else {
             gen_lea_modrm(env, s, modrm);
@@ -6166,7 +6161,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 case 0:
                     gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
                     tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                    gen_op_mov_reg_T0(MO_16, R_EAX);
+                    gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
                     break;
                 default:
                     goto illegal_op;
@@ -6630,7 +6625,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_compute_eflags(s);
         /* Note: gen_compute_eflags() only gives the condition codes */
         tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
-        gen_op_mov_reg_T0(MO_8, R_AH);
+        gen_op_mov_reg_v(MO_8, R_AH, cpu_T[0]);
         break;
     case 0xf5: /* cmc */
         gen_compute_eflags(s);
@@ -6737,7 +6732,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (mod != 3) {
                 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             } else {
-                gen_op_mov_reg_T0(ot, rm);
+                gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             }
             tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
             tcg_gen_movi_tl(cpu_cc_dst, 0);
@@ -6794,7 +6789,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
                                cpu_regs[reg], cpu_T[0]);
         }
-        gen_op_mov_reg_T0(ot, reg);
+        gen_op_mov_reg_v(ot, reg, cpu_T[0]);
         break;
         /************************/
         /* bcd */
@@ -6966,14 +6961,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (dflag == MO_64) {
             gen_op_mov_TN_reg(MO_64, 0, reg);
             tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(MO_64, reg);
+            gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
         } else
 #endif
         {
             gen_op_mov_TN_reg(MO_32, 0, reg);
             tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(MO_32, reg);
+            gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
         }
         break;
     case 0xd6: /* salc */
@@ -6981,7 +6976,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto illegal_op;
         gen_compute_eflags_c(s, cpu_T[0]);
         tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
-        gen_op_mov_reg_T0(MO_8, R_EAX);
+        gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
         break;
     case 0xe0: /* loopnz */
     case 0xe1: /* loopz */
@@ -7475,11 +7470,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 if (d_ot == MO_64) {
                     tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
                 }
-                gen_op_mov_reg_T0(d_ot, reg);
+                gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
             } else {
                 gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
-                gen_op_mov_reg_T0(d_ot, reg);
+                gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
             }
         } else
 #endif
@@ -7617,7 +7612,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     gen_eob(s);
                 } else {
                     gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
-                    gen_op_mov_reg_T0(ot, rm);
+                    gen_op_mov_reg_v(ot, rm, cpu_T[0]);
                 }
                 break;
             default:
@@ -7654,7 +7649,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
-                gen_op_mov_reg_T0(ot, rm);
+                gen_op_mov_reg_v(ot, rm, cpu_T[0]);
             }
         }
         break;
@@ -7789,7 +7784,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
-        gen_op_mov_reg_T0(ot, reg);
+        gen_op_mov_reg_v(ot, reg, cpu_T[0]);
 
         set_cc_op(s, CC_OP_EFLAGS);
         break;
commit fac0aff9f3f2bb23e597ff0dad92d8eee6916c8f
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 16:38:38 2013 +1000

    target-i386: Tidy cpu_regs initialization
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 9baeffa..5a594b9 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7823,6 +7823,37 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
 void optimize_flags_init(void)
 {
+    static const char reg_names[CPU_NB_REGS][4] = {
+#ifdef TARGET_X86_64
+        [R_EAX] = "rax",
+        [R_EBX] = "rbx",
+        [R_ECX] = "rcx",
+        [R_EDX] = "rdx",
+        [R_ESI] = "rsi",
+        [R_EDI] = "rdi",
+        [R_EBP] = "rbp",
+        [R_ESP] = "rsp",
+        [8]  = "r8",
+        [9]  = "r9",
+        [10] = "r10",
+        [11] = "r11",
+        [12] = "r12",
+        [13] = "r13",
+        [14] = "r14",
+        [15] = "r15",
+#else
+        [R_EAX] = "eax",
+        [R_EBX] = "ebx",
+        [R_ECX] = "ecx",
+        [R_EDX] = "edx",
+        [R_ESI] = "esi",
+        [R_EDI] = "edi",
+        [R_EBP] = "ebp",
+        [R_ESP] = "esp",
+#endif
+    };
+    int i;
+
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
     cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
                                        offsetof(CPUX86State, cc_op), "cc_op");
@@ -7833,57 +7864,11 @@ void optimize_flags_init(void)
     cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
                                      "cc_src2");
 
-#ifdef TARGET_X86_64
-    cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EAX]), "rax");
-    cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ECX]), "rcx");
-    cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EDX]), "rdx");
-    cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EBX]), "rbx");
-    cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ESP]), "rsp");
-    cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EBP]), "rbp");
-    cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ESI]), "rsi");
-    cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EDI]), "rdi");
-    cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
-                                         offsetof(CPUX86State, regs[8]), "r8");
-    cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[9]), "r9");
-    cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[10]), "r10");
-    cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[11]), "r11");
-    cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[12]), "r12");
-    cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[13]), "r13");
-    cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[14]), "r14");
-    cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
-                                          offsetof(CPUX86State, regs[15]), "r15");
-#else
-    cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EAX]), "eax");
-    cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ECX]), "ecx");
-    cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EDX]), "edx");
-    cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EBX]), "ebx");
-    cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ESP]), "esp");
-    cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EBP]), "ebp");
-    cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_ESI]), "esi");
-    cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
-                                             offsetof(CPUX86State, regs[R_EDI]), "edi");
-#endif
+    for (i = 0; i < CPU_NB_REGS; ++i) {
+        cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
+                                         offsetof(CPUX86State, regs[i]),
+                                         reg_names[i]);
+    }
 }
 
 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
commit 8e31d234b224634729d02b58a8faf364a574e5d7
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 13:57:45 2013 +1000

    target_i386: Clean up gen_pop_T0
    
    Reduce ifdefs, share more code between paths, reduce the number of TCG
    ops generated.  Avoid re-computing the size of the operation across
    gen_pop_T0 and gen_pop_update.
    
    Add forgotten zero-extension in the TARGET_X86_64, !CODE64, ss32 case.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 589c90c..9baeffa 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2417,30 +2417,30 @@ static void gen_push_v(DisasContext *s, TCGv val)
 }
 
 /* two step pop is necessary for precise exceptions */
-static void gen_pop_T0(DisasContext *s)
+static TCGMemOp gen_pop_T0(DisasContext *s)
 {
-#ifdef TARGET_X86_64
+    TCGMemOp d_ot = mo_pushpop(s, s->dflag);
+    TCGv addr = cpu_A0;
+
     if (CODE64(s)) {
-        gen_op_movq_A0_reg(R_ESP);
-        gen_op_ld_v(s, mo_pushpop(s, s->dflag), cpu_T[0], cpu_A0);
-    } else
-#endif
-    {
-        gen_op_movl_A0_reg(R_ESP);
-        if (s->ss32) {
-            if (s->addseg)
-                gen_op_addl_A0_seg(s, R_SS);
-        } else {
-            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-            gen_op_addl_A0_seg(s, R_SS);
-        }
-        gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
+        addr = cpu_regs[R_ESP];
+    } else if (!s->ss32) {
+        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESP]);
+        gen_op_addl_A0_seg(s, R_SS);
+    } else if (s->addseg) {
+        tcg_gen_mov_tl(cpu_A0, cpu_regs[R_ESP]);
+        gen_op_addl_A0_seg(s, R_SS);
+    } else {
+        tcg_gen_ext32u_tl(cpu_A0, cpu_regs[R_ESP]);
     }
+
+    gen_op_ld_v(s, d_ot, cpu_T[0], addr);
+    return d_ot;
 }
 
-static void gen_pop_update(DisasContext *s)
+static void gen_pop_update(DisasContext *s, TCGMemOp ot)
 {
-    gen_stack_update(s, 1 << mo_pushpop(s, s->dflag));
+    gen_stack_update(s, 1 << ot);
 }
 
 static void gen_stack_A0(DisasContext *s)
@@ -5237,10 +5237,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_push_v(s, cpu_T[0]);
         break;
     case 0x58 ... 0x5f: /* pop */
-        ot = mo_pushpop(s, dflag);
-        gen_pop_T0(s);
+        ot = gen_pop_T0(s);
         /* NOTE: order is important for pop %sp */
-        gen_pop_update(s);
+        gen_pop_update(s, ot);
         gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
         break;
     case 0x60: /* pusha */
@@ -5264,13 +5263,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_push_v(s, cpu_T[0]);
         break;
     case 0x8f: /* pop Ev */
-        ot = mo_pushpop(s, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
-        gen_pop_T0(s);
+        ot = gen_pop_T0(s);
         if (mod == 3) {
             /* NOTE: order is important for pop %sp */
-            gen_pop_update(s);
+            gen_pop_update(s, ot);
             rm = (modrm & 7) | REX_B(s);
             gen_op_mov_reg_T0(ot, rm);
         } else {
@@ -5278,7 +5276,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             s->popl_esp_hack = 1 << ot;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             s->popl_esp_hack = 0;
-            gen_pop_update(s);
+            gen_pop_update(s, ot);
         }
         break;
     case 0xc8: /* enter */
@@ -5302,10 +5300,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_TN_reg(MO_16, 0, R_EBP);
             gen_op_mov_reg_T0(MO_16, R_ESP);
         }
-        gen_pop_T0(s);
-        ot = mo_pushpop(s, dflag);
+        ot = gen_pop_T0(s);
         gen_op_mov_reg_T0(ot, R_EBP);
-        gen_pop_update(s);
+        gen_pop_update(s, ot);
         break;
     case 0x06: /* push es */
     case 0x0e: /* push cs */
@@ -5327,9 +5324,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s))
             goto illegal_op;
         reg = b >> 3;
-        gen_pop_T0(s);
+        ot = gen_pop_T0(s);
         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
-        gen_pop_update(s);
+        gen_pop_update(s, ot);
         if (reg == R_SS) {
             /* if reg == SS, inhibit interrupts/trace. */
             /* If several instructions disable interrupts, only the
@@ -5345,9 +5342,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x1a1: /* pop fs */
     case 0x1a9: /* pop gs */
-        gen_pop_T0(s);
+        ot = gen_pop_T0(s);
         gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
-        gen_pop_update(s);
+        gen_pop_update(s, ot);
         if (s->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
@@ -6383,23 +6380,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xc2: /* ret im */
         val = cpu_ldsw_code(env, s->pc);
         s->pc += 2;
-        gen_pop_T0(s);
-        if (CODE64(s) && dflag != MO_16) {
-            dflag = MO_64;
-        }
-        gen_stack_update(s, val + (1 << dflag));
-        if (dflag == MO_16) {
-            tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
-        }
+        ot = gen_pop_T0(s);
+        gen_stack_update(s, val + (1 << ot));
+        /* Note that gen_pop_T0 uses a zero-extending load.  */
         gen_op_jmp_T0();
         gen_eob(s);
         break;
     case 0xc3: /* ret */
-        gen_pop_T0(s);
-        gen_pop_update(s);
-        if (dflag == MO_16) {
-            tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
-        }
+        ot = gen_pop_T0(s);
+        gen_pop_update(s, ot);
+        /* Note that gen_pop_T0 uses a zero-extending load.  */
         gen_op_jmp_T0();
         gen_eob(s);
         break;
@@ -6572,7 +6562,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (s->vm86 && s->iopl != 3) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
         } else {
-            gen_pop_T0(s);
+            ot = gen_pop_T0(s);
             if (s->cpl == 0) {
                 if (dflag != MO_16) {
                     gen_helper_write_eflags(cpu_env, cpu_T[0],
@@ -6618,7 +6608,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     }
                 }
             }
-            gen_pop_update(s);
+            gen_pop_update(s, ot);
             set_cc_op(s, CC_OP_EFLAGS);
             /* abort translation because TF/AC flag may change */
             gen_jmp_im(s->pc - s->cs_base);
commit 432baffe15c18af576232f22ada2f4dec88ad74a
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 13:19:04 2013 +1000

    target-i386: Combine gen_push_T* into gen_push_v
    
    Reduce ifdefs, share more code between paths, reduce the number of TCG
    ops generated.
    
    Add forgotten zero-extension in the TARGET_X86_64, !CODE64, ss32 case.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8673f95..589c90c 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2384,78 +2384,36 @@ static inline void gen_stack_update(DisasContext *s, int addend)
     }
 }
 
-/* generate a push. It depends on ss32, addseg and dflag */
-static void gen_push_T0(DisasContext *s)
+/* Generate a push. It depends on ss32, addseg and dflag.  */
+static void gen_push_v(DisasContext *s, TCGv val)
 {
-#ifdef TARGET_X86_64
-    if (CODE64(s)) {
-        gen_op_movq_A0_reg(R_ESP);
-        if (s->dflag != MO_16) {
-            gen_op_addq_A0_im(-8);
-            gen_op_st_v(s, MO_64, cpu_T[0], cpu_A0);
-        } else {
-            gen_op_addq_A0_im(-2);
-            gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
-        }
-        gen_op_mov_reg_A0(MO_64, R_ESP);
-    } else
-#endif
-    {
-        gen_op_movl_A0_reg(R_ESP);
-        gen_op_addl_A0_im(-1 << s->dflag);
-        if (s->ss32) {
-            if (s->addseg) {
-                tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-                gen_op_addl_A0_seg(s, R_SS);
-            }
-        } else {
-            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-            tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-            gen_op_addl_A0_seg(s, R_SS);
-        }
-        gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
-        if (s->ss32 && !s->addseg)
-            gen_op_mov_reg_A0(MO_32, R_ESP);
-        else
-            gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
-    }
-}
+    TCGMemOp a_ot, d_ot = mo_pushpop(s, s->dflag);
+    int size = 1 << d_ot;
+    TCGv new_esp = cpu_A0;
+
+    tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
 
-/* generate a push. It depends on ss32, addseg and dflag */
-/* slower version for T1, only used for call Ev */
-static void gen_push_T1(DisasContext *s)
-{
-#ifdef TARGET_X86_64
     if (CODE64(s)) {
-        gen_op_movq_A0_reg(R_ESP);
-        if (s->dflag != MO_16) {
-            gen_op_addq_A0_im(-8);
-            gen_op_st_v(s, MO_64, cpu_T[1], cpu_A0);
-        } else {
-            gen_op_addq_A0_im(-2);
-            gen_op_st_v(s, MO_16, cpu_T[1], cpu_A0);
-        }
-        gen_op_mov_reg_A0(MO_64, R_ESP);
-    } else
-#endif
-    {
-        gen_op_movl_A0_reg(R_ESP);
-        gen_op_addl_A0_im(-1 << s->dflag);
-        if (s->ss32) {
-            if (s->addseg) {
-                gen_op_addl_A0_seg(s, R_SS);
-            }
-        } else {
-            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
+        a_ot = MO_64;
+    } else if (s->ss32) {
+        a_ot = MO_32;
+        if (s->addseg) {
+            new_esp = cpu_tmp4;
+            tcg_gen_mov_tl(new_esp, cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
+        } else {
+            tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
-        gen_op_st_v(s, s->dflag, cpu_T[1], cpu_A0);
-
-        if (s->ss32 && !s->addseg)
-            gen_op_mov_reg_A0(MO_32, R_ESP);
-        else
-            gen_stack_update(s, -1 << s->dflag);
+    } else {
+        a_ot = MO_16;
+        new_esp = cpu_tmp4;
+        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
+        tcg_gen_mov_tl(new_esp, cpu_A0);
+        gen_op_addl_A0_seg(s, R_SS);
     }
+
+    gen_op_st_v(s, d_ot, val, cpu_A0);
+    gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
 }
 
 /* two step pop is necessary for precise exceptions */
@@ -4984,7 +4942,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
             next_eip = s->pc - s->cs_base;
             tcg_gen_movi_tl(cpu_T[1], next_eip);
-            gen_push_T1(s);
+            gen_push_v(s, cpu_T[1]);
             gen_op_jmp_T0();
             gen_eob(s);
             break;
@@ -5034,7 +4992,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_eob(s);
             break;
         case 6: /* push Ev */
-            gen_push_T0(s);
+            gen_push_v(s, cpu_T[0]);
             break;
         default:
             goto illegal_op;
@@ -5276,7 +5234,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /* push/pop */
     case 0x50 ... 0x57: /* push */
         gen_op_mov_TN_reg(MO_32, 0, (b & 7) | REX_B(s));
-        gen_push_T0(s);
+        gen_push_v(s, cpu_T[0]);
         break;
     case 0x58 ... 0x5f: /* pop */
         ot = mo_pushpop(s, dflag);
@@ -5303,7 +5261,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         else
             val = (int8_t)insn_get(env, s, MO_8);
         tcg_gen_movi_tl(cpu_T[0], val);
-        gen_push_T0(s);
+        gen_push_v(s, cpu_T[0]);
         break;
     case 0x8f: /* pop Ev */
         ot = mo_pushpop(s, dflag);
@@ -5356,12 +5314,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s))
             goto illegal_op;
         gen_op_movl_T0_seg(b >> 3);
-        gen_push_T0(s);
+        gen_push_v(s, cpu_T[0]);
         break;
     case 0x1a0: /* push fs */
     case 0x1a8: /* push gs */
         gen_op_movl_T0_seg((b >> 3) & 7);
-        gen_push_T0(s);
+        gen_push_v(s, cpu_T[0]);
         break;
     case 0x07: /* pop es */
     case 0x17: /* pop ss */
@@ -6510,7 +6468,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tval &= 0xffffffff;
             }
             tcg_gen_movi_tl(cpu_T[0], next_eip);
-            gen_push_T0(s);
+            gen_push_v(s, cpu_T[0]);
             gen_jmp(s, tval);
         }
         break;
@@ -6606,7 +6564,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_update_cc_op(s);
             gen_helper_read_eflags(cpu_T[0], cpu_env);
-            gen_push_T0(s);
+            gen_push_v(s, cpu_T[0]);
         }
         break;
     case 0x9d: /* popf */
commit 7effd62514fa42c3c6c9be15a97c98a5f76748b7
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 11:34:38 2013 +1000

    target-i386: Tidy addr16 code in gen_lea_modrm
    
    Unlike the addr32, there was no bug.  But we can use the same
    technique to reduce the number of TCG ops.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 9f38adf..8673f95 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2028,51 +2028,49 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             break;
         default:
         case 2:
-            disp = cpu_lduw_code(env, s->pc);
+            disp = (int16_t)cpu_lduw_code(env, s->pc);
             s->pc += 2;
             break;
         }
-        switch(rm) {
+
+        sum = cpu_A0;
+        switch (rm) {
         case 0:
-            gen_op_movl_A0_reg(R_EBX);
-            gen_op_addl_A0_reg_sN(0, R_ESI);
+            tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
             break;
         case 1:
-            gen_op_movl_A0_reg(R_EBX);
-            gen_op_addl_A0_reg_sN(0, R_EDI);
+            tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_EDI]);
             break;
         case 2:
-            gen_op_movl_A0_reg(R_EBP);
-            gen_op_addl_A0_reg_sN(0, R_ESI);
+            tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
             break;
         case 3:
-            gen_op_movl_A0_reg(R_EBP);
-            gen_op_addl_A0_reg_sN(0, R_EDI);
+            tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
             break;
         case 4:
-            gen_op_movl_A0_reg(R_ESI);
+            sum = cpu_regs[R_ESI];
             break;
         case 5:
-            gen_op_movl_A0_reg(R_EDI);
+            sum = cpu_regs[R_EDI];
             break;
         case 6:
-            gen_op_movl_A0_reg(R_EBP);
+            sum = cpu_regs[R_EBP];
             break;
         default:
         case 7:
-            gen_op_movl_A0_reg(R_EBX);
+            sum = cpu_regs[R_EBX];
             break;
         }
-        if (disp != 0)
-            gen_op_addl_A0_im(disp);
+        tcg_gen_addi_tl(cpu_A0, sum, disp);
         tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     no_rm:
         if (must_add_seg) {
             if (override < 0) {
-                if (rm == 2 || rm == 3 || rm == 6)
+                if (rm == 2 || rm == 3 || rm == 6) {
                     override = R_SS;
-                else
+                } else {
                     override = R_DS;
+                }
             }
             gen_op_addl_A0_seg(s, override);
         }
commit ab4e4aec78657138312948359055e20f6266bd17
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 09:37:57 2013 +1000

    target-i386: Change dflag to TCGMemOp
    
    Changing the domain to TCGMemOp makes it easier to interoperate
    with other portions of the rest of the translator.
    
    We now only have one domain for size operands inside the translator,
    which makes things less confusing all the way around.  There are
    still a number of helpers that continue to use the log2-1 domain.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 9b191ad..9f38adf 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -86,7 +86,7 @@ typedef struct DisasContext {
     int override; /* -1 if no override */
     int prefix;
     TCGMemOp aflag;
-    int dflag;
+    TCGMemOp dflag;
     target_ulong pc; /* pc = eip + cs_base */
     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
                    static state change (stop translation) */
@@ -296,6 +296,40 @@ static inline bool byte_reg_is_xH(int reg)
     return true;
 }
 
+/* Select the size of a push/pop operation.  */
+static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
+{
+    if (CODE64(s)) {
+        return ot == MO_16 ? MO_16 : MO_64;
+    } else {
+        return ot;
+    }
+}
+
+/* Select only size 64 else 32.  Used for SSE operand sizes.  */
+static inline TCGMemOp mo_64_32(TCGMemOp ot)
+{
+#ifdef TARGET_X86_64
+    return ot == MO_64 ? MO_64 : MO_32;
+#else
+    return MO_32;
+#endif
+}
+
+/* Select size 8 if lsb of B is clear, else OT.  Used for decoding
+   byte vs word opcodes.  */
+static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
+{
+    return b & 1 ? ot : MO_8;
+}
+
+/* Select size 8 if lsb of B is clear, else OT capped at 32.
+   Used for decoding operand size of port opcodes.  */
+static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
+{
+    return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
+}
+
 static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
 {
     switch(ot) {
@@ -2358,7 +2392,7 @@ static void gen_push_T0(DisasContext *s)
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
         gen_op_movq_A0_reg(R_ESP);
-        if (s->dflag) {
+        if (s->dflag != MO_16) {
             gen_op_addq_A0_im(-8);
             gen_op_st_v(s, MO_64, cpu_T[0], cpu_A0);
         } else {
@@ -2370,10 +2404,7 @@ static void gen_push_T0(DisasContext *s)
 #endif
     {
         gen_op_movl_A0_reg(R_ESP);
-        if (!s->dflag)
-            gen_op_addl_A0_im(-2);
-        else
-            gen_op_addl_A0_im(-4);
+        gen_op_addl_A0_im(-1 << s->dflag);
         if (s->ss32) {
             if (s->addseg) {
                 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
@@ -2384,7 +2415,7 @@ static void gen_push_T0(DisasContext *s)
             tcg_gen_mov_tl(cpu_T[1], cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_st_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
+        gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
         if (s->ss32 && !s->addseg)
             gen_op_mov_reg_A0(MO_32, R_ESP);
         else
@@ -2399,7 +2430,7 @@ static void gen_push_T1(DisasContext *s)
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
         gen_op_movq_A0_reg(R_ESP);
-        if (s->dflag) {
+        if (s->dflag != MO_16) {
             gen_op_addq_A0_im(-8);
             gen_op_st_v(s, MO_64, cpu_T[1], cpu_A0);
         } else {
@@ -2411,10 +2442,7 @@ static void gen_push_T1(DisasContext *s)
 #endif
     {
         gen_op_movl_A0_reg(R_ESP);
-        if (!s->dflag)
-            gen_op_addl_A0_im(-2);
-        else
-            gen_op_addl_A0_im(-4);
+        gen_op_addl_A0_im(-1 << s->dflag);
         if (s->ss32) {
             if (s->addseg) {
                 gen_op_addl_A0_seg(s, R_SS);
@@ -2423,12 +2451,12 @@ static void gen_push_T1(DisasContext *s)
             tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_st_v(s, s->dflag + 1, cpu_T[1], cpu_A0);
+        gen_op_st_v(s, s->dflag, cpu_T[1], cpu_A0);
 
         if (s->ss32 && !s->addseg)
             gen_op_mov_reg_A0(MO_32, R_ESP);
         else
-            gen_stack_update(s, (-2) << s->dflag);
+            gen_stack_update(s, -1 << s->dflag);
     }
 }
 
@@ -2438,7 +2466,7 @@ static void gen_pop_T0(DisasContext *s)
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
         gen_op_movq_A0_reg(R_ESP);
-        gen_op_ld_v(s, s->dflag ? MO_64 : MO_16, cpu_T[0], cpu_A0);
+        gen_op_ld_v(s, mo_pushpop(s, s->dflag), cpu_T[0], cpu_A0);
     } else
 #endif
     {
@@ -2450,20 +2478,13 @@ static void gen_pop_T0(DisasContext *s)
             tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_ld_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
+        gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
     }
 }
 
 static void gen_pop_update(DisasContext *s)
 {
-#ifdef TARGET_X86_64
-    if (CODE64(s) && s->dflag) {
-        gen_stack_update(s, 8);
-    } else
-#endif
-    {
-        gen_stack_update(s, 2 << s->dflag);
-    }
+    gen_stack_update(s, 1 << mo_pushpop(s, s->dflag));
 }
 
 static void gen_stack_A0(DisasContext *s)
@@ -2481,7 +2502,7 @@ static void gen_pusha(DisasContext *s)
 {
     int i;
     gen_op_movl_A0_reg(R_ESP);
-    gen_op_addl_A0_im(-16 <<  s->dflag);
+    gen_op_addl_A0_im(-8 << s->dflag);
     if (!s->ss32)
         tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
@@ -2489,8 +2510,8 @@ static void gen_pusha(DisasContext *s)
         gen_op_addl_A0_seg(s, R_SS);
     for(i = 0;i < 8; i++) {
         gen_op_mov_TN_reg(MO_32, 0, 7 - i);
-        gen_op_st_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
-        gen_op_addl_A0_im(2 <<  s->dflag);
+        gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
+        gen_op_addl_A0_im(1 << s->dflag);
     }
     gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
 }
@@ -2503,31 +2524,28 @@ static void gen_popa(DisasContext *s)
     if (!s->ss32)
         tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-    tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 <<  s->dflag);
+    tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 8 << s->dflag);
     if (s->addseg)
         gen_op_addl_A0_seg(s, R_SS);
     for(i = 0;i < 8; i++) {
         /* ESP is not reloaded */
         if (i != 3) {
-            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
-            gen_op_mov_reg_T0(MO_16 + s->dflag, 7 - i);
+            gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
+            gen_op_mov_reg_T0(s->dflag, 7 - i);
         }
-        gen_op_addl_A0_im(2 <<  s->dflag);
+        gen_op_addl_A0_im(1 << s->dflag);
     }
     gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
 }
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
 {
-    TCGMemOp ot;
-    int opsize;
+    TCGMemOp ot = mo_pushpop(s, s->dflag);
+    int opsize = 1 << ot;
 
     level &= 0x1f;
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        ot = s->dflag ? MO_64 : MO_16;
-        opsize = 1 << ot;
-
         gen_op_movl_A0_reg(R_ESP);
         gen_op_addq_A0_im(-opsize);
         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
@@ -2547,9 +2565,6 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
     } else
 #endif
     {
-        ot = s->dflag + MO_16;
-        opsize = 2 << s->dflag;
-
         gen_op_movl_A0_reg(R_ESP);
         gen_op_addl_A0_im(-opsize);
         if (!s->ss32)
@@ -2563,7 +2578,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         if (level) {
             /* XXX: must save state */
             gen_helper_enter_level(cpu_env, tcg_const_i32(level),
-                                   tcg_const_i32(s->dflag),
+                                   tcg_const_i32(s->dflag - 1),
                                    cpu_T[1]);
         }
         gen_op_mov_reg_T1(ot, R_EBP);
@@ -3137,7 +3152,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x6e: /* movd mm, ea */
 #ifdef TARGET_X86_64
-            if (s->dflag == 2) {
+            if (s->dflag == MO_64) {
                 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
                 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
             } else
@@ -3152,7 +3167,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x16e: /* movd xmm, ea */
 #ifdef TARGET_X86_64
-            if (s->dflag == 2) {
+            if (s->dflag == MO_64) {
                 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg]));
@@ -3317,7 +3332,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x7e: /* movd ea, mm */
 #ifdef TARGET_X86_64
-            if (s->dflag == 2) {
+            if (s->dflag == MO_64) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,fpregs[reg].mmx));
                 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
@@ -3331,7 +3346,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x17e: /* movd ea, xmm */
 #ifdef TARGET_X86_64
-            if (s->dflag == 2) {
+            if (s->dflag == MO_64) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
                 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
@@ -3501,7 +3516,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x22a: /* cvtsi2ss */
         case 0x32a: /* cvtsi2sd */
-            ot = (s->dflag == 2) ? MO_64 : MO_32;
+            ot = mo_64_32(s->dflag);
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
@@ -3553,7 +3568,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x32c: /* cvttsd2si */
         case 0x22d: /* cvtss2si */
         case 0x32d: /* cvtsd2si */
-            ot = (s->dflag == 2) ? MO_64 : MO_32;
+            ot = mo_64_32(s->dflag);
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm);
                 if ((b >> 8) & 1) {
@@ -3603,7 +3618,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x1c5:
             if (mod != 3)
                 goto illegal_op;
-            ot = (s->dflag == 2) ? MO_64 : MO_32;
+            ot = mo_64_32(s->dflag);
             val = cpu_ldub_code(env, s->pc++);
             if (b1) {
                 val &= 7;
@@ -3756,7 +3771,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 }
                 if ((b & 0xff) == 0xf0) {
                     ot = MO_8;
-                } else if (s->dflag != 2) {
+                } else if (s->dflag != MO_64) {
                     ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
                 } else {
                     ot = MO_64;
@@ -3767,7 +3782,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
                                  cpu_T[0], tcg_const_i32(8 << ot));
 
-                ot = (s->dflag == 2) ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_op_mov_reg_T0(ot, reg);
                 break;
 
@@ -3785,7 +3800,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
                     goto illegal_op;
                 }
-                if (s->dflag != 2) {
+                if (s->dflag != MO_64) {
                     ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
                 } else {
                     ot = MO_64;
@@ -3808,7 +3823,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
                 gen_op_mov_reg_T0(ot, reg);
@@ -3822,7 +3837,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 {
                     TCGv bound, zero;
 
@@ -3862,7 +3877,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
                 {
@@ -3889,7 +3904,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 switch (ot) {
                 default:
@@ -3915,11 +3930,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 /* Note that by zero-extending the mask operand, we
                    automatically handle zero-extending the result.  */
-                if (s->dflag == 2) {
+                if (ot == MO_64) {
                     tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
                 } else {
                     tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
@@ -3933,11 +3948,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 /* Note that by zero-extending the mask operand, we
                    automatically handle zero-extending the result.  */
-                if (s->dflag == 2) {
+                if (ot == MO_64) {
                     tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
                 } else {
                     tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
@@ -3953,7 +3968,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     TCGv carry_in, carry_out, zero;
                     int end_op;
 
-                    ot = (s->dflag == 2 ? MO_64 : MO_32);
+                    ot = mo_64_32(s->dflag);
                     gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
 
                     /* Re-use the carry-out from a previous round.  */
@@ -4032,7 +4047,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = (s->dflag == 2 ? MO_64 : MO_32);
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 if (ot == MO_64) {
                     tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
@@ -4064,7 +4079,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
 
                 switch (reg & 7) {
@@ -4121,7 +4136,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 goto illegal_op;
 
             if (sse_fn_eppi == SSE_SPECIAL) {
-                ot = (s->dflag == 2) ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3)
                     gen_lea_modrm(env, s, modrm);
@@ -4279,9 +4294,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
                 set_cc_op(s, CC_OP_EFLAGS);
 
-                if (s->dflag == 2)
+                if (s->dflag == MO_64) {
                     /* The helper must use entire 64-bit gp registers */
                     val |= 1 << 8;
+                }
             }
 
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
@@ -4302,7 +4318,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? MO_64 : MO_32;
+                ot = mo_64_32(s->dflag);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 b = cpu_ldub_code(env, s->pc++);
                 if (ot == MO_64) {
@@ -4433,9 +4449,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                target_ulong pc_start)
 {
-    int b, prefixes, dflag;
+    int b, prefixes;
     int shift;
-    TCGMemOp ot, aflag;
+    TCGMemOp ot, aflag, dflag;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
@@ -4571,14 +4587,15 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /* In 64-bit mode, the default data size is 32-bit.  Select 64-bit
            data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
            over 0x66 if both are present.  */
-        dflag = (rex_w > 0 ? 2 : prefixes & PREFIX_DATA ? 0 : 1);
+        dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
         /* In 64-bit mode, 0x67 selects 32-bit addressing.  */
         aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
     } else {
         /* In 16/32-bit mode, 0x66 selects the opposite data size.  */
-        dflag = s->code32;
-        if (prefixes & PREFIX_DATA) {
-            dflag ^= 1;
+        if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
+            dflag = MO_32;
+        } else {
+            dflag = MO_16;
         }
         /* In 16/32-bit mode, 0x67 selects the opposite addressing.  */
         if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
@@ -4620,10 +4637,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             op = (b >> 3) & 7;
             f = (b >> 1) & 3;
 
-            if ((b & 1) == 0)
-                ot = MO_8;
-            else
-                ot = dflag + MO_16;
+            ot = mo_b_d(b, dflag);
 
             switch(f) {
             case 0: /* OP Ev, Gv */
@@ -4680,10 +4694,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         {
             int val;
 
-            if ((b & 1) == 0)
-                ot = MO_8;
-            else
-                ot = dflag + MO_16;
+            ot = mo_b_d(b, dflag);
 
             modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
@@ -4720,19 +4731,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /**************************/
         /* inc, dec, and other misc arith */
     case 0x40 ... 0x47: /* inc Gv */
-        ot = dflag ? MO_32 : MO_16;
+        ot = dflag;
         gen_inc(s, ot, OR_EAX + (b & 7), 1);
         break;
     case 0x48 ... 0x4f: /* dec Gv */
-        ot = dflag ? MO_32 : MO_16;
+        ot = dflag;
         gen_inc(s, ot, OR_EAX + (b & 7), -1);
         break;
     case 0xf6: /* GRP3 */
     case 0xf7:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
 
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
@@ -4928,10 +4936,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xfe: /* GRP4 */
     case 0xff: /* GRP5 */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
 
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
@@ -4945,10 +4950,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 /* operand size for jumps is 64 bit */
                 ot = MO_64;
             } else if (op == 3 || op == 5) {
-                ot = dflag ? MO_32 + (rex_w == 1) : MO_16;
+                ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
             } else if (op == 6) {
                 /* default push size is 64 bit */
-                ot = dflag ? MO_64 : MO_16;
+                ot = mo_pushpop(s, dflag);
             }
         }
         if (mod != 3) {
@@ -4976,7 +4981,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 2: /* call Ev */
             /* XXX: optimize if memory (no 'and' is necessary) */
-            if (s->dflag == 0) {
+            if (dflag == MO_16) {
                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
             }
             next_eip = s->pc - s->cs_base;
@@ -4995,18 +5000,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_jmp_im(pc_start - s->cs_base);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
-                                           tcg_const_i32(dflag),
+                                           tcg_const_i32(dflag - 1),
                                            tcg_const_i32(s->pc - pc_start));
             } else {
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
-                                      tcg_const_i32(dflag),
+                                      tcg_const_i32(dflag - 1),
                                       tcg_const_i32(s->pc - s->cs_base));
             }
             gen_eob(s);
             break;
         case 4: /* jmp Ev */
-            if (s->dflag == 0) {
+            if (dflag == MO_16) {
                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
             }
             gen_op_jmp_T0();
@@ -5040,10 +5045,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0x84: /* test Ev, Gv */
     case 0x85:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
 
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
@@ -5056,10 +5058,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xa8: /* test eAX, Iv */
     case 0xa9:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         val = insn_get(env, s, ot);
 
         gen_op_mov_TN_reg(ot, 0, OR_EAX);
@@ -5069,47 +5068,57 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
 
     case 0x98: /* CWDE/CBW */
+        switch (dflag) {
 #ifdef TARGET_X86_64
-        if (dflag == 2) {
+        case MO_64:
             gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_T0(MO_64, R_EAX);
-        } else
+            break;
 #endif
-        if (dflag == 1) {
+        case MO_32:
             gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_T0(MO_32, R_EAX);
-        } else {
+            break;
+        case MO_16:
             gen_op_mov_TN_reg(MO_8, 0, R_EAX);
             tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_T0(MO_16, R_EAX);
+            break;
+        default:
+            tcg_abort();
         }
         break;
     case 0x99: /* CDQ/CWD */
+        switch (dflag) {
 #ifdef TARGET_X86_64
-        if (dflag == 2) {
+        case MO_64:
             gen_op_mov_TN_reg(MO_64, 0, R_EAX);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
             gen_op_mov_reg_T0(MO_64, R_EDX);
-        } else
+            break;
 #endif
-        if (dflag == 1) {
+        case MO_32:
             gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
             gen_op_mov_reg_T0(MO_32, R_EDX);
-        } else {
+            break;
+        case MO_16:
             gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
             gen_op_mov_reg_T0(MO_16, R_EDX);
+            break;
+        default:
+            tcg_abort();
         }
         break;
     case 0x1af: /* imul Gv, Ev */
     case 0x69: /* imul Gv, Ev, I */
     case 0x6b:
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         if (b == 0x69)
@@ -5161,10 +5170,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x1c0:
     case 0x1c1: /* xadd Ev, Gv */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5192,10 +5198,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             int label1, label2;
             TCGv t0, t1, t2, a0;
 
-            if ((b & 1) == 0)
-                ot = MO_8;
-            else
-                ot = dflag + MO_16;
+            ot = mo_b_d(b, dflag);
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -5251,7 +5254,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if ((mod == 3) || ((modrm & 0x38) != 0x8))
             goto illegal_op;
 #ifdef TARGET_X86_64
-        if (dflag == 2) {
+        if (dflag == MO_64) {
             if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
                 goto illegal_op;
             gen_jmp_im(pc_start - s->cs_base);
@@ -5278,11 +5281,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_push_T0(s);
         break;
     case 0x58 ... 0x5f: /* pop */
-        if (CODE64(s)) {
-            ot = dflag ? MO_64 : MO_16;
-        } else {
-            ot = dflag + MO_16;
-        }
+        ot = mo_pushpop(s, dflag);
         gen_pop_T0(s);
         /* NOTE: order is important for pop %sp */
         gen_pop_update(s);
@@ -5300,11 +5299,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x68: /* push Iv */
     case 0x6a:
-        if (CODE64(s)) {
-            ot = dflag ? MO_64 : MO_16;
-        } else {
-            ot = dflag + MO_16;
-        }
+        ot = mo_pushpop(s, dflag);
         if (b == 0x68)
             val = insn_get(env, s, ot);
         else
@@ -5313,11 +5308,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_push_T0(s);
         break;
     case 0x8f: /* pop Ev */
-        if (CODE64(s)) {
-            ot = dflag ? MO_64 : MO_16;
-        } else {
-            ot = dflag + MO_16;
-        }
+        ot = mo_pushpop(s, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         gen_pop_T0(s);
@@ -5356,11 +5347,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_reg_T0(MO_16, R_ESP);
         }
         gen_pop_T0(s);
-        if (CODE64(s)) {
-            ot = dflag ? MO_64 : MO_16;
-        } else {
-            ot = dflag + MO_16;
-        }
+        ot = mo_pushpop(s, dflag);
         gen_op_mov_reg_T0(ot, R_EBP);
         gen_pop_update(s);
         break;
@@ -5415,10 +5402,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /* mov */
     case 0x88:
     case 0x89: /* mov Gv, Ev */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
@@ -5427,10 +5411,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xc6:
     case 0xc7: /* mov Ev, Iv */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod != 3) {
@@ -5447,10 +5428,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x8a:
     case 0x8b: /* mov Ev, Gv */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = MO_16 + dflag;
+        ot = mo_b_d(b, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
@@ -5484,10 +5462,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (reg >= 6)
             goto illegal_op;
         gen_op_movl_T0_seg(reg);
-        if (mod == 3)
-            ot = MO_16 + dflag;
-        else
-            ot = MO_16;
+        ot = mod == 3 ? dflag : MO_16;
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
         break;
 
@@ -5500,7 +5475,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             TCGMemOp s_ot;
 
             /* d_ot is the size of destination */
-            d_ot = dflag + MO_16;
+            d_ot = dflag;
             /* ot is the size of source */
             ot = (b & 1) + MO_8;
             /* s_ot is the sign+size of source */
@@ -5538,7 +5513,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
 
     case 0x8d: /* lea */
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
@@ -5560,10 +5535,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         {
             target_ulong offset_addr;
 
-            if ((b & 1) == 0)
-                ot = MO_8;
-            else
-                ot = dflag + MO_16;
+            ot = mo_b_d(b, dflag);
             switch (s->aflag) {
 #ifdef TARGET_X86_64
             case MO_64:
@@ -5602,7 +5574,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xb8 ... 0xbf: /* mov R, Iv */
 #ifdef TARGET_X86_64
-        if (dflag == 2) {
+        if (dflag == MO_64) {
             uint64_t tmp;
             /* 64 bit case */
             tmp = cpu_ldq_code(env, s->pc);
@@ -5613,7 +5585,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else
 #endif
         {
-            ot = dflag ? MO_32 : MO_16;
+            ot = dflag;
             val = insn_get(env, s, ot);
             reg = (b & 7) | REX_B(s);
             tcg_gen_movi_tl(cpu_T[0], val);
@@ -5623,16 +5595,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0x91 ... 0x97: /* xchg R, EAX */
     do_xchg_reg_eax:
-        ot = dflag + MO_16;
+        ot = dflag;
         reg = (b & 7) | REX_B(s);
         rm = R_EAX;
         goto do_xchg_reg;
     case 0x86:
     case 0x87: /* xchg Ev, Gv */
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5673,7 +5642,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1b5: /* lgs Gv */
         op = R_GS;
     do_lxx:
-        ot = dflag ? MO_32 : MO_16;
+        ot = dflag != MO_16 ? MO_32 : MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5701,11 +5670,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         shift = 2;
     grp2:
         {
-            if ((b & 1) == 0)
-                ot = MO_8;
-            else
-                ot = dflag + MO_16;
-
+            ot = mo_b_d(b, dflag);
             modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
             op = (modrm >> 3) & 7;
@@ -5758,7 +5723,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         op = 1;
         shift = 0;
     do_shiftd:
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
@@ -5922,7 +5887,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x0c: /* fldenv mem */
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
+                gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
                 break;
             case 0x0d: /* fldcw mem */
                 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
@@ -5932,7 +5897,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x0e: /* fnstenv mem */
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
+                gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
                 break;
             case 0x0f: /* fnstcw mem */
                 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
@@ -5953,12 +5918,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x2c: /* frstor mem */
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
+                gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
                 break;
             case 0x2e: /* fnsave mem */
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
-                gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
+                gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
                 break;
             case 0x2f: /* fnstsw mem */
                 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
@@ -6305,11 +6270,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xa4: /* movsS */
     case 0xa5:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
-
+        ot = mo_b_d(b, dflag);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -6319,11 +6280,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xaa: /* stosS */
     case 0xab:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
-
+        ot = mo_b_d(b, dflag);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -6332,10 +6289,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xac: /* lodsS */
     case 0xad:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -6344,10 +6298,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xae: /* scasS */
     case 0xaf:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         if (prefixes & PREFIX_REPNZ) {
             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
         } else if (prefixes & PREFIX_REPZ) {
@@ -6359,10 +6310,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xa6: /* cmpsS */
     case 0xa7:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag + MO_16;
+        ot = mo_b_d(b, dflag);
         if (prefixes & PREFIX_REPNZ) {
             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
         } else if (prefixes & PREFIX_REPZ) {
@@ -6373,10 +6321,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x6c: /* insS */
     case 0x6d:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base, 
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
@@ -6391,10 +6336,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x6e: /* outsS */
     case 0x6f:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes) | 4);
@@ -6413,10 +6355,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0xe4:
     case 0xe5:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         val = cpu_ldub_code(env, s->pc++);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
@@ -6432,10 +6371,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xe6:
     case 0xe7:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         val = cpu_ldub_code(env, s->pc++);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
@@ -6453,10 +6389,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xec:
     case 0xed:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
@@ -6472,10 +6405,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xee:
     case 0xef:
-        if ((b & 1) == 0)
-            ot = MO_8;
-        else
-            ot = dflag ? MO_32 : MO_16;
+        ot = mo_b_d32(b, dflag);
         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
@@ -6498,10 +6428,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         val = cpu_ldsw_code(env, s->pc);
         s->pc += 2;
         gen_pop_T0(s);
-        if (CODE64(s) && s->dflag)
-            s->dflag = 2;
-        gen_stack_update(s, val + (2 << s->dflag));
-        if (s->dflag == 0) {
+        if (CODE64(s) && dflag != MO_16) {
+            dflag = MO_64;
+        }
+        gen_stack_update(s, val + (1 << dflag));
+        if (dflag == MO_16) {
             tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
         }
         gen_op_jmp_T0();
@@ -6510,7 +6441,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xc3: /* ret */
         gen_pop_T0(s);
         gen_pop_update(s);
-        if (s->dflag == 0) {
+        if (dflag == MO_16) {
             tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
         }
         gen_op_jmp_T0();
@@ -6523,21 +6454,21 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (s->pe && !s->vm86) {
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
+            gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
                                       tcg_const_i32(val));
         } else {
             gen_stack_A0(s);
             /* pop offset */
-            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
+            gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
             /* NOTE: keeping EIP updated is not a problem in case of
                exception */
             gen_op_jmp_T0();
             /* pop selector */
-            gen_op_addl_A0_im(2 << s->dflag);
-            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
+            gen_op_addl_A0_im(1 << dflag);
+            gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
             gen_op_movl_seg_T0_vm(R_CS);
             /* add stack offset */
-            gen_stack_update(s, val + (4 << s->dflag));
+            gen_stack_update(s, val + (2 << dflag));
         }
         gen_eob(s);
         break;
@@ -6548,19 +6479,19 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
         if (!s->pe) {
             /* real mode */
-            gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
+            gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
             set_cc_op(s, CC_OP_EFLAGS);
         } else if (s->vm86) {
             if (s->iopl != 3) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
-                gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
+                gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
                 set_cc_op(s, CC_OP_EFLAGS);
             }
         } else {
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
+            gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
                                       tcg_const_i32(s->pc - s->cs_base));
             set_cc_op(s, CC_OP_EFLAGS);
         }
@@ -6568,16 +6499,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xe8: /* call im */
         {
-            if (dflag)
+            if (dflag != MO_16) {
                 tval = (int32_t)insn_get(env, s, MO_32);
-            else
+            } else {
                 tval = (int16_t)insn_get(env, s, MO_16);
+            }
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
-            if (s->dflag == 0)
+            if (dflag == MO_16) {
                 tval &= 0xffff;
-            else if(!CODE64(s))
+            } else if (!CODE64(s)) {
                 tval &= 0xffffffff;
+            }
             tcg_gen_movi_tl(cpu_T[0], next_eip);
             gen_push_T0(s);
             gen_jmp(s, tval);
@@ -6589,7 +6522,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
             if (CODE64(s))
                 goto illegal_op;
-            ot = dflag ? MO_32 : MO_16;
+            ot = dflag;
             offset = insn_get(env, s, ot);
             selector = insn_get(env, s, MO_16);
 
@@ -6598,15 +6531,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         goto do_lcall;
     case 0xe9: /* jmp im */
-        if (dflag)
+        if (dflag != MO_16) {
             tval = (int32_t)insn_get(env, s, MO_32);
-        else
+        } else {
             tval = (int16_t)insn_get(env, s, MO_16);
+        }
         tval += s->pc - s->cs_base;
-        if (s->dflag == 0)
+        if (dflag == MO_16) {
             tval &= 0xffff;
-        else if(!CODE64(s))
+        } else if (!CODE64(s)) {
             tval &= 0xffffffff;
+        }
         gen_jmp(s, tval);
         break;
     case 0xea: /* ljmp im */
@@ -6615,7 +6550,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
             if (CODE64(s))
                 goto illegal_op;
-            ot = dflag ? MO_32 : MO_16;
+            ot = dflag;
             offset = insn_get(env, s, ot);
             selector = insn_get(env, s, MO_16);
 
@@ -6626,15 +6561,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xeb: /* jmp Jb */
         tval = (int8_t)insn_get(env, s, MO_8);
         tval += s->pc - s->cs_base;
-        if (s->dflag == 0)
+        if (dflag == MO_16) {
             tval &= 0xffff;
+        }
         gen_jmp(s, tval);
         break;
     case 0x70 ... 0x7f: /* jcc Jb */
         tval = (int8_t)insn_get(env, s, MO_8);
         goto do_jcc;
     case 0x180 ... 0x18f: /* jcc Jv */
-        if (dflag) {
+        if (dflag != MO_16) {
             tval = (int32_t)insn_get(env, s, MO_32);
         } else {
             tval = (int16_t)insn_get(env, s, MO_16);
@@ -6642,8 +6578,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     do_jcc:
         next_eip = s->pc - s->cs_base;
         tval += next_eip;
-        if (s->dflag == 0)
+        if (dflag == MO_16) {
             tval &= 0xffff;
+        }
         gen_jcc(s, b, tval, next_eip);
         break;
 
@@ -6656,7 +6593,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (!(s->cpuid_features & CPUID_CMOV)) {
             goto illegal_op;
         }
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         gen_cmovcc1(env, s, ot, b, modrm, reg);
@@ -6681,7 +6618,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_pop_T0(s);
             if (s->cpl == 0) {
-                if (s->dflag) {
+                if (dflag != MO_16) {
                     gen_helper_write_eflags(cpu_env, cpu_T[0],
                                             tcg_const_i32((TF_MASK | AC_MASK |
                                                            ID_MASK | NT_MASK |
@@ -6696,7 +6633,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 }
             } else {
                 if (s->cpl <= s->iopl) {
-                    if (s->dflag) {
+                    if (dflag != MO_16) {
                         gen_helper_write_eflags(cpu_env, cpu_T[0],
                                                 tcg_const_i32((TF_MASK |
                                                                AC_MASK |
@@ -6713,7 +6650,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                                               & 0xffff));
                     }
                 } else {
-                    if (s->dflag) {
+                    if (dflag != MO_16) {
                         gen_helper_write_eflags(cpu_env, cpu_T[0],
                                            tcg_const_i32((TF_MASK | AC_MASK |
                                                           ID_MASK | NT_MASK)));
@@ -6773,7 +6710,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /************************/
         /* bit operations */
     case 0x1ba: /* bt/bts/btr/btc Gv, im */
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         op = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
@@ -6804,7 +6741,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1bb: /* btc */
         op = 3;
     do_btx:
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -6862,7 +6799,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x1bc: /* bsf / tzcnt */
     case 0x1bd: /* bsr / lzcnt */
-        ot = dflag + MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
@@ -7061,7 +6998,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x62: /* bound */
         if (CODE64(s))
             goto illegal_op;
-        ot = dflag ? MO_32 : MO_16;
+        ot = dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
@@ -7080,7 +7017,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1c8 ... 0x1cf: /* bswap reg */
         reg = (b & 7) | REX_B(s);
 #ifdef TARGET_X86_64
-        if (dflag == 2) {
+        if (dflag == MO_64) {
             gen_op_mov_TN_reg(MO_64, 0, reg);
             tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
             gen_op_mov_reg_T0(MO_64, reg);
@@ -7110,8 +7047,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tval = (int8_t)insn_get(env, s, MO_8);
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
-            if (s->dflag == 0)
+            if (dflag == MO_16) {
                 tval &= 0xffff;
+            }
 
             l1 = gen_new_label();
             l2 = gen_new_label();
@@ -7196,7 +7134,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_sysexit(cpu_env, tcg_const_i32(dflag));
+            gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
             gen_eob(s);
         }
         break;
@@ -7214,7 +7152,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
+            gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
             /* condition codes are modified only in long mode */
             if (s->lma) {
                 set_cc_op(s, CC_OP_EFLAGS);
@@ -7248,9 +7186,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
-            ot = MO_16;
-            if (mod == 3)
-                ot += s->dflag;
+            ot = mod == 3 ? dflag : MO_16;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             break;
         case 2: /* lldt */
@@ -7271,9 +7207,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
-            ot = MO_16;
-            if (mod == 3)
-                ot += s->dflag;
+            ot = mod == 3 ? dflag : MO_16;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
             break;
         case 3: /* ltr */
@@ -7321,7 +7255,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
             gen_add_A0_im(s, 2);
             tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
-            if (s->dflag == 0) {
+            if (dflag == MO_16) {
                 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
             }
             gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
@@ -7377,7 +7311,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 gen_add_A0_im(s, 2);
                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
-                if (s->dflag == 0) {
+                if (dflag == MO_16) {
                     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
                 }
                 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
@@ -7479,7 +7413,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
                 gen_add_A0_im(s, 2);
                 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
-                if (s->dflag == 0) {
+                if (dflag == MO_16) {
                     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
                 }
                 if (op == 2) {
@@ -7582,7 +7516,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s)) {
             int d_ot;
             /* d_ot is the size of destination */
-            d_ot = dflag + MO_16;
+            d_ot = dflag;
 
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
@@ -7657,7 +7591,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             TCGv t0;
             if (!s->pe || s->vm86)
                 goto illegal_op;
-            ot = dflag ? MO_32 : MO_16;
+            ot = dflag != MO_16 ? MO_32 : MO_16;
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
@@ -7793,7 +7727,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1c3: /* MOVNTI reg, mem */
         if (!(s->cpuid_features & CPUID_SSE2))
             goto illegal_op;
-        ot = s->dflag == 2 ? MO_64 : MO_32;
+        ot = mo_64_32(dflag);
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
@@ -7818,7 +7752,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_lea_modrm(env, s, modrm);
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
+            gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
             break;
         case 1: /* fxrstor */
             if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
@@ -7831,8 +7765,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_lea_modrm(env, s, modrm);
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            gen_helper_fxrstor(cpu_env, cpu_A0,
-                               tcg_const_i32((s->dflag == 2)));
+            gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
             break;
         case 2: /* ldmxcsr */
         case 3: /* stmxcsr */
@@ -7902,12 +7835,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
-        if (s->prefix & PREFIX_DATA)
+        if (s->prefix & PREFIX_DATA) {
             ot = MO_16;
-        else if (s->dflag != 2)
-            ot = MO_32;
-        else
-            ot = MO_64;
+        } else {
+            ot = mo_64_32(dflag);
+        }
 
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
commit 6f17675a9c14125af544948791a26e3d8033e2b0
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 09:34:20 2013 +1000

    target-i386: Change gen_op_mov_reg_A0 size parameter to TCGMemOp
    
    Change the domain of the parameter and update all callers.
    Which lets us defer completely to gen_op_mov_reg_v.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8861973..9b191ad 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -334,25 +334,9 @@ static inline void gen_op_mov_reg_T1(TCGMemOp ot, int reg)
     gen_op_mov_reg_v(ot, reg, cpu_T[1]);
 }
 
-static void gen_op_mov_reg_A0(TCGMemOp size, int reg)
+static inline void gen_op_mov_reg_A0(TCGMemOp size, int reg)
 {
-    switch (size) {
-    case MO_8:
-        tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
-        break;
-    case MO_16:
-        /* For x86_64, this sets the higher half of register to zero.
-           For i386, this is equivalent to a mov. */
-        tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
-        break;
-#ifdef TARGET_X86_64
-    case MO_32:
-        tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
-        break;
-#endif
-    default:
-        tcg_abort();
-    }
+    gen_op_mov_reg_v(size, reg, cpu_A0);
 }
 
 static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
@@ -2381,7 +2365,7 @@ static void gen_push_T0(DisasContext *s)
             gen_op_addq_A0_im(-2);
             gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
         }
-        gen_op_mov_reg_A0(2, R_ESP);
+        gen_op_mov_reg_A0(MO_64, R_ESP);
     } else
 #endif
     {
@@ -2402,9 +2386,9 @@ static void gen_push_T0(DisasContext *s)
         }
         gen_op_st_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
         if (s->ss32 && !s->addseg)
-            gen_op_mov_reg_A0(1, R_ESP);
+            gen_op_mov_reg_A0(MO_32, R_ESP);
         else
-            gen_op_mov_reg_T1(s->ss32 + 1, R_ESP);
+            gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
     }
 }
 
@@ -2422,7 +2406,7 @@ static void gen_push_T1(DisasContext *s)
             gen_op_addq_A0_im(-2);
             gen_op_st_v(s, MO_16, cpu_T[1], cpu_A0);
         }
-        gen_op_mov_reg_A0(2, R_ESP);
+        gen_op_mov_reg_A0(MO_64, R_ESP);
     } else
 #endif
     {
@@ -2442,7 +2426,7 @@ static void gen_push_T1(DisasContext *s)
         gen_op_st_v(s, s->dflag + 1, cpu_T[1], cpu_A0);
 
         if (s->ss32 && !s->addseg)
-            gen_op_mov_reg_A0(1, R_ESP);
+            gen_op_mov_reg_A0(MO_32, R_ESP);
         else
             gen_stack_update(s, (-2) << s->dflag);
     }
@@ -5566,7 +5550,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         s->addseg = 0;
         gen_lea_modrm(env, s, modrm);
         s->addseg = val;
-        gen_op_mov_reg_A0(ot - MO_16, reg);
+        gen_op_mov_reg_A0(ot, reg);
         break;
 
     case 0xa0: /* mov EAX, Ov */
commit 1d71ddb1c28f58e1065386725634ed36ae1d665f
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 08:27:33 2013 +1000

    target-i386: Change aflag to TCGMemOp
    
    Changing the domain to TCGMemOp makes it easier to interoperate
    with other portions of the rest of the translator.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index f1b4932..8861973 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -85,7 +85,8 @@ typedef struct DisasContext {
     /* current insn context */
     int override; /* -1 if no override */
     int prefix;
-    int aflag, dflag;
+    TCGMemOp aflag;
+    int dflag;
     target_ulong pc; /* pc = eip + cs_base */
     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
                    static state change (stop translation) */
@@ -509,17 +510,18 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s)
     int override;
 
     override = s->override;
+    switch (s->aflag) {
 #ifdef TARGET_X86_64
-    if (s->aflag == 2) {
+    case MO_64:
         if (override >= 0) {
             gen_op_movq_A0_seg(override);
             gen_op_addq_A0_reg_sN(0, R_ESI);
         } else {
             gen_op_movq_A0_reg(R_ESI);
         }
-    } else
+        break;
 #endif
-    if (s->aflag) {
+    case MO_32:
         /* 32 bit address */
         if (s->addseg && override < 0)
             override = R_DS;
@@ -529,32 +531,41 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s)
         } else {
             gen_op_movl_A0_reg(R_ESI);
         }
-    } else {
+        break;
+    case MO_16:
         /* 16 address, always override */
         if (override < 0)
             override = R_DS;
         tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESI]);
         gen_op_addl_A0_seg(s, override);
+        break;
+    default:
+        tcg_abort();
     }
 }
 
 static inline void gen_string_movl_A0_EDI(DisasContext *s)
 {
+    switch (s->aflag) {
 #ifdef TARGET_X86_64
-    if (s->aflag == 2) {
+    case MO_64:
         gen_op_movq_A0_reg(R_EDI);
-    } else
+        break;
 #endif
-    if (s->aflag) {
+    case MO_32:
         if (s->addseg) {
             gen_op_movl_A0_seg(R_ES);
             gen_op_addl_A0_reg_sN(0, R_EDI);
         } else {
             gen_op_movl_A0_reg(R_EDI);
         }
-    } else {
+        break;
+    case MO_16:
         tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_EDI]);
         gen_op_addl_A0_seg(s, R_ES);
+        break;
+    default:
+        tcg_abort();
     }
 }
 
@@ -700,8 +711,8 @@ static inline void gen_movs(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_EDI(s);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
-    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
+    gen_op_add_reg_T0(s->aflag, R_ESI);
+    gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
 static void gen_op_update1_cc(void)
@@ -1113,7 +1124,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
 
     l1 = gen_new_label();
     l2 = gen_new_label();
-    gen_op_jnz_ecx(s->aflag + 1, l1);
+    gen_op_jnz_ecx(s->aflag, l1);
     gen_set_label(l2);
     gen_jmp_tb(s, next_eip, 1);
     gen_set_label(l1);
@@ -1126,7 +1137,7 @@ static inline void gen_stos(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_EDI(s);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
+    gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
@@ -1135,7 +1146,7 @@ static inline void gen_lods(DisasContext *s, TCGMemOp ot)
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_mov_reg_T0(ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
+    gen_op_add_reg_T0(s->aflag, R_ESI);
 }
 
 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
@@ -1144,7 +1155,7 @@ static inline void gen_scas(DisasContext *s, TCGMemOp ot)
     gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
     gen_op(s, OP_CMPL, ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
+    gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
@@ -1154,8 +1165,8 @@ static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_ESI(s);
     gen_op(s, OP_CMPL, ot, OR_TMP0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
-    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
+    gen_op_add_reg_T0(s->aflag, R_ESI);
+    gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
@@ -1172,7 +1183,7 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot)
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
+    gen_op_add_reg_T0(s->aflag, R_EDI);
     if (use_icount)
         gen_io_end();
 }
@@ -1190,7 +1201,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot)
     gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
 
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
+    gen_op_add_reg_T0(s->aflag, R_ESI);
     if (use_icount)
         gen_io_end();
 }
@@ -1205,11 +1216,11 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     gen_update_cc_op(s);                                                      \
     l2 = gen_jz_ecx_string(s, next_eip);                                      \
     gen_ ## op(s, ot);                                                        \
-    gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);                               \
+    gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
     /* a loop would cause two single step exceptions if ECX = 1               \
        before rep string_insn */                                              \
     if (!s->jmp_opt)                                                          \
-        gen_op_jz_ecx(s->aflag + 1, l2);                                      \
+        gen_op_jz_ecx(s->aflag, l2);                                          \
     gen_jmp(s, cur_eip);                                                      \
 }
 
@@ -1223,11 +1234,11 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     gen_update_cc_op(s);                                                      \
     l2 = gen_jz_ecx_string(s, next_eip);                                      \
     gen_ ## op(s, ot);                                                        \
-    gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);                               \
+    gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
     gen_update_cc_op(s);                                                      \
     gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);                                 \
     if (!s->jmp_opt)                                                          \
-        gen_op_jz_ecx(s->aflag + 1, l2);                                      \
+        gen_op_jz_ecx(s->aflag, l2);                                          \
     gen_jmp(s, cur_eip);                                                      \
 }
 
@@ -1884,7 +1895,9 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
     mod = (modrm >> 6) & 3;
     rm = modrm & 7;
 
-    if (s->aflag) {
+    switch (s->aflag) {
+    case MO_64:
+    case MO_32:
         havesib = 0;
         base = rm;
         index = -1;
@@ -1964,7 +1977,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             tcg_gen_ld_tl(cpu_tmp0, cpu_env,
                           offsetof(CPUX86State, segs[override].base));
             if (CODE64(s)) {
-                if (s->aflag != 2) {
+                if (s->aflag == MO_32) {
                     tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
                 }
                 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
@@ -1974,10 +1987,12 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
         }
 
-        if (s->aflag != 2) {
+        if (s->aflag == MO_32) {
             tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
         }
-    } else {
+        break;
+
+    case MO_16:
         switch (mod) {
         case 0:
             if (rm == 6) {
@@ -2043,6 +2058,10 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             }
             gen_op_addl_A0_seg(s, override);
         }
+        break;
+
+    default:
+        tcg_abort();
     }
 }
 
@@ -2055,8 +2074,9 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
         return;
     rm = modrm & 7;
 
-    if (s->aflag) {
-
+    switch (s->aflag) {
+    case MO_64:
+    case MO_32:
         base = rm;
 
         if (base == 4) {
@@ -2078,7 +2098,9 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
             s->pc += 4;
             break;
         }
-    } else {
+        break;
+
+    case MO_16:
         switch (mod) {
         case 0:
             if (rm == 6) {
@@ -2093,6 +2115,10 @@ static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
             s->pc += 2;
             break;
         }
+        break;
+
+    default:
+        tcg_abort();
     }
 }
 
@@ -4396,16 +4422,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             /* maskmov : we must prepare A0 */
             if (mod != 3)
                 goto illegal_op;
-#ifdef TARGET_X86_64
-            if (s->aflag == 2) {
-                gen_op_movq_A0_reg(R_EDI);
-            } else
-#endif
-            {
-                gen_op_movl_A0_reg(R_EDI);
-                if (s->aflag == 0)
-                    tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-            }
+            tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
+            gen_extu(s->aflag, cpu_A0);
             gen_add_A0_ds_seg(s);
 
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
@@ -4431,9 +4449,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                target_ulong pc_start)
 {
-    int b, prefixes, aflag, dflag;
+    int b, prefixes, dflag;
     int shift;
-    TCGMemOp ot;
+    TCGMemOp ot, aflag;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
@@ -4571,7 +4589,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
            over 0x66 if both are present.  */
         dflag = (rex_w > 0 ? 2 : prefixes & PREFIX_DATA ? 0 : 1);
         /* In 64-bit mode, 0x67 selects 32-bit addressing.  */
-        aflag = (prefixes & PREFIX_ADR ? 1 : 2);
+        aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
     } else {
         /* In 16/32-bit mode, 0x66 selects the opposite data size.  */
         dflag = s->code32;
@@ -4579,9 +4597,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             dflag ^= 1;
         }
         /* In 16/32-bit mode, 0x67 selects the opposite addressing.  */
-        aflag = s->code32;
-        if (prefixes & PREFIX_ADR) {
-            aflag ^= 1;
+        if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
+            aflag = MO_32;
+        }  else {
+            aflag = MO_16;
         }
     }
 
@@ -5561,18 +5580,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 ot = MO_8;
             else
                 ot = dflag + MO_16;
+            switch (s->aflag) {
 #ifdef TARGET_X86_64
-            if (s->aflag == 2) {
+            case MO_64:
                 offset_addr = cpu_ldq_code(env, s->pc);
                 s->pc += 8;
-            } else
+                break;
 #endif
-            {
-                if (s->aflag) {
-                    offset_addr = insn_get(env, s, MO_32);
-                } else {
-                    offset_addr = insn_get(env, s, MO_16);
-                }
+            default:
+                offset_addr = insn_get(env, s, s->aflag);
+                break;
             }
             tcg_gen_movi_tl(cpu_A0, offset_addr);
             gen_add_A0_ds_seg(s);
@@ -5586,24 +5603,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         break;
     case 0xd7: /* xlat */
-#ifdef TARGET_X86_64
-        if (s->aflag == 2) {
-            gen_op_movq_A0_reg(R_EBX);
-            gen_op_mov_TN_reg(MO_64, 0, R_EAX);
-            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
-            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
-        } else
-#endif
-        {
-            gen_op_movl_A0_reg(R_EBX);
-            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
-            tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
-            tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
-            if (s->aflag == 0)
-                tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-            else
-                tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
-        }
+        tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
+        tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
+        tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
+        gen_extu(s->aflag, cpu_A0);
         gen_add_A0_ds_seg(s);
         gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
         gen_op_mov_reg_T0(MO_8, R_EAX);
@@ -7133,17 +7136,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             switch(b) {
             case 0: /* loopnz */
             case 1: /* loopz */
-                gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
-                gen_op_jz_ecx(s->aflag + 1, l3);
+                gen_op_add_reg_im(s->aflag, R_ECX, -1);
+                gen_op_jz_ecx(s->aflag, l3);
                 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
                 break;
             case 2: /* loop */
-                gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
-                gen_op_jnz_ecx(s->aflag + 1, l1);
+                gen_op_add_reg_im(s->aflag, R_ECX, -1);
+                gen_op_jnz_ecx(s->aflag, l1);
                 break;
             default:
             case 3: /* jcxz */
-                gen_op_jz_ecx(s->aflag + 1, l1);
+                gen_op_jz_ecx(s->aflag, l1);
                 break;
             }
 
@@ -7348,16 +7351,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         goto illegal_op;
                     gen_update_cc_op(s);
                     gen_jmp_im(pc_start - s->cs_base);
-#ifdef TARGET_X86_64
-                    if (s->aflag == 2) {
-                        gen_op_movq_A0_reg(R_EAX);
-                    } else
-#endif
-                    {
-                        gen_op_movl_A0_reg(R_EAX);
-                        if (s->aflag == 0)
-                            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
-                    }
+                    tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
+                    gen_extu(s->aflag, cpu_A0);
                     gen_add_A0_ds_seg(s);
                     gen_helper_monitor(cpu_env, cpu_A0);
                     break;
@@ -7417,7 +7412,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                         break;
                     } else {
-                        gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag),
+                        gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
                                          tcg_const_i32(s->pc - pc_start));
                         tcg_gen_exit_tb(0);
                         s->is_jmp = DISAS_TB_JUMP;
@@ -7435,7 +7430,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                         break;
                     } else {
-                        gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
+                        gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
                     }
                     break;
                 case 3: /* VMSAVE */
@@ -7445,7 +7440,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                         break;
                     } else {
-                        gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
+                        gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
                     }
                     break;
                 case 4: /* STGI */
@@ -7484,7 +7479,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
                         break;
                     } else {
-                        gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
+                        gen_helper_invlpga(cpu_env,
+                                           tcg_const_i32(s->aflag - 1));
                     }
                     break;
                 default:
commit c92aa1addeae7e3fe6876dd3dff7978f1d3449d2
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 07:50:53 2013 +1000

    target-i386: Change gen_op_j*z_ecx size parameter to TCGMemOp
    
    Change the domain of the parameter and update all callers.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 47897b4..f1b4932 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -605,17 +605,17 @@ static void gen_exts(TCGMemOp ot, TCGv reg)
     gen_ext_tl(reg, reg, ot, true);
 }
 
-static inline void gen_op_jnz_ecx(int size, int label1)
+static inline void gen_op_jnz_ecx(TCGMemOp size, int label1)
 {
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
-    gen_extu(size + 1, cpu_tmp0);
+    gen_extu(size, cpu_tmp0);
     tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
 }
 
-static inline void gen_op_jz_ecx(int size, int label1)
+static inline void gen_op_jz_ecx(TCGMemOp size, int label1)
 {
     tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
-    gen_extu(size + 1, cpu_tmp0);
+    gen_extu(size, cpu_tmp0);
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
 }
 
@@ -1113,7 +1113,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
 
     l1 = gen_new_label();
     l2 = gen_new_label();
-    gen_op_jnz_ecx(s->aflag, l1);
+    gen_op_jnz_ecx(s->aflag + 1, l1);
     gen_set_label(l2);
     gen_jmp_tb(s, next_eip, 1);
     gen_set_label(l1);
@@ -1209,7 +1209,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     /* a loop would cause two single step exceptions if ECX = 1               \
        before rep string_insn */                                              \
     if (!s->jmp_opt)                                                          \
-        gen_op_jz_ecx(s->aflag, l2);                                          \
+        gen_op_jz_ecx(s->aflag + 1, l2);                                      \
     gen_jmp(s, cur_eip);                                                      \
 }
 
@@ -1227,7 +1227,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     gen_update_cc_op(s);                                                      \
     gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);                                 \
     if (!s->jmp_opt)                                                          \
-        gen_op_jz_ecx(s->aflag, l2);                                          \
+        gen_op_jz_ecx(s->aflag + 1, l2);                                      \
     gen_jmp(s, cur_eip);                                                      \
 }
 
@@ -7134,16 +7134,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0: /* loopnz */
             case 1: /* loopz */
                 gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
-                gen_op_jz_ecx(s->aflag, l3);
+                gen_op_jz_ecx(s->aflag + 1, l3);
                 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
                 break;
             case 2: /* loop */
                 gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
-                gen_op_jnz_ecx(s->aflag, l1);
+                gen_op_jnz_ecx(s->aflag + 1, l1);
                 break;
             default:
             case 3: /* jcxz */
-                gen_op_jz_ecx(s->aflag, l1);
+                gen_op_jz_ecx(s->aflag + 1, l1);
                 break;
             }
 
commit d3f4bbe3318da00f5923ad5c9b60075f8a1cc073
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 07:44:57 2013 +1000

    target-i386: Change gen_op_add_reg_* size parameter to TCGMemOp
    
    These functions used the aflags/dflags domain, which is log2-1
    of the byte size.  Confusingly, they used enumeration values
    from the log2 domain.
    
    Change the domain of the parameter and update all callers.
    
    Since we're now in a common domain, defer the deposit/extend/mov
    decision to gen_op_mov_reg_v.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 10d1501..47897b4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -409,48 +409,16 @@ static inline void gen_op_jmp_T0(void)
     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, eip));
 }
 
-static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
+static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
 {
-    switch(size) {
-    case MO_8:
-        tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
-        tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
-        break;
-    case MO_16:
-        tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
-        /* For x86_64, this sets the higher half of register to zero.
-           For i386, this is equivalent to a nop. */
-        tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
-        tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
-        break;
-#ifdef TARGET_X86_64
-    case MO_32:
-        tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
-        break;
-#endif
-    }
+    tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
+    gen_op_mov_reg_v(size, reg, cpu_tmp0);
 }
 
-static inline void gen_op_add_reg_T0(int size, int reg)
+static inline void gen_op_add_reg_T0(TCGMemOp size, int reg)
 {
-    switch(size) {
-    case MO_8:
-        tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
-        tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
-        break;
-    case MO_16:
-        tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
-        /* For x86_64, this sets the higher half of register to zero.
-           For i386, this is equivalent to a nop. */
-        tcg_gen_ext32u_tl(cpu_tmp0, cpu_tmp0);
-        tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
-        break;
-#ifdef TARGET_X86_64
-    case MO_32:
-        tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
-        break;
-#endif
-    }
+    tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
+    gen_op_mov_reg_v(size, reg, cpu_tmp0);
 }
 
 static inline void gen_op_addl_A0_reg_sN(int shift, int reg)
@@ -732,8 +700,8 @@ static inline void gen_movs(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_EDI(s);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_ESI);
-    gen_op_add_reg_T0(s->aflag, R_EDI);
+    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
+    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
 }
 
 static void gen_op_update1_cc(void)
@@ -1158,7 +1126,7 @@ static inline void gen_stos(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_EDI(s);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_EDI);
+    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
 }
 
 static inline void gen_lods(DisasContext *s, TCGMemOp ot)
@@ -1167,7 +1135,7 @@ static inline void gen_lods(DisasContext *s, TCGMemOp ot)
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_mov_reg_T0(ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_ESI);
+    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
 }
 
 static inline void gen_scas(DisasContext *s, TCGMemOp ot)
@@ -1176,7 +1144,7 @@ static inline void gen_scas(DisasContext *s, TCGMemOp ot)
     gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
     gen_op(s, OP_CMPL, ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_EDI);
+    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
 }
 
 static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
@@ -1186,8 +1154,8 @@ static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
     gen_string_movl_A0_ESI(s);
     gen_op(s, OP_CMPL, ot, OR_TMP0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_ESI);
-    gen_op_add_reg_T0(s->aflag, R_EDI);
+    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
+    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
 }
 
 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
@@ -1204,7 +1172,7 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot)
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_EDI);
+    gen_op_add_reg_T0(s->aflag + 1, R_EDI);
     if (use_icount)
         gen_io_end();
 }
@@ -1222,7 +1190,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot)
     gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
 
     gen_op_movl_T0_Dshift(ot);
-    gen_op_add_reg_T0(s->aflag, R_ESI);
+    gen_op_add_reg_T0(s->aflag + 1, R_ESI);
     if (use_icount)
         gen_io_end();
 }
@@ -1237,7 +1205,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     gen_update_cc_op(s);                                                      \
     l2 = gen_jz_ecx_string(s, next_eip);                                      \
     gen_ ## op(s, ot);                                                        \
-    gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
+    gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);                               \
     /* a loop would cause two single step exceptions if ECX = 1               \
        before rep string_insn */                                              \
     if (!s->jmp_opt)                                                          \
@@ -1255,7 +1223,7 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
     gen_update_cc_op(s);                                                      \
     l2 = gen_jz_ecx_string(s, next_eip);                                      \
     gen_ ## op(s, ot);                                                        \
-    gen_op_add_reg_im(s->aflag, R_ECX, -1);                                   \
+    gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);                               \
     gen_update_cc_op(s);                                                      \
     gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2);                                 \
     if (!s->jmp_opt)                                                          \
@@ -2364,13 +2332,13 @@ static inline void gen_stack_update(DisasContext *s, int addend)
 {
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        gen_op_add_reg_im(2, R_ESP, addend);
+        gen_op_add_reg_im(MO_64, R_ESP, addend);
     } else
 #endif
     if (s->ss32) {
-        gen_op_add_reg_im(1, R_ESP, addend);
+        gen_op_add_reg_im(MO_32, R_ESP, addend);
     } else {
-        gen_op_add_reg_im(0, R_ESP, addend);
+        gen_op_add_reg_im(MO_16, R_ESP, addend);
     }
 }
 
@@ -7165,12 +7133,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             switch(b) {
             case 0: /* loopnz */
             case 1: /* loopz */
-                gen_op_add_reg_im(s->aflag, R_ECX, -1);
+                gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
                 gen_op_jz_ecx(s->aflag, l3);
                 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
                 break;
             case 2: /* loop */
-                gen_op_add_reg_im(s->aflag, R_ECX, -1);
+                gen_op_add_reg_im(s->aflag + 1, R_ECX, -1);
                 gen_op_jnz_ecx(s->aflag, l1);
                 break;
             default:
commit d67dc9e6194dec1f9b361b94ada6c567d6099f39
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Nov 6 07:25:05 2013 +1000

    target-i386: Use TCGMemOp for 'ot' variables
    
    The 'ot' variables (operand type?) hold the log2(byte size) of
    the operand being manipulated.  This is the same as the MO_SIZE
    subset of the TCGMemOp.  Indeed, we often pass 'ot' to the
    tcg_gen_qemu_ld/st functions.
    
    Changing the type from 'int' makes it easier to see what domain
    the variable should be.
    
    This does require adding some default cases to some switch statements,
    to avoid the 'unhandled enumeration value' warning that would result
    from the change of type.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index c3c51a6..10d1501 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -126,7 +126,7 @@ typedef struct DisasContext {
 static void gen_eob(DisasContext *s);
 static void gen_jmp(DisasContext *s, target_ulong eip);
 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
-static void gen_op(DisasContext *s1, int op, int ot, int d);
+static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
 
 /* i386 arith/logic operations */
 enum {
@@ -295,7 +295,7 @@ static inline bool byte_reg_is_xH(int reg)
     return true;
 }
 
-static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
+static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
 {
     switch(ot) {
     case MO_8:
@@ -308,7 +308,6 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
     case MO_16:
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
         break;
-    default: /* XXX this shouldn't be reached;  abort? */
     case MO_32:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
@@ -319,26 +318,27 @@ static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
         tcg_gen_mov_tl(cpu_regs[reg], t0);
         break;
 #endif
+    default:
+        tcg_abort();
     }
 }
 
-static inline void gen_op_mov_reg_T0(int ot, int reg)
+static inline void gen_op_mov_reg_T0(TCGMemOp ot, int reg)
 {
     gen_op_mov_reg_v(ot, reg, cpu_T[0]);
 }
 
-static inline void gen_op_mov_reg_T1(int ot, int reg)
+static inline void gen_op_mov_reg_T1(TCGMemOp ot, int reg)
 {
     gen_op_mov_reg_v(ot, reg, cpu_T[1]);
 }
 
-static inline void gen_op_mov_reg_A0(int size, int reg)
+static void gen_op_mov_reg_A0(TCGMemOp size, int reg)
 {
-    switch(size) {
+    switch (size) {
     case MO_8:
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
         break;
-    default: /* XXX this shouldn't be reached;  abort? */
     case MO_16:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
@@ -349,10 +349,12 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
         tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
         break;
 #endif
+    default:
+        tcg_abort();
     }
 }
 
-static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
+static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
 {
     if (ot == MO_8 && byte_reg_is_xH(reg)) {
         tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
@@ -362,7 +364,7 @@ static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
     }
 }
 
-static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg)
+static inline void gen_op_mov_TN_reg(TCGMemOp ot, int t_index, int reg)
 {
     gen_op_mov_v_reg(ot, cpu_T[t_index], reg);
 }
@@ -588,13 +590,13 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_T0_Dshift(int ot) 
+static inline void gen_op_movl_T0_Dshift(TCGMemOp ot)
 {
     tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, df));
     tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot);
 };
 
-static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
+static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
 {
     switch (size) {
     case MO_8:
@@ -625,12 +627,12 @@ static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
     }
 }
 
-static void gen_extu(int ot, TCGv reg)
+static void gen_extu(TCGMemOp ot, TCGv reg)
 {
     gen_ext_tl(reg, reg, ot, false);
 }
 
-static void gen_exts(int ot, TCGv reg)
+static void gen_exts(TCGMemOp ot, TCGv reg)
 {
     gen_ext_tl(reg, reg, ot, true);
 }
@@ -649,7 +651,7 @@ static inline void gen_op_jz_ecx(int size, int label1)
     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
 }
 
-static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
+static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
 {
     switch (ot) {
     case MO_8:
@@ -661,10 +663,12 @@ static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
     case MO_32:
         gen_helper_inl(v, n);
         break;
+    default:
+        tcg_abort();
     }
 }
 
-static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
+static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
 {
     switch (ot) {
     case MO_8:
@@ -676,10 +680,12 @@ static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
     case MO_32:
         gen_helper_outl(v, n);
         break;
+    default:
+        tcg_abort();
     }
 }
 
-static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
+static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
                          uint32_t svm_flags)
 {
     int state_saved;
@@ -701,6 +707,8 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
         case MO_32:
             gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
             break;
+        default:
+            tcg_abort();
         }
     }
     if(s->flags & HF_SVMI_MASK) {
@@ -717,7 +725,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
     }
 }
 
-static inline void gen_movs(DisasContext *s, int ot)
+static inline void gen_movs(DisasContext *s, TCGMemOp ot)
 {
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
@@ -911,7 +919,7 @@ static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
         return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
     default:
         {
-            int size = (s->cc_op - CC_OP_ADDB) & 3;
+            TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
             TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
             return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
         }
@@ -952,7 +960,7 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
         return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
     default:
         {
-            int size = (s->cc_op - CC_OP_ADDB) & 3;
+            TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
             TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
             return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
         }
@@ -963,7 +971,8 @@ static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
    value 'b'. In the fast case, T0 is guaranted not to be used. */
 static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
 {
-    int inv, jcc_op, size, cond;
+    int inv, jcc_op, cond;
+    TCGMemOp size;
     CCPrepare cc;
     TCGv t0;
 
@@ -1143,7 +1152,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
     return l2;
 }
 
-static inline void gen_stos(DisasContext *s, int ot)
+static inline void gen_stos(DisasContext *s, TCGMemOp ot)
 {
     gen_op_mov_TN_reg(MO_32, 0, R_EAX);
     gen_string_movl_A0_EDI(s);
@@ -1152,7 +1161,7 @@ static inline void gen_stos(DisasContext *s, int ot)
     gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
-static inline void gen_lods(DisasContext *s, int ot)
+static inline void gen_lods(DisasContext *s, TCGMemOp ot)
 {
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
@@ -1161,7 +1170,7 @@ static inline void gen_lods(DisasContext *s, int ot)
     gen_op_add_reg_T0(s->aflag, R_ESI);
 }
 
-static inline void gen_scas(DisasContext *s, int ot)
+static inline void gen_scas(DisasContext *s, TCGMemOp ot)
 {
     gen_string_movl_A0_EDI(s);
     gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
@@ -1170,7 +1179,7 @@ static inline void gen_scas(DisasContext *s, int ot)
     gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
-static inline void gen_cmps(DisasContext *s, int ot)
+static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
 {
     gen_string_movl_A0_EDI(s);
     gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
@@ -1181,7 +1190,7 @@ static inline void gen_cmps(DisasContext *s, int ot)
     gen_op_add_reg_T0(s->aflag, R_EDI);
 }
 
-static inline void gen_ins(DisasContext *s, int ot)
+static inline void gen_ins(DisasContext *s, TCGMemOp ot)
 {
     if (use_icount)
         gen_io_start();
@@ -1200,7 +1209,7 @@ static inline void gen_ins(DisasContext *s, int ot)
         gen_io_end();
 }
 
-static inline void gen_outs(DisasContext *s, int ot)
+static inline void gen_outs(DisasContext *s, TCGMemOp ot)
 {
     if (use_icount)
         gen_io_start();
@@ -1221,7 +1230,7 @@ static inline void gen_outs(DisasContext *s, int ot)
 /* same method as Valgrind : we generate jumps to current or next
    instruction */
 #define GEN_REPZ(op)                                                          \
-static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
+static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
                                  target_ulong cur_eip, target_ulong next_eip) \
 {                                                                             \
     int l2;\
@@ -1237,7 +1246,7 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
 }
 
 #define GEN_REPZ2(op)                                                         \
-static inline void gen_repz_ ## op(DisasContext *s, int ot,                   \
+static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot,              \
                                    target_ulong cur_eip,                      \
                                    target_ulong next_eip,                     \
                                    int nz)                                    \
@@ -1319,7 +1328,7 @@ static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
 }
 
 /* if d == OR_TMP0, it means memory operand (address in A0) */
-static void gen_op(DisasContext *s1, int op, int ot, int d)
+static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
 {
     if (d != OR_TMP0) {
         gen_op_mov_TN_reg(ot, 0, d);
@@ -1385,7 +1394,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
 }
 
 /* if d == OR_TMP0, it means memory operand (address in A0) */
-static void gen_inc(DisasContext *s1, int ot, int d, int c)
+static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
 {
     if (d != OR_TMP0) {
         gen_op_mov_TN_reg(ot, 0, d);
@@ -1404,8 +1413,8 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c)
     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
 }
 
-static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
-                            TCGv count, bool is_right)
+static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
+                            TCGv shm1, TCGv count, bool is_right)
 {
     TCGv_i32 z32, s32, oldop;
     TCGv z_tl;
@@ -1449,7 +1458,7 @@ static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
     set_cc_op(s, CC_OP_DYNAMIC);
 }
 
-static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, 
+static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
                             int is_right, int is_arith)
 {
     target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
@@ -1485,7 +1494,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
     gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
 }
 
-static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
+static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
                             int is_right, int is_arith)
 {
     int mask = (ot == MO_64 ? 0x3f : 0x1f);
@@ -1533,7 +1542,7 @@ static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
         tcg_gen_shri_tl(ret, arg1, -arg2);
 }
 
-static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
+static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
 {
     target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
     TCGv_i32 t0, t1;
@@ -1618,7 +1627,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
     set_cc_op(s, CC_OP_DYNAMIC);
 }
 
-static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
+static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
                           int is_right)
 {
     int mask = (ot == MO_64 ? 0x3f : 0x1f);
@@ -1696,7 +1705,7 @@ static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
 }
 
 /* XXX: add faster immediate = 1 case */
-static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1, 
+static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
                            int is_right)
 {
     gen_compute_eflags(s);
@@ -1724,6 +1733,8 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
             gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #endif
+        default:
+            tcg_abort();
         }
     } else {
         switch (ot) {
@@ -1741,6 +1752,8 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
             gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #endif
+        default:
+            tcg_abort();
         }
     }
     /* store */
@@ -1748,7 +1761,7 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
 }
 
 /* XXX: add faster immediate case */
-static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
+static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
                              bool is_right, TCGv count_in)
 {
     target_ulong mask = (ot == MO_64 ? 63 : 31);
@@ -1829,7 +1842,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
     tcg_temp_free(count);
 }
 
-static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
+static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
 {
     if (s != OR_TMP1)
         gen_op_mov_TN_reg(ot, 1, s);
@@ -1859,7 +1872,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
     }
 }
 
-static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
+static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
 {
     switch(op) {
     case OP_ROL:
@@ -2140,7 +2153,7 @@ static void gen_add_A0_ds_seg(DisasContext *s)
 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
    OR_TMP0 */
 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
-                           int ot, int reg, int is_store)
+                           TCGMemOp ot, int reg, int is_store)
 {
     int mod, rm;
 
@@ -2170,11 +2183,11 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
     }
 }
 
-static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
+static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
 {
     uint32_t ret;
 
-    switch(ot) {
+    switch (ot) {
     case MO_8:
         ret = cpu_ldub_code(env, s->pc);
         s->pc++;
@@ -2183,16 +2196,20 @@ static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
         ret = cpu_lduw_code(env, s->pc);
         s->pc += 2;
         break;
-    default:
     case MO_32:
+#ifdef TARGET_X86_64
+    case MO_64:
+#endif
         ret = cpu_ldl_code(env, s->pc);
         s->pc += 4;
         break;
+    default:
+        tcg_abort();
     }
     return ret;
 }
 
-static inline int insn_const_size(unsigned int ot)
+static inline int insn_const_size(TCGMemOp ot)
 {
     if (ot <= MO_32) {
         return 1 << ot;
@@ -2251,7 +2268,7 @@ static inline void gen_jcc(DisasContext *s, int b,
     }
 }
 
-static void gen_cmovcc1(CPUX86State *env, DisasContext *s, int ot, int b,
+static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
                         int modrm, int reg)
 {
     CCPrepare cc;
@@ -2524,7 +2541,8 @@ static void gen_popa(DisasContext *s)
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
 {
-    int ot, opsize;
+    TCGMemOp ot;
+    int opsize;
 
     level &= 0x1f;
 #ifdef TARGET_X86_64
@@ -3036,12 +3054,13 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = {
 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     target_ulong pc_start, int rex_r)
 {
-    int b1, op1_offset, op2_offset, is_xmm, val, ot;
+    int b1, op1_offset, op2_offset, is_xmm, val;
     int modrm, mod, rm, reg;
     SSEFunc_0_epp sse_fn_epp;
     SSEFunc_0_eppi sse_fn_eppi;
     SSEFunc_0_ppi sse_fn_ppi;
     SSEFunc_0_eppt sse_fn_eppt;
+    TCGMemOp ot;
 
     b &= 0xff;
     if (s->prefix & PREFIX_DATA)
@@ -4445,7 +4464,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                target_ulong pc_start)
 {
     int b, prefixes, aflag, dflag;
-    int shift, ot;
+    int shift;
+    TCGMemOp ot;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
commit a7e5c7de2a634cbf7b528659c5e8a25818c5b92e
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:38:58 2013 +1000

    target-i386: Remove gen_op_andl_A0_ffff
    
    Replace it with tcg_gen_ext16u_tl, and in two cases merge with a
    previous move from cpu_regs.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 4da5b8e..c3c51a6 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,11 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_andl_A0_ffff(void)
-{
-    tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
-}
-
 #ifdef TARGET_X86_64
 
 #define NB_OP_SIZES 4
@@ -568,8 +563,7 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s)
         /* 16 address, always override */
         if (override < 0)
             override = R_DS;
-        gen_op_movl_A0_reg(R_ESI);
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESI]);
         gen_op_addl_A0_seg(s, override);
     }
 }
@@ -589,8 +583,7 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s)
             gen_op_movl_A0_reg(R_EDI);
         }
     } else {
-        gen_op_movl_A0_reg(R_EDI);
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_EDI]);
         gen_op_addl_A0_seg(s, R_ES);
     }
 }
@@ -2058,7 +2051,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
         }
         if (disp != 0)
             gen_op_addl_A0_im(disp);
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     no_rm:
         if (must_add_seg) {
             if (override < 0) {
@@ -2392,7 +2385,7 @@ static void gen_push_T0(DisasContext *s)
                 gen_op_addl_A0_seg(s, R_SS);
             }
         } else {
-            gen_op_andl_A0_ffff();
+            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             tcg_gen_mov_tl(cpu_T[1], cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
@@ -2432,7 +2425,7 @@ static void gen_push_T1(DisasContext *s)
                 gen_op_addl_A0_seg(s, R_SS);
             }
         } else {
-            gen_op_andl_A0_ffff();
+            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
         gen_op_st_v(s, s->dflag + 1, cpu_T[1], cpu_A0);
@@ -2459,7 +2452,7 @@ static void gen_pop_T0(DisasContext *s)
             if (s->addseg)
                 gen_op_addl_A0_seg(s, R_SS);
         } else {
-            gen_op_andl_A0_ffff();
+            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
         gen_op_ld_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
@@ -2482,7 +2475,7 @@ static void gen_stack_A0(DisasContext *s)
 {
     gen_op_movl_A0_reg(R_ESP);
     if (!s->ss32)
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
     if (s->addseg)
         gen_op_addl_A0_seg(s, R_SS);
@@ -2495,7 +2488,7 @@ static void gen_pusha(DisasContext *s)
     gen_op_movl_A0_reg(R_ESP);
     gen_op_addl_A0_im(-16 <<  s->dflag);
     if (!s->ss32)
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
     if (s->addseg)
         gen_op_addl_A0_seg(s, R_SS);
@@ -2513,7 +2506,7 @@ static void gen_popa(DisasContext *s)
     int i;
     gen_op_movl_A0_reg(R_ESP);
     if (!s->ss32)
-        gen_op_andl_A0_ffff();
+        tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
     tcg_gen_mov_tl(cpu_T[1], cpu_A0);
     tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 16 <<  s->dflag);
     if (s->addseg)
@@ -2564,7 +2557,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         gen_op_movl_A0_reg(R_ESP);
         gen_op_addl_A0_im(-opsize);
         if (!s->ss32)
-            gen_op_andl_A0_ffff();
+            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
         if (s->addseg)
             gen_op_addl_A0_seg(s, R_SS);
@@ -4424,7 +4417,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             {
                 gen_op_movl_A0_reg(R_EDI);
                 if (s->aflag == 0)
-                    gen_op_andl_A0_ffff();
+                    tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             }
             gen_add_A0_ds_seg(s);
 
@@ -5619,7 +5612,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
             if (s->aflag == 0)
-                gen_op_andl_A0_ffff();
+                tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
             else
                 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
         }
@@ -7375,7 +7368,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     {
                         gen_op_movl_A0_reg(R_EAX);
                         if (s->aflag == 0)
-                            gen_op_andl_A0_ffff();
+                            tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
                     }
                     gen_add_A0_ds_seg(s);
                     gen_helper_monitor(cpu_env, cpu_A0);
commit 2b98a7d75308a968472a537b215408faf0b9c628
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:29:14 2013 +1000

    target-i386: Remove gen_op_movl_T0_T1
    
    Replace it with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6051c2c..4da5b8e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,11 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_T0_T1(void)
-{
-    tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
-}
-
 static inline void gen_op_andl_A0_ffff(void)
 {
     tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff);
@@ -5046,7 +5041,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                           tcg_const_i32(s->pc - pc_start));
             } else {
                 gen_op_movl_seg_T0_vm(R_CS);
-                gen_op_movl_T0_T1();
+                tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
                 gen_op_jmp_T0();
             }
             gen_eob(s);
commit f0706f0c939ea751e8bb164f58594e254749b7fd
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:27:09 2013 +1000

    target-i386: Remove gen_op_andl_T0_im
    
    Replace it with its definition.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 502d129..6051c2c 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,11 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_andl_T0_im(uint32_t val)
-{
-    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
-}
-
 static inline void gen_op_movl_T0_T1(void)
 {
     tcg_gen_mov_tl(cpu_T[0], cpu_T[1]);
@@ -7363,8 +7358,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
             gen_add_A0_im(s, 2);
             tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
-            if (!s->dflag)
-                gen_op_andl_T0_im(0xffffff);
+            if (s->dflag == 0) {
+                tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
+            }
             gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
             break;
         case 1:
@@ -7426,8 +7422,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 gen_add_A0_im(s, 2);
                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
-                if (!s->dflag)
-                    gen_op_andl_T0_im(0xffffff);
+                if (s->dflag == 0) {
+                    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
+                }
                 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
             }
             break;
@@ -7526,8 +7523,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
                 gen_add_A0_im(s, 2);
                 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
-                if (!s->dflag)
-                    gen_op_andl_T0_im(0xffffff);
+                if (s->dflag == 0) {
+                    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
+                }
                 if (op == 2) {
                     tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
                     tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
commit 40b90233d260446a6d4099f41f0aed1b77962248
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:23:48 2013 +1000

    target-i386: Remove gen_op_andl_T0_ffff
    
    Replace it with tcg_gen_ext16u_tl.  In four places we can combine that
    with a previous move into cpu_T[0], and in one place we can infer that
    the zero-extension has already happened via the previous load.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index a0fba1b..502d129 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,11 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_andl_T0_ffff(void)
-{
-    tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
-}
-
 static inline void gen_op_andl_T0_im(uint32_t val)
 {
     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val);
@@ -5007,8 +5002,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 2: /* call Ev */
             /* XXX: optimize if memory (no 'and' is necessary) */
-            if (s->dflag == 0)
-                gen_op_andl_T0_ffff();
+            if (s->dflag == 0) {
+                tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
+            }
             next_eip = s->pc - s->cs_base;
             tcg_gen_movi_tl(cpu_T[1], next_eip);
             gen_push_T1(s);
@@ -5036,8 +5032,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_eob(s);
             break;
         case 4: /* jmp Ev */
-            if (s->dflag == 0)
-                gen_op_andl_T0_ffff();
+            if (s->dflag == 0) {
+                tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
+            }
             gen_op_jmp_T0();
             gen_eob(s);
             break;
@@ -6422,8 +6419,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             ot = MO_8;
         else
             ot = dflag ? MO_32 : MO_16;
-        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
-        gen_op_andl_T0_ffff();
+        tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base, 
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -6441,8 +6437,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             ot = MO_8;
         else
             ot = dflag ? MO_32 : MO_16;
-        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
-        gen_op_andl_T0_ffff();
+        tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes) | 4);
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
@@ -6504,8 +6499,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             ot = MO_8;
         else
             ot = dflag ? MO_32 : MO_16;
-        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
-        gen_op_andl_T0_ffff();
+        tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
         if (use_icount)
@@ -6524,8 +6518,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             ot = MO_8;
         else
             ot = dflag ? MO_32 : MO_16;
-        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
-        gen_op_andl_T0_ffff();
+        tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
         gen_op_mov_TN_reg(ot, 1, R_EAX);
@@ -6550,16 +6543,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s) && s->dflag)
             s->dflag = 2;
         gen_stack_update(s, val + (2 << s->dflag));
-        if (s->dflag == 0)
-            gen_op_andl_T0_ffff();
+        if (s->dflag == 0) {
+            tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
+        }
         gen_op_jmp_T0();
         gen_eob(s);
         break;
     case 0xc3: /* ret */
         gen_pop_T0(s);
         gen_pop_update(s);
-        if (s->dflag == 0)
-            gen_op_andl_T0_ffff();
+        if (s->dflag == 0) {
+            tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
+        }
         gen_op_jmp_T0();
         gen_eob(s);
         break;
@@ -6575,15 +6570,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_stack_A0(s);
             /* pop offset */
-            gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
-            if (s->dflag == 0)
-                gen_op_andl_T0_ffff();
+            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
             /* NOTE: keeping EIP updated is not a problem in case of
                exception */
             gen_op_jmp_T0();
             /* pop selector */
             gen_op_addl_A0_im(2 << s->dflag);
-            gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
+            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
             gen_op_movl_seg_T0_vm(R_CS);
             /* add stack offset */
             gen_stack_update(s, val + (4 << s->dflag));
commit cc0bce884b9a3cf38b5aa8a711813e7ca1c26cac
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:13:44 2013 +1000

    target-i386: Remove gen_movtl_T*_im
    
    Propagate the definitions into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index ade8606..a0fba1b 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,16 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_movtl_T0_im(target_ulong val)
-{
-    tcg_gen_movi_tl(cpu_T[0], val);
-}
-
-static inline void gen_movtl_T1_im(target_ulong val)
-{
-    tcg_gen_movi_tl(cpu_T[1], val);
-}
-
 static inline void gen_op_andl_T0_ffff(void)
 {
     tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
@@ -5020,7 +5010,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (s->dflag == 0)
                 gen_op_andl_T0_ffff();
             next_eip = s->pc - s->cs_base;
-            gen_movtl_T1_im(next_eip);
+            tcg_gen_movi_tl(cpu_T[1], next_eip);
             gen_push_T1(s);
             gen_op_jmp_T0();
             gen_eob(s);
@@ -5663,7 +5653,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tmp = cpu_ldq_code(env, s->pc);
             s->pc += 8;
             reg = (b & 7) | REX_B(s);
-            gen_movtl_T0_im(tmp);
+            tcg_gen_movi_tl(cpu_T[0], tmp);
             gen_op_mov_reg_T0(MO_64, reg);
         } else
 #endif
@@ -6637,7 +6627,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tval &= 0xffff;
             else if(!CODE64(s))
                 tval &= 0xffffffff;
-            gen_movtl_T0_im(next_eip);
+            tcg_gen_movi_tl(cpu_T[0], next_eip);
             gen_push_T0(s);
             gen_jmp(s, tval);
         }
commit 3250cff8e521ec361d3bda69acffa77b70f9525d
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 12:09:00 2013 +1000

    target-i386: Remove gen_op_mov*_A0_im
    
    Propagate the definitions into all users.  In two cases, this allows
    us to share code between the 32-bit and 64-bit immediate moves.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 59554aa..ade8606 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,18 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_A0_im(uint32_t val)
-{
-    tcg_gen_movi_tl(cpu_A0, val);
-}
-
-#ifdef TARGET_X86_64
-static inline void gen_op_movq_A0_im(int64_t val)
-{
-    tcg_gen_movi_tl(cpu_A0, val);
-}
-#endif
-
 static inline void gen_movtl_T0_im(target_ulong val)
 {
     tcg_gen_movi_tl(cpu_T[0], val);
@@ -2046,7 +2034,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
             if (rm == 6) {
                 disp = cpu_lduw_code(env, s->pc);
                 s->pc += 2;
-                gen_op_movl_A0_im(disp);
+                tcg_gen_movi_tl(cpu_A0, disp);
                 rm = 0; /* avoid SS override */
                 goto no_rm;
             } else {
@@ -5619,7 +5607,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (s->aflag == 2) {
                 offset_addr = cpu_ldq_code(env, s->pc);
                 s->pc += 8;
-                gen_op_movq_A0_im(offset_addr);
             } else
 #endif
             {
@@ -5628,8 +5615,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 } else {
                     offset_addr = insn_get(env, s, MO_16);
                 }
-                gen_op_movl_A0_im(offset_addr);
             }
+            tcg_gen_movi_tl(cpu_A0, offset_addr);
             gen_add_A0_ds_seg(s);
             if ((b & 2) == 0) {
                 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
commit 0ae657b11656284d5f3967c3fe9640c2a238fcd0
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 11:58:01 2013 +1000

    target-i386: Remove gen_op_movl_T0_im*
    
    Propagate the definitions into all users.  The only time that
    gen_op_movl_T1_imu was used, the input was type 'unsigned',
    so the replacement works identically.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 46eabe4..59554aa 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,16 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_T1_im(int32_t val)
-{
-    tcg_gen_movi_tl(cpu_T[1], val);
-}
-
-static inline void gen_op_movl_T1_imu(uint32_t val)
-{
-    tcg_gen_movi_tl(cpu_T[1], val);
-}
-
 static inline void gen_op_movl_A0_im(uint32_t val)
 {
     tcg_gen_movi_tl(cpu_A0, val);
@@ -1934,7 +1924,7 @@ static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
         break;
     default:
         /* currently not optimized */
-        gen_op_movl_T1_im(c);
+        tcg_gen_movi_tl(cpu_T[1], c);
         gen_shift(s1, op, ot, d, OR_TMP1);
         break;
     }
@@ -4727,7 +4717,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 break;
             case 2: /* OP A, Iv */
                 val = insn_get(env, s, ot);
-                gen_op_movl_T1_im(val);
+                tcg_gen_movi_tl(cpu_T[1], val);
                 gen_op(s, op, ot, OR_EAX);
                 break;
             }
@@ -4775,7 +4765,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 val = (int8_t)insn_get(env, s, MO_8);
                 break;
             }
-            gen_op_movl_T1_im(val);
+            tcg_gen_movi_tl(cpu_T[1], val);
             gen_op(s, op, ot, opreg);
         }
         break;
@@ -4813,7 +4803,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         switch(op) {
         case 0: /* test */
             val = insn_get(env, s, ot);
-            gen_op_movl_T1_im(val);
+            tcg_gen_movi_tl(cpu_T[1], val);
             gen_op_testl_T0_T1_cc();
             set_cc_op(s, CC_OP_LOGICB + ot);
             break;
@@ -5124,7 +5114,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         val = insn_get(env, s, ot);
 
         gen_op_mov_TN_reg(ot, 0, OR_EAX);
-        gen_op_movl_T1_im(val);
+        tcg_gen_movi_tl(cpu_T[1], val);
         gen_op_testl_T0_T1_cc();
         set_cc_op(s, CC_OP_LOGICB + ot);
         break;
@@ -5180,10 +5170,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         if (b == 0x69) {
             val = insn_get(env, s, ot);
-            gen_op_movl_T1_im(val);
+            tcg_gen_movi_tl(cpu_T[1], val);
         } else if (b == 0x6b) {
             val = (int8_t)insn_get(env, s, MO_8);
-            gen_op_movl_T1_im(val);
+            tcg_gen_movi_tl(cpu_T[1], val);
         } else {
             gen_op_mov_TN_reg(ot, 1, reg);
         }
@@ -6676,7 +6666,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             selector = insn_get(env, s, MO_16);
 
             tcg_gen_movi_tl(cpu_T[0], selector);
-            gen_op_movl_T1_imu(offset);
+            tcg_gen_movi_tl(cpu_T[1], offset);
         }
         goto do_lcall;
     case 0xe9: /* jmp im */
@@ -6702,7 +6692,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             selector = insn_get(env, s, MO_16);
 
             tcg_gen_movi_tl(cpu_T[0], selector);
-            gen_op_movl_T1_imu(offset);
+            tcg_gen_movi_tl(cpu_T[1], offset);
         }
         goto do_ljmp;
     case 0xeb: /* jmp Jb */
@@ -6869,7 +6859,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         /* load shift */
         val = cpu_ldub_code(env, s->pc++);
-        gen_op_movl_T1_im(val);
+        tcg_gen_movi_tl(cpu_T[1], val);
         if (op < 4)
             goto illegal_op;
         op -= 4;
commit 1b90d56e8c46ca92f39c330a5ce38ef7f6d6ebb6
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 11:51:10 2013 +1000

    target-i386: Remove gen_op_movl_T0_im*
    
    Propagate the definition of gen_op_movl_T0_im to all users.
    The function gen_op_movl_T0_imu was unused.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0671371..46eabe4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,16 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_T0_im(int32_t val)
-{
-    tcg_gen_movi_tl(cpu_T[0], val);
-}
-
-static inline void gen_op_movl_T0_imu(uint32_t val)
-{
-    tcg_gen_movi_tl(cpu_T[0], val);
-}
-
 static inline void gen_op_movl_T1_im(int32_t val)
 {
     tcg_gen_movi_tl(cpu_T[1], val);
@@ -3500,13 +3490,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             }
             val = cpu_ldub_code(env, s->pc++);
             if (is_xmm) {
-                gen_op_movl_T0_im(val);
+                tcg_gen_movi_tl(cpu_T[0], val);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
                 tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
                 op1_offset = offsetof(CPUX86State,xmm_t0);
             } else {
-                gen_op_movl_T0_im(val);
+                tcg_gen_movi_tl(cpu_T[0], val);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
                 tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
@@ -5380,7 +5370,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             val = insn_get(env, s, ot);
         else
             val = (int8_t)insn_get(env, s, MO_8);
-        gen_op_movl_T0_im(val);
+        tcg_gen_movi_tl(cpu_T[0], val);
         gen_push_T0(s);
         break;
     case 0x8f: /* pop Ev */
@@ -5509,7 +5499,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_lea_modrm(env, s, modrm);
         }
         val = insn_get(env, s, ot);
-        gen_op_movl_T0_im(val);
+        tcg_gen_movi_tl(cpu_T[0], val);
         if (mod != 3) {
             gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         } else {
@@ -5685,7 +5675,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0xb0 ... 0xb7: /* mov R, Ib */
         val = insn_get(env, s, MO_8);
-        gen_op_movl_T0_im(val);
+        tcg_gen_movi_tl(cpu_T[0], val);
         gen_op_mov_reg_T0(MO_8, (b & 7) | REX_B(s));
         break;
     case 0xb8 ... 0xbf: /* mov R, Iv */
@@ -5704,7 +5694,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             ot = dflag ? MO_32 : MO_16;
             val = insn_get(env, s, ot);
             reg = (b & 7) | REX_B(s);
-            gen_op_movl_T0_im(val);
+            tcg_gen_movi_tl(cpu_T[0], val);
             gen_op_mov_reg_T0(ot, reg);
         }
         break;
@@ -6508,12 +6498,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         else
             ot = dflag ? MO_32 : MO_16;
         val = cpu_ldub_code(env, s->pc++);
-        gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
         if (use_icount)
             gen_io_start();
-        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+        tcg_gen_movi_i32(cpu_tmp2_i32, val);
         gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
         gen_op_mov_reg_T1(ot, R_EAX);
         if (use_icount) {
@@ -6528,14 +6517,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         else
             ot = dflag ? MO_32 : MO_16;
         val = cpu_ldub_code(env, s->pc++);
-        gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
         gen_op_mov_TN_reg(ot, 1, R_EAX);
 
         if (use_icount)
             gen_io_start();
-        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+        tcg_gen_movi_i32(cpu_tmp2_i32, val);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
         if (use_icount) {
@@ -6687,7 +6675,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             offset = insn_get(env, s, ot);
             selector = insn_get(env, s, MO_16);
 
-            gen_op_movl_T0_im(selector);
+            tcg_gen_movi_tl(cpu_T[0], selector);
             gen_op_movl_T1_imu(offset);
         }
         goto do_lcall;
@@ -6713,7 +6701,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             offset = insn_get(env, s, ot);
             selector = insn_get(env, s, MO_16);
 
-            gen_op_movl_T0_im(selector);
+            tcg_gen_movi_tl(cpu_T[0], selector);
             gen_op_movl_T1_imu(offset);
         }
         goto do_ljmp;
commit 97212c8844f50b3552e991e0d3305d7d69c2a99f
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 11:37:35 2013 +1000

    target-i386: Remove gen_op_movl_T0_0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 2d404d7..0671371 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -252,11 +252,6 @@ static void gen_update_cc_op(DisasContext *s)
     }
 }
 
-static inline void gen_op_movl_T0_0(void)
-{
-    tcg_gen_movi_tl(cpu_T[0], 0);
-}
-
 static inline void gen_op_movl_T0_im(int32_t val)
 {
     tcg_gen_movi_tl(cpu_T[0], val);
@@ -1257,7 +1252,7 @@ static inline void gen_ins(DisasContext *s, int ot)
     gen_string_movl_A0_EDI(s);
     /* Note: we must do this dummy write first to be restartable in
        case of page fault. */
-    gen_op_movl_T0_0();
+    tcg_gen_movi_tl(cpu_T[0], 0);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
@@ -3271,7 +3266,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
-                gen_op_movl_T0_0();
+                tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
@@ -3286,7 +3281,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
-                gen_op_movl_T0_0();
+                tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
             } else {
@@ -3507,13 +3502,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (is_xmm) {
                 gen_op_movl_T0_im(val);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
-                gen_op_movl_T0_0();
+                tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
                 op1_offset = offsetof(CPUX86State,xmm_t0);
             } else {
                 gen_op_movl_T0_im(val);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
-                gen_op_movl_T0_0();
+                tcg_gen_movi_tl(cpu_T[0], 0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
                 op1_offset = offsetof(CPUX86State,mmx_t0);
             }
@@ -4716,7 +4711,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 xor_zero:
                     /* xor reg, reg optimisation */
                     set_cc_op(s, CC_OP_CLR);
-                    gen_op_movl_T0_0();
+                    tcg_gen_movi_tl(cpu_T[0], 0);
                     gen_op_mov_reg_T0(ot, reg);
                     break;
                 } else {
commit a7fbcbe538518108a967306c29dbb0fe76e0b512
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 11:31:34 2013 +1000

    target-i386: Tidy extend + move
    
    For the known MO_32/MO_64 cases, we don't need to extend a 32-bit temp
    into a 64-bit temp before storing into the hardware register.
    
    We do need the extension for the MO_8/MO_16 cases, in order for the
    deposit_tl operation to work, so leave those alone.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index ad6ecd3..2d404d7 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -3538,16 +3538,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                              offsetof(CPUX86State,xmm_regs[rm]));
             gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
-            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-            gen_op_mov_reg_T0(MO_32, reg);
+            tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
             break;
         case 0x150: /* movmskpd */
             rm = (modrm & 7) | REX_B(s);
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                              offsetof(CPUX86State,xmm_regs[rm]));
             gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
-            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-            gen_op_mov_reg_T0(MO_32, reg);
+            tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
             break;
         case 0x02a: /* cvtpi2ps */
         case 0x12a: /* cvtpi2pd */
@@ -3731,9 +3729,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
                 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
             }
-            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_op_mov_reg_T0(MO_32, reg);
+            tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
             break;
 
         case 0x138:
@@ -4229,8 +4226,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                                         offsetof(CPUX86State,
                                                 xmm_regs[reg].XMM_L(val & 3)));
                         if (mod == 3) {
-                            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                            gen_op_mov_reg_v(ot, rm, cpu_T[0]);
+                            tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
                         } else {
                             tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
                                                 s->mem_index, MO_LEUL);
@@ -4241,7 +4237,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                                         offsetof(CPUX86State,
                                                 xmm_regs[reg].XMM_Q(val & 1)));
                         if (mod == 3) {
-                            gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
+                            tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
                         } else {
                             tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
                                                 s->mem_index, MO_LEQ);
commit d5601ad0235679a1b58e8975a34f63c5f039af36
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Nov 5 11:14:33 2013 +1000

    target-i386: Tidy extend + store
    
    We can now use tcg_gen_qemu_st_i32 directly to avoid the extension.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 58be71f..ad6ecd3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4228,12 +4228,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                         tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
                                         offsetof(CPUX86State,
                                                 xmm_regs[reg].XMM_L(val & 3)));
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
                         if (mod == 3) {
+                            tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
                             gen_op_mov_reg_v(ot, rm, cpu_T[0]);
                         } else {
-                            tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
-                                               s->mem_index, MO_LEUL);
+                            tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                                s->mem_index, MO_LEUL);
                         }
                     } else { /* pextrq */
 #ifdef TARGET_X86_64
@@ -5970,8 +5970,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     switch(op >> 4) {
                     case 1:
                         gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
+                        tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         break;
                     case 2:
                         gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
@@ -5981,8 +5981,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 3:
                     default:
                         gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
+                        tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUW);
                         break;
                     }
                     gen_helper_fpop(cpu_env);
@@ -5991,13 +5991,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     switch(op >> 4) {
                     case 0:
                         gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
+                        tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         break;
                     case 1:
                         gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
+                        tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         break;
                     case 2:
                         gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
@@ -6007,8 +6007,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 3:
                     default:
                         gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
-                        tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
+                        tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUW);
                         break;
                     }
                     if ((op & 7) == 3)
@@ -6033,8 +6033,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 break;
             case 0x0f: /* fnstcw mem */
                 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
-                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
+                tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                    s->mem_index, MO_LEUW);
                 break;
             case 0x1d: /* fldt mem */
                 gen_update_cc_op(s);
@@ -6059,8 +6059,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 break;
             case 0x2f: /* fnstsw mem */
                 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
-                tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
+                tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
+                                    s->mem_index, MO_LEUW);
                 break;
             case 0x3c: /* fbld */
                 gen_update_cc_op(s);
commit 80b0201384f17fd6401eb11eab79ea0e5896b496
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 09:54:48 2013 -1000

    target-i386: Tidy load + truncate
    
    We can now use tcg_gen_qemu_ld_i32 directly to avoid the truncation.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 3d03d47..58be71f 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4303,12 +4303,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 case 0x22:
                     if (ot == MO_32) { /* pinsrd */
                         if (mod == 3) {
-                            gen_op_mov_v_reg(ot, cpu_tmp0, rm);
+                            tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
                         } else {
-                            tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
-                                               s->mem_index, MO_LEUL);
+                            tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                                s->mem_index, MO_LEUL);
                         }
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
                         tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
                                         offsetof(CPUX86State,
                                                 xmm_regs[reg].XMM_L(val & 3)));
@@ -5905,13 +5904,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 2:
@@ -5921,8 +5920,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_ld_v(s, MO_SW, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LESW);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
                     }
@@ -5944,13 +5943,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 case 0:
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LEUL);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 2:
@@ -5960,8 +5959,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_ld_v(s, MO_SW, cpu_T[0], cpu_A0);
-                        tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                        tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                            s->mem_index, MO_LESW);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
                     }
@@ -6023,8 +6022,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
                 break;
             case 0x0d: /* fldcw mem */
-                gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
-                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                    s->mem_index, MO_LEUW);
                 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
                 break;
             case 0x0e: /* fnstenv mem */
@@ -7953,8 +7952,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_lea_modrm(env, s, modrm);
             if (op == 2) {
-                gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
+                                    s->mem_index, MO_LEUL);
                 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
commit 24b9c00fc3106a98adc0e89915584eadb092b745
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 09:35:30 2013 -1000

    target-i386: Tidy gen_op_mov_TN_reg+tcg_gen_trunc_tl_i32
    
    For the 16 and 32-bit cases, we don't need to truncate via
    a temporary register.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index c07062c..3d03d47 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1259,8 +1259,7 @@ static inline void gen_ins(DisasContext *s, int ot)
        case of page fault. */
     gen_op_movl_T0_0();
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
-    gen_op_mov_TN_reg(MO_16, 1, R_EDX);
-    tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
+    tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
     gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
@@ -1277,8 +1276,7 @@ static inline void gen_outs(DisasContext *s, int ot)
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
 
-    gen_op_mov_TN_reg(MO_16, 1, R_EDX);
-    tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
+    tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
     gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
@@ -3839,8 +3837,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     ot = MO_64;
                 }
 
-                gen_op_mov_TN_reg(MO_32, 0, reg);
-                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+                tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
                                  cpu_T[0], tcg_const_i32(8 << ot));
commit 3655a19fdd9891c1e3a568d77483a11b2ad70951
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 09:22:04 2013 -1000

    target-i386: Use MO_BE for movbe
    
    Fold the bswap into the memory operation.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index cfd75dc..c07062c 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -3869,44 +3869,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     ot = MO_64;
                 }
 
-                /* Load the data incoming to the bswap.  Note that the TCG
-                   implementation of bswap requires the input be zero
-                   extended.  In the case of the loads, we simply know that
-                   gen_op_ld_v via gen_ldst_modrm does that already.  */
-                if ((b & 1) == 0) {
-                    gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
-                } else {
-                    switch (ot) {
-                    case MO_16:
-                        tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
-                        break;
-                    default:
-                        tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
-                        break;
-                    case MO_64:
-                        tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
-                        break;
-                    }
-                }
-
-                switch (ot) {
-                case MO_16:
-                    tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
-                    break;
-                default:
-                    tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
-                    break;
-#ifdef TARGET_X86_64
-                case MO_64:
-                    tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
-                    break;
-#endif
-                }
-
+                gen_lea_modrm(env, s, modrm);
                 if ((b & 1) == 0) {
+                    tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
+                                       s->mem_index, ot | MO_BE);
                     gen_op_mov_reg_T0(ot, reg);
                 } else {
-                    gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
+                    tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
+                                       s->mem_index, ot | MO_BE);
                 }
                 break;
 
commit 4eeb3939b5b4731747cb38a9e6b8fb20062b5ef1
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:55:59 2013 -1000

    target-i386: Remove unused arguments to gen_lea_modrm
    
    The reg_ptr and offset_ptr outputs are universally unused.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0a414c4..cfd75dc 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -1957,15 +1957,13 @@ static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
     }
 }
 
-static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
-                          int *reg_ptr, int *offset_ptr)
+static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
 {
     target_long disp;
     int havesib;
     int base;
     int index;
     int scale;
-    int opreg;
     int mod, rm, code, override, must_add_seg;
     TCGv sum;
 
@@ -2060,7 +2058,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
                     tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
                 }
                 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-                goto done;
+                return;
             }
 
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
@@ -2136,12 +2134,6 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm,
             gen_op_addl_A0_seg(s, override);
         }
     }
-
- done:
-    opreg = OR_A0;
-    disp = 0;
-    *reg_ptr = opreg;
-    *offset_ptr = disp;
 }
 
 static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
@@ -2221,7 +2213,7 @@ static void gen_add_A0_ds_seg(DisasContext *s)
 static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
                            int ot, int reg, int is_store)
 {
-    int mod, rm, opreg, disp;
+    int mod, rm;
 
     mod = (modrm >> 6) & 3;
     rm = (modrm & 7) | REX_B(s);
@@ -2236,7 +2228,7 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
                 gen_op_mov_reg_T0(ot, reg);
         }
     } else {
-        gen_lea_modrm(env, s, modrm, &opreg, &disp);
+        gen_lea_modrm(env, s, modrm);
         if (is_store) {
             if (reg != OR_TMP0)
                 gen_op_mov_TN_reg(ot, 0, reg);
@@ -3116,7 +3108,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     target_ulong pc_start, int rex_r)
 {
     int b1, op1_offset, op2_offset, is_xmm, val, ot;
-    int modrm, mod, rm, reg, reg_addr, offset_addr;
+    int modrm, mod, rm, reg;
     SSEFunc_0_epp sse_fn_epp;
     SSEFunc_0_eppi sse_fn_eppi;
     SSEFunc_0_ppi sse_fn_ppi;
@@ -3187,7 +3179,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x0e7: /* movntq */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
             break;
         case 0x1e7: /* movntdq */
@@ -3195,20 +3187,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x12b: /* movntps */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             break;
         case 0x3f0: /* lddqu */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             break;
         case 0x22b: /* movntss */
         case 0x32b: /* movntsd */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             if (b1 & 1) {
                 gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             } else {
@@ -3251,7 +3243,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x6f: /* movq mm, ea */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
             } else {
                 rm = (modrm & 7);
@@ -3268,7 +3260,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x16f: /* movdqa xmm, ea */
         case 0x26f: /* movdqu xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3278,7 +3270,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x210: /* movss xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_movl_T0_0();
@@ -3293,7 +3285,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x310: /* movsd xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
                 gen_op_movl_T0_0();
@@ -3308,7 +3300,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x012: /* movlps */
         case 0x112: /* movlpd */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3320,7 +3312,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x212: /* movsldup */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3336,7 +3328,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x312: /* movddup */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3350,7 +3342,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x016: /* movhps */
         case 0x116: /* movhpd */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(1)));
             } else {
@@ -3362,7 +3354,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x216: /* movshdup */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3427,7 +3419,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x27e: /* movq xmm, ea */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_ldq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3439,7 +3431,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x7f: /* movq ea, mm */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
             } else {
                 rm = (modrm & 7);
@@ -3454,7 +3446,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x17f: /* movdqa ea, xmm */
         case 0x27f: /* movdqu ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
             } else {
                 rm = (modrm & 7) | REX_B(s);
@@ -3464,7 +3456,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x211: /* movss ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
             } else {
@@ -3475,7 +3467,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x311: /* movsd ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_stq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3487,7 +3479,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x013: /* movlps */
         case 0x113: /* movlpd */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_stq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3497,7 +3489,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x017: /* movhps */
         case 0x117: /* movhpd */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_stq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(1)));
             } else {
@@ -3563,7 +3555,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x12a: /* cvtpi2pd */
             gen_helper_enter_mmx(cpu_env);
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 op2_offset = offsetof(CPUX86State,mmx_t0);
                 gen_ldq_env_A0(s, op2_offset);
             } else {
@@ -3608,7 +3600,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x12d: /* cvtpd2pi */
             gen_helper_enter_mmx(cpu_env);
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 op2_offset = offsetof(CPUX86State,xmm_t0);
                 gen_ldo_env_A0(s, op2_offset);
             } else {
@@ -3639,7 +3631,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x32d: /* cvtsd2si */
             ot = (s->dflag == 2) ? MO_64 : MO_32;
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 if ((b >> 8) & 1) {
                     gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
                 } else {
@@ -3705,7 +3697,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x1d6: /* movq ea, xmm */
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_stq_env_A0(s, offsetof(CPUX86State,
                                            xmm_regs[reg].XMM_Q(0)));
             } else {
@@ -3773,7 +3765,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
                 } else {
                     op2_offset = offsetof(CPUX86State,xmm_t0);
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     switch (b) {
                     case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
                     case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
@@ -3807,7 +3799,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                 } else {
                     op2_offset = offsetof(CPUX86State,mmx_t0);
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     gen_ldq_env_A0(s, op2_offset);
                 }
             }
@@ -4240,7 +4232,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 ot = (s->dflag == 2) ? MO_64 : MO_32;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3)
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                 reg = ((modrm >> 3) & 7) | rex_r;
                 val = cpu_ldub_code(env, s->pc++);
                 switch (b) {
@@ -4379,7 +4371,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
                 } else {
                     op2_offset = offsetof(CPUX86State,xmm_t0);
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     gen_ldo_env_A0(s, op2_offset);
                 }
             } else {
@@ -4388,7 +4380,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
                 } else {
                     op2_offset = offsetof(CPUX86State,mmx_t0);
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     gen_ldq_env_A0(s, op2_offset);
                 }
             }
@@ -4455,7 +4447,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         if (is_xmm) {
             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 op2_offset = offsetof(CPUX86State,xmm_t0);
                 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
                                 b == 0xc2)) {
@@ -4479,7 +4471,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         } else {
             op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 op2_offset = offsetof(CPUX86State,mmx_t0);
                 gen_ldq_env_A0(s, op2_offset);
             } else {
@@ -4561,7 +4553,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 {
     int b, prefixes, aflag, dflag;
     int shift, ot;
-    int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
+    int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
 
@@ -4756,7 +4748,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 mod = (modrm >> 6) & 3;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3) {
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     opreg = OR_TMP0;
                 } else if (op == OP_XORL && rm == reg) {
                 xor_zero:
@@ -4777,7 +4769,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 reg = ((modrm >> 3) & 7) | rex_r;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3) {
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
                 } else if (op == OP_XORL && rm == reg) {
                     goto xor_zero;
@@ -4819,7 +4811,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     s->rip_offset = 1;
                 else
                     s->rip_offset = insn_const_size(ot);
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 opreg = OR_TMP0;
             } else {
                 opreg = rm;
@@ -4865,7 +4857,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod != 3) {
             if (op == 0)
                 s->rip_offset = insn_const_size(ot);
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
@@ -5076,7 +5068,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
         }
         if (mod != 3) {
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             if (op >= 2 && op != 3 && op != 5)
                 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
@@ -5298,7 +5290,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_reg_T1(ot, reg);
             gen_op_mov_reg_T0(ot, rm);
         } else {
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_op_addl_T0_T1();
@@ -5330,7 +5322,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_mov_v_reg(ot, t0, rm);
             } else {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 tcg_gen_mov_tl(a0, cpu_A0);
                 gen_op_ld_v(s, ot, t0, a0);
                 rm = 0; /* avoid warning */
@@ -5378,7 +5370,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_jmp_im(pc_start - s->cs_base);
             gen_update_cc_op(s);
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_helper_cmpxchg16b(cpu_env, cpu_A0);
         } else
 #endif        
@@ -5387,7 +5379,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_jmp_im(pc_start - s->cs_base);
             gen_update_cc_op(s);
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_helper_cmpxchg8b(cpu_env, cpu_A0);
         }
         set_cc_op(s, CC_OP_EFLAGS);
@@ -5557,7 +5549,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         mod = (modrm >> 6) & 3;
         if (mod != 3) {
             s->rip_offset = insn_const_size(ot);
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
         }
         val = insn_get(env, s, ot);
         gen_op_movl_T0_im(val);
@@ -5652,7 +5644,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_T0(d_ot, reg);
             }
@@ -5670,7 +5662,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         s->override = -1;
         val = s->addseg;
         s->addseg = 0;
-        gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm);
         s->addseg = val;
         gen_op_mov_reg_A0(ot - MO_16, reg);
         break;
@@ -5783,7 +5775,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_reg_T0(ot, rm);
             gen_op_mov_reg_T1(ot, reg);
         } else {
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_op_mov_TN_reg(ot, 0, reg);
             /* for xchg, lock is implicit */
             if (!(prefixes & PREFIX_LOCK))
@@ -5818,7 +5810,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
-        gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm);
         gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
         gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
         /* load the segment first to handle exceptions properly */
@@ -5853,7 +5845,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 if (shift == 2) {
                     s->rip_offset = 1;
                 }
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 opreg = OR_TMP0;
             } else {
                 opreg = (modrm & 7) | REX_B(s);
@@ -5903,7 +5895,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         rm = (modrm & 7) | REX_B(s);
         reg = ((modrm >> 3) & 7) | rex_r;
         if (mod != 3) {
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             opreg = OR_TMP0;
         } else {
             opreg = rm;
@@ -5934,7 +5926,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
         if (mod != 3) {
             /* memory op */
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             switch(op) {
             case 0x00 ... 0x07: /* fxxxs */
             case 0x10 ... 0x17: /* fixxxl */
@@ -6925,7 +6917,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         rm = (modrm & 7) | REX_B(s);
         if (mod != 3) {
             s->rip_offset = 1;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
@@ -6956,7 +6948,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         rm = (modrm & 7) | REX_B(s);
         gen_op_mov_TN_reg(MO_32, 1, reg);
         if (mod != 3) {
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             /* specific case: we need to add a displacement */
             gen_exts(ot, cpu_T[1]);
             tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
@@ -7213,7 +7205,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod == 3)
             goto illegal_op;
         gen_op_mov_TN_reg(ot, 0, reg);
-        gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm);
         gen_jmp_im(pc_start - s->cs_base);
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
         if (ot == MO_16) {
@@ -7461,7 +7453,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (mod == 3)
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
             gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
             gen_add_A0_im(s, 2);
@@ -7524,7 +7516,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 }
             } else { /* sidt */
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
                 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 gen_add_A0_im(s, 2);
@@ -7625,7 +7617,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             } else {
                 gen_svm_check_intercept(s, pc_start,
                                         op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
                 gen_add_A0_im(s, 2);
                 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
@@ -7667,7 +7659,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 } else {
                     gen_update_cc_op(s);
                     gen_jmp_im(pc_start - s->cs_base);
-                    gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                    gen_lea_modrm(env, s, modrm);
                     gen_helper_invlpg(cpu_env, cpu_A0);
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
@@ -7746,7 +7738,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_T0(d_ot, reg);
             }
@@ -7767,7 +7759,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             mod = (modrm >> 6) & 3;
             rm = modrm & 7;
             if (mod != 3) {
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
                 gen_op_ld_v(s, ot, t0, cpu_A0);
                 a0 = tcg_temp_local_new();
                 tcg_gen_mov_tl(a0, cpu_A0);
@@ -7837,7 +7829,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 3: /* prefetchnt0 */
             if (mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             /* nothing more to do */
             break;
         default: /* nop (multi byte) */
@@ -7964,7 +7956,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                 break;
             }
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
@@ -7977,7 +7969,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
                 break;
             }
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_fxrstor(cpu_env, cpu_A0,
@@ -7992,7 +7984,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
                 mod == 3)
                 goto illegal_op;
-            gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+            gen_lea_modrm(env, s, modrm);
             if (op == 2) {
                 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -8017,7 +8009,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 /* clflush */
                 if (!(s->cpuid_features & CPUID_CLFLUSH))
                     goto illegal_op;
-                gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+                gen_lea_modrm(env, s, modrm);
             }
             break;
         default:
@@ -8029,7 +8021,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
-        gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
+        gen_lea_modrm(env, s, modrm);
         /* ignore for now */
         break;
     case 0x1aa: /* rsm */
commit 4b1fe0671f5f9324b570c5ec165c67b36b05e7d2
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:32:39 2013 -1000

    target-i386: Tidy movsl
    
    Always perform a sign-extending load.  In the extremely unlikely
    case that we've used an 0x66 prefix, the extension to 64-bits is
    unnecessary but not wrong; the store will still examine only 16 bits.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index f3baa4d..0a414c4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7747,11 +7747,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                if (d_ot == MO_64) {
-                    gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
-                } else {
-                    gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
-                }
+                gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_T0(d_ot, reg);
             }
         } else
commit c8fbc479674d00a8f9dd63f9a9d4978c4c4b96d9
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:28:40 2013 -1000

    target-i386: Tidy mov[sz][bw]
    
    We can use the MO_SIGN bit to tidy the reg-reg switch statement
    as well as pass it on to gen_op_ld_v, eliminating one call.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 9205b72..f3baa4d 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -5618,11 +5618,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1be: /* movsbS Gv, Eb */
     case 0x1bf: /* movswS Gv, Eb */
         {
-            int d_ot;
+            TCGMemOp d_ot;
+            TCGMemOp s_ot;
+
             /* d_ot is the size of destination */
             d_ot = dflag + MO_16;
             /* ot is the size of source */
             ot = (b & 1) + MO_8;
+            /* s_ot is the sign+size of source */
+            s_ot = b & 8 ? MO_SIGN | ot : ot;
+
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -5630,29 +5635,25 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
             if (mod == 3) {
                 gen_op_mov_TN_reg(ot, 0, rm);
-                switch(ot | (b & 8)) {
-                case MO_8:
+                switch (s_ot) {
+                case MO_UB:
                     tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
                     break;
-                case MO_8 | 8:
+                case MO_SB:
                     tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
                     break;
-                case MO_16:
+                case MO_UW:
                     tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
                     break;
                 default:
-                case MO_16 | 8:
+                case MO_SW:
                     tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
                     break;
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                if (b & 8) {
-                    gen_op_ld_v(s, ot | MO_SIGN, cpu_T[0], cpu_A0);
-                } else {
-                    gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
-                }
+                gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_T0(d_ot, reg);
             }
         }
commit ee3138da2f76b415cbce6466aa4083a84fc26241
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:16:45 2013 -1000

    target-i386: Fix typo in gen_push_T1
    
    By inspection, obviously we should be storing T[1] not T[0].
    This could only happen for x86_64 in 64-bit mode with 0x66
    prefix to call insn -- i.e. never.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index a1a23a6..9205b72 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2488,7 +2488,7 @@ static void gen_push_T1(DisasContext *s)
             gen_op_st_v(s, MO_64, cpu_T[1], cpu_A0);
         } else {
             gen_op_addq_A0_im(-2);
-            gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
+            gen_op_st_v(s, MO_16, cpu_T[1], cpu_A0);
         }
         gen_op_mov_reg_A0(2, R_ESP);
     } else
commit b5afc104947369cd3d49de88dee8629193639b46
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:14:26 2013 -1000

    target-i386: Remove gen_op_st_T1_A0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 725d5ec..a1a23a6 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -586,11 +586,6 @@ static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
     tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
 }
 
-static inline void gen_op_st_T1_A0(DisasContext *s, int idx)
-{
-    gen_op_st_v(s, idx, cpu_T[1], cpu_A0);
-}
-
 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
 {
     if (d == OR_TMP0) {
@@ -2490,7 +2485,7 @@ static void gen_push_T1(DisasContext *s)
         gen_op_movq_A0_reg(R_ESP);
         if (s->dflag) {
             gen_op_addq_A0_im(-8);
-            gen_op_st_T1_A0(s, MO_64);
+            gen_op_st_v(s, MO_64, cpu_T[1], cpu_A0);
         } else {
             gen_op_addq_A0_im(-2);
             gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
@@ -2512,7 +2507,7 @@ static void gen_push_T1(DisasContext *s)
             gen_op_andl_A0_ffff();
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_st_T1_A0(s, s->dflag + 1);
+        gen_op_st_v(s, s->dflag + 1, cpu_T[1], cpu_A0);
 
         if (s->ss32 && !s->addseg)
             gen_op_mov_reg_A0(1, R_ESP);
commit fd8ca9f6f5250771207f7dbe88bb804ac0b90a39
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 08:12:01 2013 -1000

    target-i386: Remove gen_op_st_T0_A0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index f531726..725d5ec 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -586,11 +586,6 @@ static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
     tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
 }
 
-static inline void gen_op_st_T0_A0(DisasContext *s, int idx)
-{
-    gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
-}
-
 static inline void gen_op_st_T1_A0(DisasContext *s, int idx)
 {
     gen_op_st_v(s, idx, cpu_T[1], cpu_A0);
@@ -599,7 +594,7 @@ static inline void gen_op_st_T1_A0(DisasContext *s, int idx)
 static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
 {
     if (d == OR_TMP0) {
-        gen_op_st_T0_A0(s, idx);
+        gen_op_st_v(s, idx, cpu_T[0], cpu_A0);
     } else {
         gen_op_mov_reg_T0(idx, d);
     }
@@ -801,7 +796,7 @@ static inline void gen_movs(DisasContext *s, int ot)
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     gen_string_movl_A0_EDI(s);
-    gen_op_st_T0_A0(s, ot);
+    gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_ESI);
     gen_op_add_reg_T0(s->aflag, R_EDI);
@@ -1226,7 +1221,7 @@ static inline void gen_stos(DisasContext *s, int ot)
 {
     gen_op_mov_TN_reg(MO_32, 0, R_EAX);
     gen_string_movl_A0_EDI(s);
-    gen_op_st_T0_A0(s, ot);
+    gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
 }
@@ -1268,12 +1263,12 @@ static inline void gen_ins(DisasContext *s, int ot)
     /* Note: we must do this dummy write first to be restartable in
        case of page fault. */
     gen_op_movl_T0_0();
-    gen_op_st_T0_A0(s, ot);
+    gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_mov_TN_reg(MO_16, 1, R_EDX);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
-    gen_op_st_T0_A0(s, ot);
+    gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
     if (use_icount)
@@ -2250,7 +2245,7 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
         if (is_store) {
             if (reg != OR_TMP0)
                 gen_op_mov_TN_reg(ot, 0, reg);
-            gen_op_st_T0_A0(s, ot);
+            gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
             if (reg != OR_TMP0)
@@ -2454,10 +2449,10 @@ static void gen_push_T0(DisasContext *s)
         gen_op_movq_A0_reg(R_ESP);
         if (s->dflag) {
             gen_op_addq_A0_im(-8);
-            gen_op_st_T0_A0(s, MO_64);
+            gen_op_st_v(s, MO_64, cpu_T[0], cpu_A0);
         } else {
             gen_op_addq_A0_im(-2);
-            gen_op_st_T0_A0(s, MO_16);
+            gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
         }
         gen_op_mov_reg_A0(2, R_ESP);
     } else
@@ -2478,7 +2473,7 @@ static void gen_push_T0(DisasContext *s)
             tcg_gen_mov_tl(cpu_T[1], cpu_A0);
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_st_T0_A0(s, s->dflag + 1);
+        gen_op_st_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
         if (s->ss32 && !s->addseg)
             gen_op_mov_reg_A0(1, R_ESP);
         else
@@ -2498,7 +2493,7 @@ static void gen_push_T1(DisasContext *s)
             gen_op_st_T1_A0(s, MO_64);
         } else {
             gen_op_addq_A0_im(-2);
-            gen_op_st_T0_A0(s, MO_16);
+            gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
         }
         gen_op_mov_reg_A0(2, R_ESP);
     } else
@@ -2583,7 +2578,7 @@ static void gen_pusha(DisasContext *s)
         gen_op_addl_A0_seg(s, R_SS);
     for(i = 0;i < 8; i++) {
         gen_op_mov_TN_reg(MO_32, 0, 7 - i);
-        gen_op_st_T0_A0(s, MO_16 + s->dflag);
+        gen_op_st_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
         gen_op_addl_A0_im(2 <<  s->dflag);
     }
     gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
@@ -2627,7 +2622,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
 
         /* push bp */
         gen_op_mov_TN_reg(MO_32, 0, R_EBP);
-        gen_op_st_T0_A0(s, ot);
+        gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         if (level) {
             /* XXX: must save state */
             gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
@@ -2652,7 +2647,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
             gen_op_addl_A0_seg(s, R_SS);
         /* push bp */
         gen_op_mov_TN_reg(MO_32, 0, R_EBP);
-        gen_op_st_T0_A0(s, ot);
+        gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
         if (level) {
             /* XXX: must save state */
             gen_helper_enter_level(cpu_env, tcg_const_i32(level),
@@ -3224,7 +3219,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                     xmm_regs[reg].XMM_L(0)));
-                gen_op_st_T0_A0(s, MO_32);
+                gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
             }
             break;
         case 0x6e: /* movd mm, ea */
@@ -3476,7 +3471,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
-                gen_op_st_T0_A0(s, MO_32);
+                gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
@@ -4891,7 +4886,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 2: /* not */
             tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
             if (mod != 3) {
-                gen_op_st_T0_A0(s, ot);
+                gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             } else {
                 gen_op_mov_reg_T0(ot, rm);
             }
@@ -4899,7 +4894,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 3: /* neg */
             tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
             if (mod != 3) {
-                gen_op_st_T0_A0(s, ot);
+                gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             } else {
                 gen_op_mov_reg_T0(ot, rm);
             }
@@ -5312,7 +5307,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_op_addl_T0_T1();
-            gen_op_st_T0_A0(s, ot);
+            gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             gen_op_mov_reg_T1(ot, reg);
         }
         gen_op_update2_cc();
@@ -5571,10 +5566,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         val = insn_get(env, s, ot);
         gen_op_movl_T0_im(val);
-        if (mod != 3)
-            gen_op_st_T0_A0(s, ot);
-        else
+        if (mod != 3) {
+            gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
+        } else {
             gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
+        }
         break;
     case 0x8a:
     case 0x8b: /* mov Ev, Gv */
@@ -5715,7 +5711,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_op_mov_reg_T0(ot, R_EAX);
             } else {
                 gen_op_mov_TN_reg(ot, 0, R_EAX);
-                gen_op_st_T0_A0(s, ot);
+                gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             }
         }
         break;
@@ -5797,7 +5793,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_lock();
             gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
-            gen_op_st_T0_A0(s, ot);
+            gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_unlock();
             gen_op_mov_reg_T1(ot, reg);
@@ -6021,7 +6017,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 1:
                         gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, MO_32);
+                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
                         break;
                     case 2:
                         gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
@@ -6032,7 +6028,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     default:
                         gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, MO_16);
+                        gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                         break;
                     }
                     gen_helper_fpop(cpu_env);
@@ -6042,12 +6038,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 0:
                         gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, MO_32);
+                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
                         break;
                     case 1:
                         gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, MO_32);
+                        gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
                         break;
                     case 2:
                         gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
@@ -6058,7 +6054,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     default:
                         gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, MO_16);
+                        gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                         break;
                     }
                     if ((op & 7) == 3)
@@ -6084,7 +6080,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x0f: /* fnstcw mem */
                 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_T0_A0(s, MO_16);
+                gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 break;
             case 0x1d: /* fldt mem */
                 gen_update_cc_op(s);
@@ -6110,7 +6106,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x2f: /* fnstsw mem */
                 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_T0_A0(s, MO_16);
+                gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 break;
             case 0x3c: /* fbld */
                 gen_update_cc_op(s);
@@ -7004,10 +7000,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         }
         set_cc_op(s, CC_OP_SARB + ot);
         if (op != 0) {
-            if (mod != 3)
-                gen_op_st_T0_A0(s, ot);
-            else
+            if (mod != 3) {
+                gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
+            } else {
                 gen_op_mov_reg_T0(ot, rm);
+            }
             tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
             tcg_gen_movi_tl(cpu_cc_dst, 0);
         }
@@ -7470,12 +7467,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
-            gen_op_st_T0_A0(s, MO_16);
+            gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
             gen_add_A0_im(s, 2);
             tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
             if (!s->dflag)
                 gen_op_andl_T0_im(0xffffff);
-            gen_op_st_T0_A0(s, CODE64(s) + MO_32);
+            gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
             break;
         case 1:
             if (mod == 3) {
@@ -7533,12 +7530,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
-                gen_op_st_T0_A0(s, MO_16);
+                gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
                 gen_add_A0_im(s, 2);
                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
                 if (!s->dflag)
                     gen_op_andl_T0_im(0xffffff);
-                gen_op_st_T0_A0(s, CODE64(s) + MO_32);
+                gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
             }
             break;
         case 2: /* lgdt */
@@ -8010,7 +8007,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
-                gen_op_st_T0_A0(s, MO_32);
+                gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
             }
             break;
         case 5: /* lfence */
commit d4faa3e08a13aa70bf0d9709610ab27713167df9
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 10:59:43 2013 -0700

    target-i386: Introduce gen_op_st_rm_T0_A0
    
    Too many places have the same test vs OR_TMP0 to indicate
    a write back to memory.  Hoist that to a subroutine.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 1e425e3..f531726 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -596,6 +596,15 @@ static inline void gen_op_st_T1_A0(DisasContext *s, int idx)
     gen_op_st_v(s, idx, cpu_T[1], cpu_A0);
 }
 
+static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
+{
+    if (d == OR_TMP0) {
+        gen_op_st_T0_A0(s, idx);
+    } else {
+        gen_op_mov_reg_T0(idx, d);
+    }
+}
+
 static inline void gen_jmp_im(target_ulong pc)
 {
     tcg_gen_movi_tl(cpu_tmp0, pc);
@@ -1403,10 +1412,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
         gen_compute_eflags_c(s1, cpu_tmp4);
         tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
         tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update3_cc(cpu_tmp4);
         set_cc_op(s1, CC_OP_ADCB + ot);
         break;
@@ -1414,57 +1420,39 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
         gen_compute_eflags_c(s1, cpu_tmp4);
         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update3_cc(cpu_tmp4);
         set_cc_op(s1, CC_OP_SBBB + ot);
         break;
     case OP_ADDL:
         gen_op_addl_T0_T1();
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update2_cc();
         set_cc_op(s1, CC_OP_ADDB + ot);
         break;
     case OP_SUBL:
         tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
         tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update2_cc();
         set_cc_op(s1, CC_OP_SUBB + ot);
         break;
     default:
     case OP_ANDL:
         tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update1_cc();
         set_cc_op(s1, CC_OP_LOGICB + ot);
         break;
     case OP_ORL:
         tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update1_cc();
         set_cc_op(s1, CC_OP_LOGICB + ot);
         break;
     case OP_XORL:
         tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-        if (d != OR_TMP0)
-            gen_op_mov_reg_T0(ot, d);
-        else
-            gen_op_st_T0_A0(s1, ot);
+        gen_op_st_rm_T0_A0(s1, ot, d);
         gen_op_update1_cc();
         set_cc_op(s1, CC_OP_LOGICB + ot);
         break;
@@ -1493,10 +1481,7 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c)
         tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
         set_cc_op(s1, CC_OP_DECB + ot);
     }
-    if (d != OR_TMP0)
-        gen_op_mov_reg_T0(ot, d);
-    else
-        gen_op_st_T0_A0(s1, ot);
+    gen_op_st_rm_T0_A0(s1, ot, d);
     tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
 }
 
@@ -1576,11 +1561,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
     }
 
     /* store */
-    if (op1 == OR_TMP0) {
-        gen_op_st_T0_A0(s, ot);
-    } else {
-        gen_op_mov_reg_T0(ot, op1);
-    }
+    gen_op_st_rm_T0_A0(s, ot, op1);
 
     gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
 }
@@ -1615,11 +1596,8 @@ static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
     }
 
     /* store */
-    if (op1 == OR_TMP0)
-        gen_op_st_T0_A0(s, ot);
-    else
-        gen_op_mov_reg_T0(ot, op1);
-        
+    gen_op_st_rm_T0_A0(s, ot, op1);
+
     /* update eflags if non zero shift */
     if (op2 != 0) {
         tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
@@ -1683,11 +1661,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
     }
 
     /* store */
-    if (op1 == OR_TMP0) {
-        gen_op_st_T0_A0(s, ot);
-    } else {
-        gen_op_mov_reg_T0(ot, op1);
-    }
+    gen_op_st_rm_T0_A0(s, ot, op1);
 
     /* We'll need the flags computed into CC_SRC.  */
     gen_compute_eflags(s);
@@ -1778,11 +1752,7 @@ static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
     }
 
     /* store */
-    if (op1 == OR_TMP0) {
-        gen_op_st_T0_A0(s, ot);
-    } else {
-        gen_op_mov_reg_T0(ot, op1);
-    }
+    gen_op_st_rm_T0_A0(s, ot, op1);
 
     if (op2 != 0) {
         /* Compute the flags into CC_SRC.  */
@@ -1855,10 +1825,7 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
         }
     }
     /* store */
-    if (op1 == OR_TMP0)
-        gen_op_st_T0_A0(s, ot);
-    else
-        gen_op_mov_reg_T0(ot, op1);
+    gen_op_st_rm_T0_A0(s, ot, op1);
 }
 
 /* XXX: add faster immediate case */
@@ -1937,11 +1904,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
     }
 
     /* store */
-    if (op1 == OR_TMP0) {
-        gen_op_st_T0_A0(s, ot);
-    } else {
-        gen_op_mov_reg_T0(ot, op1);
-    }
+    gen_op_st_rm_T0_A0(s, ot, op1);
 
     gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
     tcg_temp_free(count);
commit dc732b76fa6f30bbfc46f721d52a67d0505a1445
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 10:43:41 2013 -0700

    target-i386: Remove gen_op_lds_T0_A0
    
    Replace its users by gen_op_ld_v with the MO_SIGN bit set.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index b747e99..1e425e3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -576,11 +576,6 @@ static inline void gen_op_addq_A0_reg_sN(int shift, int reg)
 }
 #endif
 
-static inline void gen_op_lds_T0_A0(DisasContext *s, int idx)
-{
-    tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0, s->mem_index, idx | MO_LE | MO_SIGN);
-}
-
 static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
 {
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
@@ -5700,7 +5695,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             } else {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 if (b & 8) {
-                    gen_op_lds_T0_A0(s, ot);
+                    gen_op_ld_v(s, ot | MO_SIGN, cpu_T[0], cpu_A0);
                 } else {
                     gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
                 }
@@ -6012,7 +6007,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_lds_T0_A0(s, MO_16);
+                        gen_op_ld_v(s, MO_SW, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6051,7 +6046,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_lds_T0_A0(s, MO_16);
+                        gen_op_ld_v(s, MO_SW, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -7797,7 +7792,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             } else {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 if (d_ot == MO_64) {
-                    gen_op_lds_T0_A0(s, MO_32);
+                    gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
                 } else {
                     gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 }
commit 0f712e109becb8c0e911209967a014ce3df21a71
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 10:39:41 2013 -0700

    target-i386: Remove gen_op_ld_T1_A0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 97bbc1f..b747e99 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -586,11 +586,6 @@ static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
 }
 
-static inline void gen_op_ld_T1_A0(DisasContext *s, int idx)
-{
-    gen_op_ld_v(s, idx, cpu_T[1], cpu_A0);
-}
-
 static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
 {
     tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
@@ -1244,7 +1239,7 @@ static inline void gen_lods(DisasContext *s, int ot)
 static inline void gen_scas(DisasContext *s, int ot)
 {
     gen_string_movl_A0_EDI(s);
-    gen_op_ld_T1_A0(s, ot);
+    gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
     gen_op(s, OP_CMPL, ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
@@ -1253,7 +1248,7 @@ static inline void gen_scas(DisasContext *s, int ot)
 static inline void gen_cmps(DisasContext *s, int ot)
 {
     gen_string_movl_A0_EDI(s);
-    gen_op_ld_T1_A0(s, ot);
+    gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
     gen_string_movl_A0_ESI(s);
     gen_op(s, OP_CMPL, ot, OR_TMP0);
     gen_op_movl_T0_Dshift(ot);
@@ -4835,7 +4830,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3) {
                     gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                    gen_op_ld_T1_A0(s, ot);
+                    gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
                 } else if (op == OP_XORL && rm == reg) {
                     goto xor_zero;
                 } else {
@@ -5166,7 +5161,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_eob(s);
             break;
         case 3: /* lcall Ev */
-            gen_op_ld_T1_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
             gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_lcall:
@@ -5192,7 +5187,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_eob(s);
             break;
         case 5: /* ljmp Ev */
-            gen_op_ld_T1_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
             gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_ljmp:
@@ -5357,7 +5352,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             gen_op_mov_TN_reg(ot, 0, reg);
-            gen_op_ld_T1_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_op_addl_T0_T1();
             gen_op_st_T0_A0(s, ot);
             gen_op_mov_reg_T1(ot, reg);
@@ -5843,7 +5838,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             /* for xchg, lock is implicit */
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_lock();
-            gen_op_ld_T1_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
             gen_op_st_T0_A0(s, ot);
             if (!(prefixes & PREFIX_LOCK))
                 gen_helper_unlock();
@@ -5874,7 +5869,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod == 3)
             goto illegal_op;
         gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-        gen_op_ld_T1_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
         gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
         /* load the segment first to handle exceptions properly */
         gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
@@ -7680,7 +7675,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_svm_check_intercept(s, pc_start,
                                         op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                gen_op_ld_T1_A0(s, MO_16);
+                gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
                 gen_add_A0_im(s, 2);
                 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
                 if (!s->dflag)
commit cc1a80dfb369974bb275387f9559eafdcb6e08eb
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 10:35:24 2013 -0700

    target-i386: Remove gen_op_ldu_T0_A0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6efe64f..97bbc1f 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -586,11 +586,6 @@ static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
 }
 
-static inline void gen_op_ldu_T0_A0(DisasContext *s, int idx)
-{
-    gen_op_ld_v(s, idx, cpu_T[0], cpu_A0);
-}
-
 static inline void gen_op_ld_T1_A0(DisasContext *s, int idx)
 {
     gen_op_ld_v(s, idx, cpu_T[1], cpu_A0);
@@ -5173,7 +5168,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 3: /* lcall Ev */
             gen_op_ld_T1_A0(s, ot);
             gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
-            gen_op_ldu_T0_A0(s, MO_16);
+            gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_lcall:
             if (s->pe && !s->vm86) {
                 gen_update_cc_op(s);
@@ -5199,7 +5194,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 5: /* ljmp Ev */
             gen_op_ld_T1_A0(s, ot);
             gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
-            gen_op_ldu_T0_A0(s, MO_16);
+            gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         do_ljmp:
             if (s->pe && !s->vm86) {
                 gen_update_cc_op(s);
@@ -5712,7 +5707,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 if (b & 8) {
                     gen_op_lds_T0_A0(s, ot);
                 } else {
-                    gen_op_ldu_T0_A0(s, ot);
+                    gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             }
@@ -5791,7 +5786,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
         }
         gen_add_A0_ds_seg(s);
-        gen_op_ldu_T0_A0(s, MO_8);
+        gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
         gen_op_mov_reg_T0(MO_8, R_EAX);
         break;
     case 0xb0 ... 0xb7: /* mov R, Ib */
@@ -5882,7 +5877,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_op_ld_T1_A0(s, ot);
         gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
         /* load the segment first to handle exceptions properly */
-        gen_op_ldu_T0_A0(s, MO_16);
+        gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
         /* then put the data */
         gen_op_mov_reg_T1(ot, reg);
commit 909be183823febfe579766e89f9a499ff4da3e47
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 10:30:24 2013 -0700

    target-i386: Remove gen_op_ld_T0_A0
    
    Propagate its definition into all users.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index e7e18e3..6efe64f 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -586,12 +586,6 @@ static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
     tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
 }
 
-/* XXX: always use ldu or lds */
-static inline void gen_op_ld_T0_A0(DisasContext *s, int idx)
-{
-    gen_op_ld_v(s, idx, cpu_T[0], cpu_A0);
-}
-
 static inline void gen_op_ldu_T0_A0(DisasContext *s, int idx)
 {
     gen_op_ld_v(s, idx, cpu_T[0], cpu_A0);
@@ -811,7 +805,7 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
 static inline void gen_movs(DisasContext *s, int ot)
 {
     gen_string_movl_A0_ESI(s);
-    gen_op_ld_T0_A0(s, ot);
+    gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     gen_string_movl_A0_EDI(s);
     gen_op_st_T0_A0(s, ot);
     gen_op_movl_T0_Dshift(ot);
@@ -1246,7 +1240,7 @@ static inline void gen_stos(DisasContext *s, int ot)
 static inline void gen_lods(DisasContext *s, int ot)
 {
     gen_string_movl_A0_ESI(s);
-    gen_op_ld_T0_A0(s, ot);
+    gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     gen_op_mov_reg_T0(ot, R_EAX);
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_ESI);
@@ -1297,7 +1291,7 @@ static inline void gen_outs(DisasContext *s, int ot)
     if (use_icount)
         gen_io_start();
     gen_string_movl_A0_ESI(s);
-    gen_op_ld_T0_A0(s, ot);
+    gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
 
     gen_op_mov_TN_reg(MO_16, 1, R_EDX);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
@@ -1417,7 +1411,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
     if (d != OR_TMP0) {
         gen_op_mov_TN_reg(ot, 0, d);
     } else {
-        gen_op_ld_T0_A0(s1, ot);
+        gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
     }
     switch(op) {
     case OP_ADCL:
@@ -1501,10 +1495,11 @@ static void gen_op(DisasContext *s1, int op, int ot, int d)
 /* if d == OR_TMP0, it means memory operand (address in A0) */
 static void gen_inc(DisasContext *s1, int ot, int d, int c)
 {
-    if (d != OR_TMP0)
+    if (d != OR_TMP0) {
         gen_op_mov_TN_reg(ot, 0, d);
-    else
-        gen_op_ld_T0_A0(s1, ot);
+    } else {
+        gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
+    }
     gen_compute_eflags_c(s1, cpu_cc_src);
     if (c > 0) {
         tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
@@ -1572,7 +1567,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
 
     /* load */
     if (op1 == OR_TMP0) {
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
         gen_op_mov_TN_reg(ot, 0, op1);
     }
@@ -1612,7 +1607,7 @@ static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
 
     /* load */
     if (op1 == OR_TMP0)
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     else
         gen_op_mov_TN_reg(ot, 0, op1);
 
@@ -1663,7 +1658,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
 
     /* load */
     if (op1 == OR_TMP0) {
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
         gen_op_mov_TN_reg(ot, 0, op1);
     }
@@ -1753,7 +1748,7 @@ static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
 
     /* load */
     if (op1 == OR_TMP0) {
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
         gen_op_mov_TN_reg(ot, 0, op1);
     }
@@ -1835,7 +1830,7 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
 
     /* load */
     if (op1 == OR_TMP0)
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     else
         gen_op_mov_TN_reg(ot, 0, op1);
     
@@ -1890,7 +1885,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
 
     /* load */
     if (op1 == OR_TMP0) {
-        gen_op_ld_T0_A0(s, ot);
+        gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
     } else {
         gen_op_mov_TN_reg(ot, 0, op1);
     }
@@ -2309,7 +2304,7 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
                 gen_op_mov_TN_reg(ot, 0, reg);
             gen_op_st_T0_A0(s, ot);
         } else {
-            gen_op_ld_T0_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
             if (reg != OR_TMP0)
                 gen_op_mov_reg_T0(ot, reg);
         }
@@ -2589,7 +2584,7 @@ static void gen_pop_T0(DisasContext *s)
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
         gen_op_movq_A0_reg(R_ESP);
-        gen_op_ld_T0_A0(s, s->dflag ? MO_64 : MO_16);
+        gen_op_ld_v(s, s->dflag ? MO_64 : MO_16, cpu_T[0], cpu_A0);
     } else
 #endif
     {
@@ -2601,7 +2596,7 @@ static void gen_pop_T0(DisasContext *s)
             gen_op_andl_A0_ffff();
             gen_op_addl_A0_seg(s, R_SS);
         }
-        gen_op_ld_T0_A0(s, s->dflag + 1);
+        gen_op_ld_v(s, s->dflag + 1, cpu_T[0], cpu_A0);
     }
 }
 
@@ -2660,7 +2655,7 @@ static void gen_popa(DisasContext *s)
     for(i = 0;i < 8; i++) {
         /* ESP is not reloaded */
         if (i != 3) {
-            gen_op_ld_T0_A0(s, MO_16 + s->dflag);
+            gen_op_ld_v(s, MO_16 + s->dflag, cpu_T[0], cpu_A0);
             gen_op_mov_reg_T0(MO_16 + s->dflag, 7 - i);
         }
         gen_op_addl_A0_im(2 <<  s->dflag);
@@ -3346,7 +3341,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x210: /* movss xmm, ea */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                gen_op_ld_T0_A0(s, MO_32);
+                gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_movl_T0_0();
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
@@ -3710,7 +3705,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 if ((b >> 8) & 1) {
                     gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
                 } else {
-                    gen_op_ld_T0_A0(s, MO_32);
+                    gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                     tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
                 }
                 op2_offset = offsetof(CPUX86State,xmm_t0);
@@ -4529,7 +4524,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     /* specific case for SSE single instructions */
                     if (b1 == 2) {
                         /* 32 bit access */
-                        gen_op_ld_T0_A0(s, MO_32);
+                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                         tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
                     } else {
                         /* 64 bit access */
@@ -4933,7 +4928,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (op == 0)
                 s->rip_offset = insn_const_size(ot);
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-            gen_op_ld_T0_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
         }
@@ -5145,7 +5140,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod != 3) {
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             if (op >= 2 && op != 3 && op != 5)
-                gen_op_ld_T0_A0(s, ot);
+                gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
         }
@@ -5768,7 +5763,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
             gen_add_A0_ds_seg(s);
             if ((b & 2) == 0) {
-                gen_op_ld_T0_A0(s, ot);
+                gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
                 gen_op_mov_reg_T0(ot, R_EAX);
             } else {
                 gen_op_mov_TN_reg(ot, 0, R_EAX);
@@ -6011,12 +6006,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_T0_A0(s, MO_32);
+                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_T0_A0(s, MO_32);
+                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6050,12 +6045,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 case 0:
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_T0_A0(s, MO_32);
+                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_T0_A0(s, MO_32);
+                        gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6129,7 +6124,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
                 break;
             case 0x0d: /* fldcw mem */
-                gen_op_ld_T0_A0(s, MO_16);
+                gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
                 break;
@@ -6736,7 +6731,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         } else {
             gen_stack_A0(s);
             /* pop offset */
-            gen_op_ld_T0_A0(s, 1 + s->dflag);
+            gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
             if (s->dflag == 0)
                 gen_op_andl_T0_ffff();
             /* NOTE: keeping EIP updated is not a problem in case of
@@ -6744,7 +6739,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_op_jmp_T0();
             /* pop selector */
             gen_op_addl_A0_im(2 << s->dflag);
-            gen_op_ld_T0_A0(s, 1 + s->dflag);
+            gen_op_ld_v(s, 1 + s->dflag, cpu_T[0], cpu_A0);
             gen_op_movl_seg_T0_vm(R_CS);
             /* add stack offset */
             gen_stack_update(s, val + (4 << s->dflag));
@@ -6991,7 +6986,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (mod != 3) {
             s->rip_offset = 1;
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-            gen_op_ld_T0_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
         }
@@ -7027,7 +7022,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
             tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
-            gen_op_ld_T0_A0(s, ot);
+            gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
         } else {
             gen_op_mov_TN_reg(ot, 0, rm);
         }
@@ -7692,7 +7687,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 gen_op_ld_T1_A0(s, MO_16);
                 gen_add_A0_im(s, 2);
-                gen_op_ld_T0_A0(s, CODE64(s) + MO_32);
+                gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
                 if (!s->dflag)
                     gen_op_andl_T0_im(0xffffff);
                 if (op == 2) {
@@ -7814,7 +7809,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 if (d_ot == MO_64) {
                     gen_op_lds_T0_A0(s, MO_32);
                 } else {
-                    gen_op_ld_T0_A0(s, MO_32);
+                    gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             }
@@ -8062,7 +8057,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             if (op == 2) {
-                gen_op_ld_T0_A0(s, MO_32);
+                gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
             } else {
commit 4ba9938c893c040af589a7fb1265ac19a2dc43d2
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Nov 2 09:54:47 2013 -0700

    target-i386: Replace OT_* constants with MO_* constants
    
    The MO_8/16/32/64 constants have the same encoding and meaning
    as the OT_BYTE/WORD/LONG/QUAD.  Since we rely on them being the
    same, for the qemu_ld/st helpers, standardize on the common names.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index c69fcdc..e7e18e3 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -163,14 +163,6 @@ enum {
     JCC_LE,
 };
 
-/* operand size */
-enum {
-    OT_BYTE = 0,
-    OT_WORD,
-    OT_LONG,
-    OT_QUAD,
-};
-
 enum {
     /* I386 int registers */
     OR_EAX,   /* MUST be even numbered */
@@ -373,24 +365,24 @@ static inline bool byte_reg_is_xH(int reg)
 static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
 {
     switch(ot) {
-    case OT_BYTE:
+    case MO_8:
         if (!byte_reg_is_xH(reg)) {
             tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
         } else {
             tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
         }
         break;
-    case OT_WORD:
+    case MO_16:
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
         break;
     default: /* XXX this shouldn't be reached;  abort? */
-    case OT_LONG:
+    case MO_32:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
         tcg_gen_ext32u_tl(cpu_regs[reg], t0);
         break;
 #ifdef TARGET_X86_64
-    case OT_QUAD:
+    case MO_64:
         tcg_gen_mov_tl(cpu_regs[reg], t0);
         break;
 #endif
@@ -410,17 +402,17 @@ static inline void gen_op_mov_reg_T1(int ot, int reg)
 static inline void gen_op_mov_reg_A0(int size, int reg)
 {
     switch(size) {
-    case OT_BYTE:
+    case MO_8:
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
         break;
     default: /* XXX this shouldn't be reached;  abort? */
-    case OT_WORD:
+    case MO_16:
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a mov. */
         tcg_gen_ext32u_tl(cpu_regs[reg], cpu_A0);
         break;
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         tcg_gen_mov_tl(cpu_regs[reg], cpu_A0);
         break;
 #endif
@@ -429,7 +421,7 @@ static inline void gen_op_mov_reg_A0(int size, int reg)
 
 static inline void gen_op_mov_v_reg(int ot, TCGv t0, int reg)
 {
-    if (ot == OT_BYTE && byte_reg_is_xH(reg)) {
+    if (ot == MO_8 && byte_reg_is_xH(reg)) {
         tcg_gen_shri_tl(t0, cpu_regs[reg - 4], 8);
         tcg_gen_ext8u_tl(t0, t0);
     } else {
@@ -485,11 +477,11 @@ static inline void gen_op_jmp_T0(void)
 static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
 {
     switch(size) {
-    case OT_BYTE:
+    case MO_8:
         tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
         break;
-    case OT_WORD:
+    case MO_16:
         tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a nop. */
@@ -497,7 +489,7 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
         tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
         break;
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         tcg_gen_addi_tl(cpu_regs[reg], cpu_regs[reg], val);
         break;
 #endif
@@ -507,11 +499,11 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
 static inline void gen_op_add_reg_T0(int size, int reg)
 {
     switch(size) {
-    case OT_BYTE:
+    case MO_8:
         tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
         tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
         break;
-    case OT_WORD:
+    case MO_16:
         tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
         /* For x86_64, this sets the higher half of register to zero.
            For i386, this is equivalent to a nop. */
@@ -519,7 +511,7 @@ static inline void gen_op_add_reg_T0(int size, int reg)
         tcg_gen_mov_tl(cpu_regs[reg], cpu_tmp0);
         break;
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         tcg_gen_add_tl(cpu_regs[reg], cpu_regs[reg], cpu_T[0]);
         break;
 #endif
@@ -696,14 +688,14 @@ static inline void gen_op_movl_T0_Dshift(int ot)
 static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
 {
     switch (size) {
-    case OT_BYTE:
+    case MO_8:
         if (sign) {
             tcg_gen_ext8s_tl(dst, src);
         } else {
             tcg_gen_ext8u_tl(dst, src);
         }
         return dst;
-    case OT_WORD:
+    case MO_16:
         if (sign) {
             tcg_gen_ext16s_tl(dst, src);
         } else {
@@ -711,7 +703,7 @@ static TCGv gen_ext_tl(TCGv dst, TCGv src, int size, bool sign)
         }
         return dst;
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         if (sign) {
             tcg_gen_ext32s_tl(dst, src);
         } else {
@@ -751,13 +743,13 @@ static inline void gen_op_jz_ecx(int size, int label1)
 static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
 {
     switch (ot) {
-    case OT_BYTE:
+    case MO_8:
         gen_helper_inb(v, n);
         break;
-    case OT_WORD:
+    case MO_16:
         gen_helper_inw(v, n);
         break;
-    case OT_LONG:
+    case MO_32:
         gen_helper_inl(v, n);
         break;
     }
@@ -766,13 +758,13 @@ static void gen_helper_in_func(int ot, TCGv v, TCGv_i32 n)
 static void gen_helper_out_func(int ot, TCGv_i32 v, TCGv_i32 n)
 {
     switch (ot) {
-    case OT_BYTE:
+    case MO_8:
         gen_helper_outb(v, n);
         break;
-    case OT_WORD:
+    case MO_16:
         gen_helper_outw(v, n);
         break;
-    case OT_LONG:
+    case MO_32:
         gen_helper_outl(v, n);
         break;
     }
@@ -791,13 +783,13 @@ static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip,
         state_saved = 1;
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
         switch (ot) {
-        case OT_BYTE:
+        case MO_8:
             gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
             break;
-        case OT_WORD:
+        case MO_16:
             gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
             break;
-        case OT_LONG:
+        case MO_32:
             gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
             break;
         }
@@ -1244,7 +1236,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
 
 static inline void gen_stos(DisasContext *s, int ot)
 {
-    gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
+    gen_op_mov_TN_reg(MO_32, 0, R_EAX);
     gen_string_movl_A0_EDI(s);
     gen_op_st_T0_A0(s, ot);
     gen_op_movl_T0_Dshift(ot);
@@ -1289,7 +1281,7 @@ static inline void gen_ins(DisasContext *s, int ot)
        case of page fault. */
     gen_op_movl_T0_0();
     gen_op_st_T0_A0(s, ot);
-    gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
+    gen_op_mov_TN_reg(MO_16, 1, R_EDX);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
@@ -1307,7 +1299,7 @@ static inline void gen_outs(DisasContext *s, int ot)
     gen_string_movl_A0_ESI(s);
     gen_op_ld_T0_A0(s, ot);
 
-    gen_op_mov_TN_reg(OT_WORD, 1, R_EDX);
+    gen_op_mov_TN_reg(MO_16, 1, R_EDX);
     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[1]);
     tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
     tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
@@ -1576,7 +1568,7 @@ static void gen_shift_flags(DisasContext *s, int ot, TCGv result, TCGv shm1,
 static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, 
                             int is_right, int is_arith)
 {
-    target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
+    target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
 
     /* load */
     if (op1 == OR_TMP0) {
@@ -1616,7 +1608,7 @@ static void gen_shift_rm_T1(DisasContext *s, int ot, int op1,
 static void gen_shift_rm_im(DisasContext *s, int ot, int op1, int op2,
                             int is_right, int is_arith)
 {
-    int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
+    int mask = (ot == MO_64 ? 0x3f : 0x1f);
 
     /* load */
     if (op1 == OR_TMP0)
@@ -1666,7 +1658,7 @@ static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2)
 
 static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
 {
-    target_ulong mask = (ot == OT_QUAD ? 0x3f : 0x1f);
+    target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
     TCGv_i32 t0, t1;
 
     /* load */
@@ -1679,18 +1671,18 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
     tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
 
     switch (ot) {
-    case OT_BYTE:
+    case MO_8:
         /* Replicate the 8-bit input so that a 32-bit rotate works.  */
         tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
         tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
         goto do_long;
-    case OT_WORD:
+    case MO_16:
         /* Replicate the 16-bit input so that a 32-bit rotate works.  */
         tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
         goto do_long;
     do_long:
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
         if (is_right) {
@@ -1756,7 +1748,7 @@ static void gen_rot_rm_T1(DisasContext *s, int ot, int op1, int is_right)
 static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
                           int is_right)
 {
-    int mask = (ot == OT_QUAD ? 0x3f : 0x1f);
+    int mask = (ot == MO_64 ? 0x3f : 0x1f);
     int shift;
 
     /* load */
@@ -1770,7 +1762,7 @@ static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
     if (op2 != 0) {
         switch (ot) {
 #ifdef TARGET_X86_64
-        case OT_LONG:
+        case MO_32:
             tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
             if (is_right) {
                 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
@@ -1787,10 +1779,10 @@ static void gen_rot_rm_im(DisasContext *s, int ot, int op1, int op2,
                 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
             }
             break;
-        case OT_BYTE:
+        case MO_8:
             mask = 7;
             goto do_shifts;
-        case OT_WORD:
+        case MO_16:
             mask = 15;
         do_shifts:
             shift = op2 & mask;
@@ -1849,34 +1841,34 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
     
     if (is_right) {
         switch (ot) {
-        case OT_BYTE:
+        case MO_8:
             gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
-        case OT_WORD:
+        case MO_16:
             gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
-        case OT_LONG:
+        case MO_32:
             gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #ifdef TARGET_X86_64
-        case OT_QUAD:
+        case MO_64:
             gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #endif
         }
     } else {
         switch (ot) {
-        case OT_BYTE:
+        case MO_8:
             gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
-        case OT_WORD:
+        case MO_16:
             gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
-        case OT_LONG:
+        case MO_32:
             gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #ifdef TARGET_X86_64
-        case OT_QUAD:
+        case MO_64:
             gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
             break;
 #endif
@@ -1893,7 +1885,7 @@ static void gen_rotc_rm_T1(DisasContext *s, int ot, int op1,
 static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
                              bool is_right, TCGv count_in)
 {
-    target_ulong mask = (ot == OT_QUAD ? 63 : 31);
+    target_ulong mask = (ot == MO_64 ? 63 : 31);
     TCGv count;
 
     /* load */
@@ -1907,7 +1899,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
     tcg_gen_andi_tl(count, count_in, mask);
 
     switch (ot) {
-    case OT_WORD:
+    case MO_16:
         /* Note: we implement the Intel behaviour for shift count > 16.
            This means "shrdw C, B, A" shifts A:B:A >> C.  Build the B:A
            portion by constructing it as a 32-bit value.  */
@@ -1920,7 +1912,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
         }
         /* FALLTHRU */
 #ifdef TARGET_X86_64
-    case OT_LONG:
+    case MO_32:
         /* Concatenate the two 32-bit values and use a 64-bit shift.  */
         tcg_gen_subi_tl(cpu_tmp0, count, 1);
         if (is_right) {
@@ -1946,7 +1938,7 @@ static void gen_shiftd_rm_T1(DisasContext *s, int ot, int op1,
             tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
         } else {
             tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
-            if (ot == OT_WORD) {
+            if (ot == MO_16) {
                 /* Only needed if count > 16, for Intel behaviour.  */
                 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
                 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
@@ -2329,16 +2321,16 @@ static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
     uint32_t ret;
 
     switch(ot) {
-    case OT_BYTE:
+    case MO_8:
         ret = cpu_ldub_code(env, s->pc);
         s->pc++;
         break;
-    case OT_WORD:
+    case MO_16:
         ret = cpu_lduw_code(env, s->pc);
         s->pc += 2;
         break;
     default:
-    case OT_LONG:
+    case MO_32:
         ret = cpu_ldl_code(env, s->pc);
         s->pc += 4;
         break;
@@ -2348,10 +2340,11 @@ static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, int ot)
 
 static inline int insn_const_size(unsigned int ot)
 {
-    if (ot <= OT_LONG)
+    if (ot <= MO_32) {
         return 1 << ot;
-    else
+    } else {
         return 4;
+    }
 }
 
 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
@@ -2518,10 +2511,10 @@ static void gen_push_T0(DisasContext *s)
         gen_op_movq_A0_reg(R_ESP);
         if (s->dflag) {
             gen_op_addq_A0_im(-8);
-            gen_op_st_T0_A0(s, OT_QUAD);
+            gen_op_st_T0_A0(s, MO_64);
         } else {
             gen_op_addq_A0_im(-2);
-            gen_op_st_T0_A0(s, OT_WORD);
+            gen_op_st_T0_A0(s, MO_16);
         }
         gen_op_mov_reg_A0(2, R_ESP);
     } else
@@ -2559,10 +2552,10 @@ static void gen_push_T1(DisasContext *s)
         gen_op_movq_A0_reg(R_ESP);
         if (s->dflag) {
             gen_op_addq_A0_im(-8);
-            gen_op_st_T1_A0(s, OT_QUAD);
+            gen_op_st_T1_A0(s, MO_64);
         } else {
             gen_op_addq_A0_im(-2);
-            gen_op_st_T0_A0(s, OT_WORD);
+            gen_op_st_T0_A0(s, MO_16);
         }
         gen_op_mov_reg_A0(2, R_ESP);
     } else
@@ -2596,7 +2589,7 @@ static void gen_pop_T0(DisasContext *s)
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
         gen_op_movq_A0_reg(R_ESP);
-        gen_op_ld_T0_A0(s, s->dflag ? OT_QUAD : OT_WORD);
+        gen_op_ld_T0_A0(s, s->dflag ? MO_64 : MO_16);
     } else
 #endif
     {
@@ -2646,11 +2639,11 @@ static void gen_pusha(DisasContext *s)
     if (s->addseg)
         gen_op_addl_A0_seg(s, R_SS);
     for(i = 0;i < 8; i++) {
-        gen_op_mov_TN_reg(OT_LONG, 0, 7 - i);
-        gen_op_st_T0_A0(s, OT_WORD + s->dflag);
+        gen_op_mov_TN_reg(MO_32, 0, 7 - i);
+        gen_op_st_T0_A0(s, MO_16 + s->dflag);
         gen_op_addl_A0_im(2 <<  s->dflag);
     }
-    gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
+    gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
 }
 
 /* NOTE: wrap around in 16 bit not fully handled */
@@ -2667,12 +2660,12 @@ static void gen_popa(DisasContext *s)
     for(i = 0;i < 8; i++) {
         /* ESP is not reloaded */
         if (i != 3) {
-            gen_op_ld_T0_A0(s, OT_WORD + s->dflag);
-            gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i);
+            gen_op_ld_T0_A0(s, MO_16 + s->dflag);
+            gen_op_mov_reg_T0(MO_16 + s->dflag, 7 - i);
         }
         gen_op_addl_A0_im(2 <<  s->dflag);
     }
-    gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
+    gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
 }
 
 static void gen_enter(DisasContext *s, int esp_addend, int level)
@@ -2682,7 +2675,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
     level &= 0x1f;
 #ifdef TARGET_X86_64
     if (CODE64(s)) {
-        ot = s->dflag ? OT_QUAD : OT_WORD;
+        ot = s->dflag ? MO_64 : MO_16;
         opsize = 1 << ot;
 
         gen_op_movl_A0_reg(R_ESP);
@@ -2690,21 +2683,21 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         tcg_gen_mov_tl(cpu_T[1], cpu_A0);
 
         /* push bp */
-        gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
+        gen_op_mov_TN_reg(MO_32, 0, R_EBP);
         gen_op_st_T0_A0(s, ot);
         if (level) {
             /* XXX: must save state */
             gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
-                                     tcg_const_i32((ot == OT_QUAD)),
+                                     tcg_const_i32((ot == MO_64)),
                                      cpu_T[1]);
         }
         gen_op_mov_reg_T1(ot, R_EBP);
         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_T1(OT_QUAD, R_ESP);
+        gen_op_mov_reg_T1(MO_64, R_ESP);
     } else
 #endif
     {
-        ot = s->dflag + OT_WORD;
+        ot = s->dflag + MO_16;
         opsize = 2 << s->dflag;
 
         gen_op_movl_A0_reg(R_ESP);
@@ -2715,7 +2708,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         if (s->addseg)
             gen_op_addl_A0_seg(s, R_SS);
         /* push bp */
-        gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
+        gen_op_mov_TN_reg(MO_32, 0, R_EBP);
         gen_op_st_T0_A0(s, ot);
         if (level) {
             /* XXX: must save state */
@@ -2725,7 +2718,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
         }
         gen_op_mov_reg_T1(ot, R_EBP);
         tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
-        gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP);
+        gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
     }
 }
 
@@ -3288,18 +3281,18 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                     xmm_regs[reg].XMM_L(0)));
-                gen_op_st_T0_A0(s, OT_LONG);
+                gen_op_st_T0_A0(s, MO_32);
             }
             break;
         case 0x6e: /* movd mm, ea */
 #ifdef TARGET_X86_64
             if (s->dflag == 2) {
-                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
                 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
             } else
 #endif
             {
-                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,fpregs[reg].mmx));
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -3309,14 +3302,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x16e: /* movd xmm, ea */
 #ifdef TARGET_X86_64
             if (s->dflag == 2) {
-                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg]));
                 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
             } else
 #endif
             {
-                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
                 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg]));
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -3353,7 +3346,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x210: /* movss xmm, ea */
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                gen_op_ld_T0_A0(s, OT_LONG);
+                gen_op_ld_T0_A0(s, MO_32);
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
                 gen_op_movl_T0_0();
                 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
@@ -3476,13 +3469,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (s->dflag == 2) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,fpregs[reg].mmx));
-                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
             } else
 #endif
             {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
                                  offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
-                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
             }
             break;
         case 0x17e: /* movd ea, xmm */
@@ -3490,13 +3483,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (s->dflag == 2) {
                 tcg_gen_ld_i64(cpu_T[0], cpu_env, 
                                offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
-                gen_ldst_modrm(env, s, modrm, OT_QUAD, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
             } else
 #endif
             {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, 
                                  offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
-                gen_ldst_modrm(env, s, modrm, OT_LONG, OR_TMP0, 1);
+                gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
             }
             break;
         case 0x27e: /* movq xmm, ea */
@@ -3540,7 +3533,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
-                gen_op_st_T0_A0(s, OT_LONG);
+                gen_op_st_T0_A0(s, MO_32);
             } else {
                 rm = (modrm & 7) | REX_B(s);
                 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
@@ -3623,7 +3616,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                              offsetof(CPUX86State,xmm_regs[rm]));
             gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-            gen_op_mov_reg_T0(OT_LONG, reg);
+            gen_op_mov_reg_T0(MO_32, reg);
             break;
         case 0x150: /* movmskpd */
             rm = (modrm & 7) | REX_B(s);
@@ -3631,7 +3624,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                              offsetof(CPUX86State,xmm_regs[rm]));
             gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-            gen_op_mov_reg_T0(OT_LONG, reg);
+            gen_op_mov_reg_T0(MO_32, reg);
             break;
         case 0x02a: /* cvtpi2ps */
         case 0x12a: /* cvtpi2pd */
@@ -3659,11 +3652,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             break;
         case 0x22a: /* cvtsi2ss */
         case 0x32a: /* cvtsi2sd */
-            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+            ot = (s->dflag == 2) ? MO_64 : MO_32;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
             op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
-            if (ot == OT_LONG) {
+            if (ot == MO_32) {
                 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
@@ -3711,13 +3704,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x32c: /* cvttsd2si */
         case 0x22d: /* cvtss2si */
         case 0x32d: /* cvtsd2si */
-            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+            ot = (s->dflag == 2) ? MO_64 : MO_32;
             if (mod != 3) {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 if ((b >> 8) & 1) {
                     gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
                 } else {
-                    gen_op_ld_T0_A0(s, OT_LONG);
+                    gen_op_ld_T0_A0(s, MO_32);
                     tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
                 }
                 op2_offset = offsetof(CPUX86State,xmm_t0);
@@ -3726,7 +3719,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
             }
             tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
-            if (ot == OT_LONG) {
+            if (ot == MO_32) {
                 SSEFunc_i_ep sse_fn_i_ep =
                     sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
                 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
@@ -3745,7 +3738,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0xc4: /* pinsrw */
         case 0x1c4:
             s->rip_offset = 1;
-            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
             val = cpu_ldub_code(env, s->pc++);
             if (b1) {
                 val &= 7;
@@ -3761,7 +3754,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
         case 0x1c5:
             if (mod != 3)
                 goto illegal_op;
-            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+            ot = (s->dflag == 2) ? MO_64 : MO_32;
             val = cpu_ldub_code(env, s->pc++);
             if (b1) {
                 val &= 7;
@@ -3817,7 +3810,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
             }
             tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_op_mov_reg_T0(OT_LONG, reg);
+            gen_op_mov_reg_T0(MO_32, reg);
             break;
 
         case 0x138:
@@ -3914,20 +3907,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     goto illegal_op;
                 }
                 if ((b & 0xff) == 0xf0) {
-                    ot = OT_BYTE;
+                    ot = MO_8;
                 } else if (s->dflag != 2) {
-                    ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
+                    ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
                 } else {
-                    ot = OT_QUAD;
+                    ot = MO_64;
                 }
 
-                gen_op_mov_TN_reg(OT_LONG, 0, reg);
+                gen_op_mov_TN_reg(MO_32, 0, reg);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
                                  cpu_T[0], tcg_const_i32(8 << ot));
 
-                ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+                ot = (s->dflag == 2) ? MO_64 : MO_32;
                 gen_op_mov_reg_T0(ot, reg);
                 break;
 
@@ -3946,9 +3939,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     goto illegal_op;
                 }
                 if (s->dflag != 2) {
-                    ot = (s->prefix & PREFIX_DATA ? OT_WORD : OT_LONG);
+                    ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
                 } else {
-                    ot = OT_QUAD;
+                    ot = MO_64;
                 }
 
                 /* Load the data incoming to the bswap.  Note that the TCG
@@ -3959,27 +3952,27 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 } else {
                     switch (ot) {
-                    case OT_WORD:
+                    case MO_16:
                         tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[reg]);
                         break;
                     default:
                         tcg_gen_ext32u_tl(cpu_T[0], cpu_regs[reg]);
                         break;
-                    case OT_QUAD:
+                    case MO_64:
                         tcg_gen_mov_tl(cpu_T[0], cpu_regs[reg]);
                         break;
                     }
                 }
 
                 switch (ot) {
-                case OT_WORD:
+                case MO_16:
                     tcg_gen_bswap16_tl(cpu_T[0], cpu_T[0]);
                     break;
                 default:
                     tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
                     break;
 #ifdef TARGET_X86_64
-                case OT_QUAD:
+                case MO_64:
                     tcg_gen_bswap64_tl(cpu_T[0], cpu_T[0]);
                     break;
 #endif
@@ -3998,7 +3991,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
                 gen_op_mov_reg_T0(ot, reg);
@@ -4012,7 +4005,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 {
                     TCGv bound, zero;
 
@@ -4022,7 +4015,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
                     tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
 
-                    bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
+                    bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
                     zero = tcg_const_tl(0);
                     tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
                                        cpu_T[0], zero);
@@ -4052,11 +4045,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
                 {
-                    TCGv bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
+                    TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
                     /* Note that since we're using BMILG (in order to get O
                        cleared) we need to store the inverse into C.  */
                     tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
@@ -4079,7 +4072,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 switch (ot) {
                 default:
@@ -4091,7 +4084,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
                     break;
 #ifdef TARGET_X86_64
-                case OT_QUAD:
+                case MO_64:
                     tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
                                       cpu_T[0], cpu_regs[R_EDX]);
                     break;
@@ -4105,7 +4098,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 /* Note that by zero-extending the mask operand, we
                    automatically handle zero-extending the result.  */
@@ -4123,7 +4116,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 /* Note that by zero-extending the mask operand, we
                    automatically handle zero-extending the result.  */
@@ -4143,7 +4136,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     TCGv carry_in, carry_out, zero;
                     int end_op;
 
-                    ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
+                    ot = (s->dflag == 2 ? MO_64 : MO_32);
                     gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
 
                     /* Re-use the carry-out from a previous round.  */
@@ -4187,7 +4180,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
 
                     switch (ot) {
 #ifdef TARGET_X86_64
-                    case OT_LONG:
+                    case MO_32:
                         /* If we know TL is 64-bit, and we want a 32-bit
                            result, just do everything in 64-bit arithmetic.  */
                         tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
@@ -4222,9 +4215,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = (s->dflag == 2 ? OT_QUAD : OT_LONG);
+                ot = (s->dflag == 2 ? MO_64 : MO_32);
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
-                if (ot == OT_QUAD) {
+                if (ot == MO_64) {
                     tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
                 } else {
                     tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
@@ -4232,12 +4225,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 if (b == 0x1f7) {
                     tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
                 } else if (b == 0x2f7) {
-                    if (ot != OT_QUAD) {
+                    if (ot != MO_64) {
                         tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
                     }
                     tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
                 } else {
-                    if (ot != OT_QUAD) {
+                    if (ot != MO_64) {
                         tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
                     }
                     tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
@@ -4254,7 +4247,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
 
                 switch (reg & 7) {
@@ -4311,7 +4304,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                 goto illegal_op;
 
             if (sse_fn_eppi == SSE_SPECIAL) {
-                ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+                ot = (s->dflag == 2) ? MO_64 : MO_32;
                 rm = (modrm & 7) | REX_B(s);
                 if (mod != 3)
                     gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
@@ -4339,7 +4332,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     }
                     break;
                 case 0x16:
-                    if (ot == OT_LONG) { /* pextrd */
+                    if (ot == MO_32) { /* pextrd */
                         tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
                                         offsetof(CPUX86State,
                                                 xmm_regs[reg].XMM_L(val & 3)));
@@ -4378,7 +4371,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     break;
                 case 0x20: /* pinsrb */
                     if (mod == 3) {
-                        gen_op_mov_TN_reg(OT_LONG, 0, rm);
+                        gen_op_mov_TN_reg(MO_32, 0, rm);
                     } else {
                         tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
                                            s->mem_index, MO_UB);
@@ -4416,7 +4409,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                                                 xmm_regs[reg].XMM_L(3)));
                     break;
                 case 0x22:
-                    if (ot == OT_LONG) { /* pinsrd */
+                    if (ot == MO_32) { /* pinsrd */
                         if (mod == 3) {
                             gen_op_mov_v_reg(ot, cpu_tmp0, rm);
                         } else {
@@ -4494,10 +4487,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     || s->vex_l != 0) {
                     goto illegal_op;
                 }
-                ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+                ot = s->dflag == 2 ? MO_64 : MO_32;
                 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
                 b = cpu_ldub_code(env, s->pc++);
-                if (ot == OT_QUAD) {
+                if (ot == MO_64) {
                     tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
                 } else {
                     tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -4536,7 +4529,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     /* specific case for SSE single instructions */
                     if (b1 == 2) {
                         /* 32 bit access */
-                        gen_op_ld_T0_A0(s, OT_LONG);
+                        gen_op_ld_T0_A0(s, MO_32);
                         tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
                     } else {
                         /* 64 bit access */
@@ -4819,9 +4812,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             f = (b >> 1) & 3;
 
             if ((b & 1) == 0)
-                ot = OT_BYTE;
+                ot = MO_8;
             else
-                ot = dflag + OT_WORD;
+                ot = dflag + MO_16;
 
             switch(f) {
             case 0: /* OP Ev, Gv */
@@ -4879,9 +4872,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             int val;
 
             if ((b & 1) == 0)
-                ot = OT_BYTE;
+                ot = MO_8;
             else
-                ot = dflag + OT_WORD;
+                ot = dflag + MO_16;
 
             modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
@@ -4907,7 +4900,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 val = insn_get(env, s, ot);
                 break;
             case 0x83:
-                val = (int8_t)insn_get(env, s, OT_BYTE);
+                val = (int8_t)insn_get(env, s, MO_8);
                 break;
             }
             gen_op_movl_T1_im(val);
@@ -4918,19 +4911,19 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /**************************/
         /* inc, dec, and other misc arith */
     case 0x40 ... 0x47: /* inc Gv */
-        ot = dflag ? OT_LONG : OT_WORD;
+        ot = dflag ? MO_32 : MO_16;
         gen_inc(s, ot, OR_EAX + (b & 7), 1);
         break;
     case 0x48 ... 0x4f: /* dec Gv */
-        ot = dflag ? OT_LONG : OT_WORD;
+        ot = dflag ? MO_32 : MO_16;
         gen_inc(s, ot, OR_EAX + (b & 7), -1);
         break;
     case 0xf6: /* GRP3 */
     case 0xf7:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
 
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
@@ -4972,32 +4965,32 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 4: /* mul */
             switch(ot) {
-            case OT_BYTE:
-                gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
+            case MO_8:
+                gen_op_mov_TN_reg(MO_8, 1, R_EAX);
                 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(OT_WORD, R_EAX);
+                gen_op_mov_reg_T0(MO_16, R_EAX);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
                 set_cc_op(s, CC_OP_MULB);
                 break;
-            case OT_WORD:
-                gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
+            case MO_16:
+                gen_op_mov_TN_reg(MO_16, 1, R_EAX);
                 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(OT_WORD, R_EAX);
+                gen_op_mov_reg_T0(MO_16, R_EAX);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
-                gen_op_mov_reg_T0(OT_WORD, R_EDX);
+                gen_op_mov_reg_T0(MO_16, R_EDX);
                 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
                 set_cc_op(s, CC_OP_MULW);
                 break;
             default:
-            case OT_LONG:
+            case MO_32:
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
                 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
@@ -5009,7 +5002,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 set_cc_op(s, CC_OP_MULL);
                 break;
 #ifdef TARGET_X86_64
-            case OT_QUAD:
+            case MO_64:
                 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
                                   cpu_T[0], cpu_regs[R_EAX]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
@@ -5021,34 +5014,34 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 5: /* imul */
             switch(ot) {
-            case OT_BYTE:
-                gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
+            case MO_8:
+                gen_op_mov_TN_reg(MO_8, 1, R_EAX);
                 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(OT_WORD, R_EAX);
+                gen_op_mov_reg_T0(MO_16, R_EAX);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
                 set_cc_op(s, CC_OP_MULB);
                 break;
-            case OT_WORD:
-                gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
+            case MO_16:
+                gen_op_mov_TN_reg(MO_16, 1, R_EAX);
                 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
                 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
                 /* XXX: use 32 bit mul which could be faster */
                 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
-                gen_op_mov_reg_T0(OT_WORD, R_EAX);
+                gen_op_mov_reg_T0(MO_16, R_EAX);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
                 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
                 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
                 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
-                gen_op_mov_reg_T0(OT_WORD, R_EDX);
+                gen_op_mov_reg_T0(MO_16, R_EDX);
                 set_cc_op(s, CC_OP_MULW);
                 break;
             default:
-            case OT_LONG:
+            case MO_32:
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
                 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
@@ -5062,7 +5055,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 set_cc_op(s, CC_OP_MULL);
                 break;
 #ifdef TARGET_X86_64
-            case OT_QUAD:
+            case MO_64:
                 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
                                   cpu_T[0], cpu_regs[R_EAX]);
                 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
@@ -5075,21 +5068,21 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 6: /* div */
             switch(ot) {
-            case OT_BYTE:
+            case MO_8:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_divb_AL(cpu_env, cpu_T[0]);
                 break;
-            case OT_WORD:
+            case MO_16:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_divw_AX(cpu_env, cpu_T[0]);
                 break;
             default:
-            case OT_LONG:
+            case MO_32:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
                 break;
 #ifdef TARGET_X86_64
-            case OT_QUAD:
+            case MO_64:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
                 break;
@@ -5098,21 +5091,21 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 7: /* idiv */
             switch(ot) {
-            case OT_BYTE:
+            case MO_8:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
                 break;
-            case OT_WORD:
+            case MO_16:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
                 break;
             default:
-            case OT_LONG:
+            case MO_32:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
                 break;
 #ifdef TARGET_X86_64
-            case OT_QUAD:
+            case MO_64:
                 gen_jmp_im(pc_start - s->cs_base);
                 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
                 break;
@@ -5127,9 +5120,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xfe: /* GRP4 */
     case 0xff: /* GRP5 */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
 
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
@@ -5141,12 +5134,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s)) {
             if (op == 2 || op == 4) {
                 /* operand size for jumps is 64 bit */
-                ot = OT_QUAD;
+                ot = MO_64;
             } else if (op == 3 || op == 5) {
-                ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
+                ot = dflag ? MO_32 + (rex_w == 1) : MO_16;
             } else if (op == 6) {
                 /* default push size is 64 bit */
-                ot = dflag ? OT_QUAD : OT_WORD;
+                ot = dflag ? MO_64 : MO_16;
             }
         }
         if (mod != 3) {
@@ -5184,8 +5177,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 3: /* lcall Ev */
             gen_op_ld_T1_A0(s, ot);
-            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
-            gen_op_ldu_T0_A0(s, OT_WORD);
+            gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
+            gen_op_ldu_T0_A0(s, MO_16);
         do_lcall:
             if (s->pe && !s->vm86) {
                 gen_update_cc_op(s);
@@ -5210,8 +5203,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             break;
         case 5: /* ljmp Ev */
             gen_op_ld_T1_A0(s, ot);
-            gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
-            gen_op_ldu_T0_A0(s, OT_WORD);
+            gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
+            gen_op_ldu_T0_A0(s, MO_16);
         do_ljmp:
             if (s->pe && !s->vm86) {
                 gen_update_cc_op(s);
@@ -5237,9 +5230,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x84: /* test Ev, Gv */
     case 0x85:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
 
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
@@ -5253,9 +5246,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xa8: /* test eAX, Iv */
     case 0xa9:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         val = insn_get(env, s, ot);
 
         gen_op_mov_TN_reg(ot, 0, OR_EAX);
@@ -5267,45 +5260,45 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x98: /* CWDE/CBW */
 #ifdef TARGET_X86_64
         if (dflag == 2) {
-            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(OT_QUAD, R_EAX);
+            gen_op_mov_reg_T0(MO_64, R_EAX);
         } else
 #endif
         if (dflag == 1) {
-            gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(OT_LONG, R_EAX);
+            gen_op_mov_reg_T0(MO_32, R_EAX);
         } else {
-            gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_8, 0, R_EAX);
             tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(OT_WORD, R_EAX);
+            gen_op_mov_reg_T0(MO_16, R_EAX);
         }
         break;
     case 0x99: /* CDQ/CWD */
 #ifdef TARGET_X86_64
         if (dflag == 2) {
-            gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_64, 0, R_EAX);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
-            gen_op_mov_reg_T0(OT_QUAD, R_EDX);
+            gen_op_mov_reg_T0(MO_64, R_EDX);
         } else
 #endif
         if (dflag == 1) {
-            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
-            gen_op_mov_reg_T0(OT_LONG, R_EDX);
+            gen_op_mov_reg_T0(MO_32, R_EDX);
         } else {
-            gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_16, 0, R_EAX);
             tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
-            gen_op_mov_reg_T0(OT_WORD, R_EDX);
+            gen_op_mov_reg_T0(MO_16, R_EDX);
         }
         break;
     case 0x1af: /* imul Gv, Ev */
     case 0x69: /* imul Gv, Ev, I */
     case 0x6b:
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         if (b == 0x69)
@@ -5317,21 +5310,21 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             val = insn_get(env, s, ot);
             gen_op_movl_T1_im(val);
         } else if (b == 0x6b) {
-            val = (int8_t)insn_get(env, s, OT_BYTE);
+            val = (int8_t)insn_get(env, s, MO_8);
             gen_op_movl_T1_im(val);
         } else {
             gen_op_mov_TN_reg(ot, 1, reg);
         }
         switch (ot) {
 #ifdef TARGET_X86_64
-        case OT_QUAD:
+        case MO_64:
             tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
             tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
             tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
             tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
             break;
 #endif
-        case OT_LONG:
+        case MO_32:
             tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
             tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
             tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
@@ -5358,9 +5351,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1c0:
     case 0x1c1: /* xadd Ev, Gv */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5389,9 +5382,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             TCGv t0, t1, t2, a0;
 
             if ((b & 1) == 0)
-                ot = OT_BYTE;
+                ot = MO_8;
             else
-                ot = dflag + OT_WORD;
+                ot = dflag + MO_16;
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -5470,14 +5463,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /**************************/
         /* push/pop */
     case 0x50 ... 0x57: /* push */
-        gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
+        gen_op_mov_TN_reg(MO_32, 0, (b & 7) | REX_B(s));
         gen_push_T0(s);
         break;
     case 0x58 ... 0x5f: /* pop */
         if (CODE64(s)) {
-            ot = dflag ? OT_QUAD : OT_WORD;
+            ot = dflag ? MO_64 : MO_16;
         } else {
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         }
         gen_pop_T0(s);
         /* NOTE: order is important for pop %sp */
@@ -5497,22 +5490,22 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x68: /* push Iv */
     case 0x6a:
         if (CODE64(s)) {
-            ot = dflag ? OT_QUAD : OT_WORD;
+            ot = dflag ? MO_64 : MO_16;
         } else {
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         }
         if (b == 0x68)
             val = insn_get(env, s, ot);
         else
-            val = (int8_t)insn_get(env, s, OT_BYTE);
+            val = (int8_t)insn_get(env, s, MO_8);
         gen_op_movl_T0_im(val);
         gen_push_T0(s);
         break;
     case 0x8f: /* pop Ev */
         if (CODE64(s)) {
-            ot = dflag ? OT_QUAD : OT_WORD;
+            ot = dflag ? MO_64 : MO_16;
         } else {
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         }
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
@@ -5542,20 +5535,20 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xc9: /* leave */
         /* XXX: exception not precise (ESP is updated before potential exception) */
         if (CODE64(s)) {
-            gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
-            gen_op_mov_reg_T0(OT_QUAD, R_ESP);
+            gen_op_mov_TN_reg(MO_64, 0, R_EBP);
+            gen_op_mov_reg_T0(MO_64, R_ESP);
         } else if (s->ss32) {
-            gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
-            gen_op_mov_reg_T0(OT_LONG, R_ESP);
+            gen_op_mov_TN_reg(MO_32, 0, R_EBP);
+            gen_op_mov_reg_T0(MO_32, R_ESP);
         } else {
-            gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
-            gen_op_mov_reg_T0(OT_WORD, R_ESP);
+            gen_op_mov_TN_reg(MO_16, 0, R_EBP);
+            gen_op_mov_reg_T0(MO_16, R_ESP);
         }
         gen_pop_T0(s);
         if (CODE64(s)) {
-            ot = dflag ? OT_QUAD : OT_WORD;
+            ot = dflag ? MO_64 : MO_16;
         } else {
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         }
         gen_op_mov_reg_T0(ot, R_EBP);
         gen_pop_update(s);
@@ -5612,9 +5605,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x88:
     case 0x89: /* mov Gv, Ev */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
@@ -5624,9 +5617,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xc6:
     case 0xc7: /* mov Ev, Iv */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod != 3) {
@@ -5643,9 +5636,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x8a:
     case 0x8b: /* mov Ev, Gv */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = OT_WORD + dflag;
+            ot = MO_16 + dflag;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
 
@@ -5657,7 +5650,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = (modrm >> 3) & 7;
         if (reg >= 6 || reg == R_CS)
             goto illegal_op;
-        gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+        gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
         gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
         if (reg == R_SS) {
             /* if reg == SS, inhibit interrupts/trace */
@@ -5680,9 +5673,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto illegal_op;
         gen_op_movl_T0_seg(reg);
         if (mod == 3)
-            ot = OT_WORD + dflag;
+            ot = MO_16 + dflag;
         else
-            ot = OT_WORD;
+            ot = MO_16;
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
         break;
 
@@ -5693,9 +5686,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         {
             int d_ot;
             /* d_ot is the size of destination */
-            d_ot = dflag + OT_WORD;
+            d_ot = dflag + MO_16;
             /* ot is the size of source */
-            ot = (b & 1) + OT_BYTE;
+            ot = (b & 1) + MO_8;
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
             mod = (modrm >> 6) & 3;
@@ -5704,17 +5697,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             if (mod == 3) {
                 gen_op_mov_TN_reg(ot, 0, rm);
                 switch(ot | (b & 8)) {
-                case OT_BYTE:
+                case MO_8:
                     tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
                     break;
-                case OT_BYTE | 8:
+                case MO_8 | 8:
                     tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
                     break;
-                case OT_WORD:
+                case MO_16:
                     tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
                     break;
                 default:
-                case OT_WORD | 8:
+                case MO_16 | 8:
                     tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
                     break;
                 }
@@ -5732,7 +5725,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
 
     case 0x8d: /* lea */
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
@@ -5744,7 +5737,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         s->addseg = 0;
         gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
         s->addseg = val;
-        gen_op_mov_reg_A0(ot - OT_WORD, reg);
+        gen_op_mov_reg_A0(ot - MO_16, reg);
         break;
 
     case 0xa0: /* mov EAX, Ov */
@@ -5755,9 +5748,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             target_ulong offset_addr;
 
             if ((b & 1) == 0)
-                ot = OT_BYTE;
+                ot = MO_8;
             else
-                ot = dflag + OT_WORD;
+                ot = dflag + MO_16;
 #ifdef TARGET_X86_64
             if (s->aflag == 2) {
                 offset_addr = cpu_ldq_code(env, s->pc);
@@ -5767,9 +5760,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 #endif
             {
                 if (s->aflag) {
-                    offset_addr = insn_get(env, s, OT_LONG);
+                    offset_addr = insn_get(env, s, MO_32);
                 } else {
-                    offset_addr = insn_get(env, s, OT_WORD);
+                    offset_addr = insn_get(env, s, MO_16);
                 }
                 gen_op_movl_A0_im(offset_addr);
             }
@@ -5787,14 +5780,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 #ifdef TARGET_X86_64
         if (s->aflag == 2) {
             gen_op_movq_A0_reg(R_EBX);
-            gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_64, 0, R_EAX);
             tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
         } else
 #endif
         {
             gen_op_movl_A0_reg(R_EBX);
-            gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
+            gen_op_mov_TN_reg(MO_32, 0, R_EAX);
             tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
             tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
             if (s->aflag == 0)
@@ -5803,13 +5796,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
         }
         gen_add_A0_ds_seg(s);
-        gen_op_ldu_T0_A0(s, OT_BYTE);
-        gen_op_mov_reg_T0(OT_BYTE, R_EAX);
+        gen_op_ldu_T0_A0(s, MO_8);
+        gen_op_mov_reg_T0(MO_8, R_EAX);
         break;
     case 0xb0 ... 0xb7: /* mov R, Ib */
-        val = insn_get(env, s, OT_BYTE);
+        val = insn_get(env, s, MO_8);
         gen_op_movl_T0_im(val);
-        gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
+        gen_op_mov_reg_T0(MO_8, (b & 7) | REX_B(s));
         break;
     case 0xb8 ... 0xbf: /* mov R, Iv */
 #ifdef TARGET_X86_64
@@ -5820,11 +5813,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             s->pc += 8;
             reg = (b & 7) | REX_B(s);
             gen_movtl_T0_im(tmp);
-            gen_op_mov_reg_T0(OT_QUAD, reg);
+            gen_op_mov_reg_T0(MO_64, reg);
         } else
 #endif
         {
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
             val = insn_get(env, s, ot);
             reg = (b & 7) | REX_B(s);
             gen_op_movl_T0_im(val);
@@ -5834,16 +5827,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
     case 0x91 ... 0x97: /* xchg R, EAX */
     do_xchg_reg_eax:
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         reg = (b & 7) | REX_B(s);
         rm = R_EAX;
         goto do_xchg_reg;
     case 0x86:
     case 0x87: /* xchg Ev, Gv */
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5884,7 +5877,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1b5: /* lgs Gv */
         op = R_GS;
     do_lxx:
-        ot = dflag ? OT_LONG : OT_WORD;
+        ot = dflag ? MO_32 : MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
@@ -5892,9 +5885,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto illegal_op;
         gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
         gen_op_ld_T1_A0(s, ot);
-        gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
+        gen_add_A0_im(s, 1 << (ot - MO_16 + 1));
         /* load the segment first to handle exceptions properly */
-        gen_op_ldu_T0_A0(s, OT_WORD);
+        gen_op_ldu_T0_A0(s, MO_16);
         gen_movl_seg_T0(s, op, pc_start - s->cs_base);
         /* then put the data */
         gen_op_mov_reg_T1(ot, reg);
@@ -5913,9 +5906,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     grp2:
         {
             if ((b & 1) == 0)
-                ot = OT_BYTE;
+                ot = MO_8;
             else
-                ot = dflag + OT_WORD;
+                ot = dflag + MO_16;
 
             modrm = cpu_ldub_code(env, s->pc++);
             mod = (modrm >> 6) & 3;
@@ -5969,7 +5962,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         op = 1;
         shift = 0;
     do_shiftd:
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
@@ -6018,12 +6011,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_T0_A0(s, OT_LONG);
+                        gen_op_ld_T0_A0(s, MO_32);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_T0_A0(s, OT_LONG);
+                        gen_op_ld_T0_A0(s, MO_32);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6034,7 +6027,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_lds_T0_A0(s, OT_WORD);
+                        gen_op_lds_T0_A0(s, MO_16);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6057,12 +6050,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 case 0:
                     switch(op >> 4) {
                     case 0:
-                        gen_op_ld_T0_A0(s, OT_LONG);
+                        gen_op_ld_T0_A0(s, MO_32);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
                         break;
                     case 1:
-                        gen_op_ld_T0_A0(s, OT_LONG);
+                        gen_op_ld_T0_A0(s, MO_32);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6073,7 +6066,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                         break;
                     case 3:
                     default:
-                        gen_op_lds_T0_A0(s, OT_WORD);
+                        gen_op_lds_T0_A0(s, MO_16);
                         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                         gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
                         break;
@@ -6085,7 +6078,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 1:
                         gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, OT_LONG);
+                        gen_op_st_T0_A0(s, MO_32);
                         break;
                     case 2:
                         gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
@@ -6096,7 +6089,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     default:
                         gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, OT_WORD);
+                        gen_op_st_T0_A0(s, MO_16);
                         break;
                     }
                     gen_helper_fpop(cpu_env);
@@ -6106,12 +6099,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     case 0:
                         gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, OT_LONG);
+                        gen_op_st_T0_A0(s, MO_32);
                         break;
                     case 1:
                         gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, OT_LONG);
+                        gen_op_st_T0_A0(s, MO_32);
                         break;
                     case 2:
                         gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
@@ -6122,7 +6115,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                     default:
                         gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
                         tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                        gen_op_st_T0_A0(s, OT_WORD);
+                        gen_op_st_T0_A0(s, MO_16);
                         break;
                     }
                     if ((op & 7) == 3)
@@ -6136,7 +6129,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
                 break;
             case 0x0d: /* fldcw mem */
-                gen_op_ld_T0_A0(s, OT_WORD);
+                gen_op_ld_T0_A0(s, MO_16);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
                 break;
@@ -6148,7 +6141,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x0f: /* fnstcw mem */
                 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_T0_A0(s, OT_WORD);
+                gen_op_st_T0_A0(s, MO_16);
                 break;
             case 0x1d: /* fldt mem */
                 gen_update_cc_op(s);
@@ -6174,7 +6167,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             case 0x2f: /* fnstsw mem */
                 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
                 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                gen_op_st_T0_A0(s, OT_WORD);
+                gen_op_st_T0_A0(s, MO_16);
                 break;
             case 0x3c: /* fbld */
                 gen_update_cc_op(s);
@@ -6459,7 +6452,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 case 0:
                     gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
                     tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
-                    gen_op_mov_reg_T0(OT_WORD, R_EAX);
+                    gen_op_mov_reg_T0(MO_16, R_EAX);
                     break;
                 default:
                     goto illegal_op;
@@ -6517,9 +6510,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xa4: /* movsS */
     case 0xa5:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
 
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
@@ -6531,9 +6524,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xaa: /* stosS */
     case 0xab:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
 
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
@@ -6544,9 +6537,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xac: /* lodsS */
     case 0xad:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
             gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
@@ -6556,9 +6549,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xae: /* scasS */
     case 0xaf:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         if (prefixes & PREFIX_REPNZ) {
             gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
         } else if (prefixes & PREFIX_REPZ) {
@@ -6571,9 +6564,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xa6: /* cmpsS */
     case 0xa7:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag + OT_WORD;
+            ot = dflag + MO_16;
         if (prefixes & PREFIX_REPNZ) {
             gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
         } else if (prefixes & PREFIX_REPZ) {
@@ -6585,10 +6578,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x6c: /* insS */
     case 0x6d:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
-        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
+            ot = dflag ? MO_32 : MO_16;
+        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, pc_start - s->cs_base, 
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
@@ -6604,10 +6597,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x6e: /* outsS */
     case 0x6f:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
-        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
+            ot = dflag ? MO_32 : MO_16;
+        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes) | 4);
@@ -6627,9 +6620,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xe4:
     case 0xe5:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
         val = cpu_ldub_code(env, s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
@@ -6647,9 +6640,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xe6:
     case 0xe7:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
         val = cpu_ldub_code(env, s->pc++);
         gen_op_movl_T0_im(val);
         gen_check_io(s, ot, pc_start - s->cs_base,
@@ -6669,10 +6662,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xec:
     case 0xed:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
-        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
+            ot = dflag ? MO_32 : MO_16;
+        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
@@ -6689,10 +6682,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xee:
     case 0xef:
         if ((b & 1) == 0)
-            ot = OT_BYTE;
+            ot = MO_8;
         else
-            ot = dflag ? OT_LONG : OT_WORD;
-        gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
+            ot = dflag ? MO_32 : MO_16;
+        gen_op_mov_TN_reg(MO_16, 0, R_EDX);
         gen_op_andl_T0_ffff();
         gen_check_io(s, ot, pc_start - s->cs_base,
                      svm_is_rep(prefixes));
@@ -6786,9 +6779,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0xe8: /* call im */
         {
             if (dflag)
-                tval = (int32_t)insn_get(env, s, OT_LONG);
+                tval = (int32_t)insn_get(env, s, MO_32);
             else
-                tval = (int16_t)insn_get(env, s, OT_WORD);
+                tval = (int16_t)insn_get(env, s, MO_16);
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
             if (s->dflag == 0)
@@ -6806,9 +6799,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
             if (CODE64(s))
                 goto illegal_op;
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
             offset = insn_get(env, s, ot);
-            selector = insn_get(env, s, OT_WORD);
+            selector = insn_get(env, s, MO_16);
 
             gen_op_movl_T0_im(selector);
             gen_op_movl_T1_imu(offset);
@@ -6816,9 +6809,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         goto do_lcall;
     case 0xe9: /* jmp im */
         if (dflag)
-            tval = (int32_t)insn_get(env, s, OT_LONG);
+            tval = (int32_t)insn_get(env, s, MO_32);
         else
-            tval = (int16_t)insn_get(env, s, OT_WORD);
+            tval = (int16_t)insn_get(env, s, MO_16);
         tval += s->pc - s->cs_base;
         if (s->dflag == 0)
             tval &= 0xffff;
@@ -6832,29 +6825,29 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 
             if (CODE64(s))
                 goto illegal_op;
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
             offset = insn_get(env, s, ot);
-            selector = insn_get(env, s, OT_WORD);
+            selector = insn_get(env, s, MO_16);
 
             gen_op_movl_T0_im(selector);
             gen_op_movl_T1_imu(offset);
         }
         goto do_ljmp;
     case 0xeb: /* jmp Jb */
-        tval = (int8_t)insn_get(env, s, OT_BYTE);
+        tval = (int8_t)insn_get(env, s, MO_8);
         tval += s->pc - s->cs_base;
         if (s->dflag == 0)
             tval &= 0xffff;
         gen_jmp(s, tval);
         break;
     case 0x70 ... 0x7f: /* jcc Jb */
-        tval = (int8_t)insn_get(env, s, OT_BYTE);
+        tval = (int8_t)insn_get(env, s, MO_8);
         goto do_jcc;
     case 0x180 ... 0x18f: /* jcc Jv */
         if (dflag) {
-            tval = (int32_t)insn_get(env, s, OT_LONG);
+            tval = (int32_t)insn_get(env, s, MO_32);
         } else {
-            tval = (int16_t)insn_get(env, s, OT_WORD);
+            tval = (int16_t)insn_get(env, s, MO_16);
         }
     do_jcc:
         next_eip = s->pc - s->cs_base;
@@ -6867,13 +6860,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x190 ... 0x19f: /* setcc Gv */
         modrm = cpu_ldub_code(env, s->pc++);
         gen_setcc1(s, b, cpu_T[0]);
-        gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
+        gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
         break;
     case 0x140 ... 0x14f: /* cmov Gv, Ev */
         if (!(s->cpuid_features & CPUID_CMOV)) {
             goto illegal_op;
         }
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         gen_cmovcc1(env, s, ot, b, modrm, reg);
@@ -6952,7 +6945,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x9e: /* sahf */
         if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
             goto illegal_op;
-        gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
+        gen_op_mov_TN_reg(MO_8, 0, R_AH);
         gen_compute_eflags(s);
         tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
         tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -6964,7 +6957,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_compute_eflags(s);
         /* Note: gen_compute_eflags() only gives the condition codes */
         tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
-        gen_op_mov_reg_T0(OT_BYTE, R_AH);
+        gen_op_mov_reg_T0(MO_8, R_AH);
         break;
     case 0xf5: /* cmc */
         gen_compute_eflags(s);
@@ -6990,7 +6983,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         /************************/
         /* bit operations */
     case 0x1ba: /* bt/bts/btr/btc Gv, im */
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         op = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
@@ -7021,12 +7014,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1bb: /* btc */
         op = 3;
     do_btx:
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         mod = (modrm >> 6) & 3;
         rm = (modrm & 7) | REX_B(s);
-        gen_op_mov_TN_reg(OT_LONG, 1, reg);
+        gen_op_mov_TN_reg(MO_32, 1, reg);
         if (mod != 3) {
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             /* specific case: we need to add a displacement */
@@ -7078,7 +7071,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         break;
     case 0x1bc: /* bsf / tzcnt */
     case 0x1bd: /* bsr / lzcnt */
-        ot = dflag + OT_WORD;
+        ot = dflag + MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = ((modrm >> 3) & 7) | rex_r;
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
@@ -7277,7 +7270,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x62: /* bound */
         if (CODE64(s))
             goto illegal_op;
-        ot = dflag ? OT_LONG : OT_WORD;
+        ot = dflag ? MO_32 : MO_16;
         modrm = cpu_ldub_code(env, s->pc++);
         reg = (modrm >> 3) & 7;
         mod = (modrm >> 6) & 3;
@@ -7287,7 +7280,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
         gen_jmp_im(pc_start - s->cs_base);
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
-        if (ot == OT_WORD) {
+        if (ot == MO_16) {
             gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
         } else {
             gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
@@ -7297,16 +7290,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = (b & 7) | REX_B(s);
 #ifdef TARGET_X86_64
         if (dflag == 2) {
-            gen_op_mov_TN_reg(OT_QUAD, 0, reg);
+            gen_op_mov_TN_reg(MO_64, 0, reg);
             tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(OT_QUAD, reg);
+            gen_op_mov_reg_T0(MO_64, reg);
         } else
 #endif
         {
-            gen_op_mov_TN_reg(OT_LONG, 0, reg);
+            gen_op_mov_TN_reg(MO_32, 0, reg);
             tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
             tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
-            gen_op_mov_reg_T0(OT_LONG, reg);
+            gen_op_mov_reg_T0(MO_32, reg);
         }
         break;
     case 0xd6: /* salc */
@@ -7314,7 +7307,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             goto illegal_op;
         gen_compute_eflags_c(s, cpu_T[0]);
         tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
-        gen_op_mov_reg_T0(OT_BYTE, R_EAX);
+        gen_op_mov_reg_T0(MO_8, R_EAX);
         break;
     case 0xe0: /* loopnz */
     case 0xe1: /* loopz */
@@ -7323,7 +7316,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         {
             int l1, l2, l3;
 
-            tval = (int8_t)insn_get(env, s, OT_BYTE);
+            tval = (int8_t)insn_get(env, s, MO_8);
             next_eip = s->pc - s->cs_base;
             tval += next_eip;
             if (s->dflag == 0)
@@ -7464,7 +7457,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
-            ot = OT_WORD;
+            ot = MO_16;
             if (mod == 3)
                 ot += s->dflag;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
@@ -7476,7 +7469,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
-                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
@@ -7487,7 +7480,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
-            ot = OT_WORD;
+            ot = MO_16;
             if (mod == 3)
                 ot += s->dflag;
             gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
@@ -7499,7 +7492,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
-                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
                 gen_jmp_im(pc_start - s->cs_base);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
@@ -7509,7 +7502,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         case 5: /* verw */
             if (!s->pe || s->vm86)
                 goto illegal_op;
-            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
             gen_update_cc_op(s);
             if (op == 4) {
                 gen_helper_verr(cpu_env, cpu_T[0]);
@@ -7534,12 +7527,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
-            gen_op_st_T0_A0(s, OT_WORD);
+            gen_op_st_T0_A0(s, MO_16);
             gen_add_A0_im(s, 2);
             tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
             if (!s->dflag)
                 gen_op_andl_T0_im(0xffffff);
-            gen_op_st_T0_A0(s, CODE64(s) + OT_LONG);
+            gen_op_st_T0_A0(s, CODE64(s) + MO_32);
             break;
         case 1:
             if (mod == 3) {
@@ -7597,12 +7590,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
-                gen_op_st_T0_A0(s, OT_WORD);
+                gen_op_st_T0_A0(s, MO_16);
                 gen_add_A0_im(s, 2);
                 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
                 if (!s->dflag)
                     gen_op_andl_T0_im(0xffffff);
-                gen_op_st_T0_A0(s, CODE64(s) + OT_LONG);
+                gen_op_st_T0_A0(s, CODE64(s) + MO_32);
             }
             break;
         case 2: /* lgdt */
@@ -7697,9 +7690,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_svm_check_intercept(s, pc_start,
                                         op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                gen_op_ld_T1_A0(s, OT_WORD);
+                gen_op_ld_T1_A0(s, MO_16);
                 gen_add_A0_im(s, 2);
-                gen_op_ld_T0_A0(s, CODE64(s) + OT_LONG);
+                gen_op_ld_T0_A0(s, CODE64(s) + MO_32);
                 if (!s->dflag)
                     gen_op_andl_T0_im(0xffffff);
                 if (op == 2) {
@@ -7718,14 +7711,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 #else
             tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
 #endif
-            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
+            gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
             break;
         case 6: /* lmsw */
             if (s->cpl != 0) {
                 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
             } else {
                 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
-                gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+                gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
                 gen_helper_lmsw(cpu_env, cpu_T[0]);
                 gen_jmp_im(s->pc - s->cs_base);
                 gen_eob(s);
@@ -7802,7 +7795,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         if (CODE64(s)) {
             int d_ot;
             /* d_ot is the size of destination */
-            d_ot = dflag + OT_WORD;
+            d_ot = dflag + MO_16;
 
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
@@ -7810,17 +7803,18 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
 
             if (mod == 3) {
-                gen_op_mov_TN_reg(OT_LONG, 0, rm);
+                gen_op_mov_TN_reg(MO_32, 0, rm);
                 /* sign extend */
-                if (d_ot == OT_QUAD)
+                if (d_ot == MO_64) {
                     tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
+                }
                 gen_op_mov_reg_T0(d_ot, reg);
             } else {
                 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
-                if (d_ot == OT_QUAD) {
-                    gen_op_lds_T0_A0(s, OT_LONG);
+                if (d_ot == MO_64) {
+                    gen_op_lds_T0_A0(s, MO_32);
                 } else {
-                    gen_op_ld_T0_A0(s, OT_LONG);
+                    gen_op_ld_T0_A0(s, MO_32);
                 }
                 gen_op_mov_reg_T0(d_ot, reg);
             }
@@ -7835,7 +7829,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             t0 = tcg_temp_local_new();
             t1 = tcg_temp_local_new();
             t2 = tcg_temp_local_new();
-            ot = OT_WORD;
+            ot = MO_16;
             modrm = cpu_ldub_code(env, s->pc++);
             reg = (modrm >> 3) & 7;
             mod = (modrm >> 6) & 3;
@@ -7880,10 +7874,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             TCGv t0;
             if (!s->pe || s->vm86)
                 goto illegal_op;
-            ot = dflag ? OT_LONG : OT_WORD;
+            ot = dflag ? MO_32 : MO_16;
             modrm = cpu_ldub_code(env, s->pc++);
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
+            gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
             t0 = tcg_temp_local_new();
             gen_update_cc_op(s);
             if (b == 0x102) {
@@ -7937,9 +7931,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
             reg = ((modrm >> 3) & 7) | rex_r;
             if (CODE64(s))
-                ot = OT_QUAD;
+                ot = MO_64;
             else
-                ot = OT_LONG;
+                ot = MO_32;
             if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
                 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
                 reg = 8;
@@ -7982,9 +7976,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             rm = (modrm & 7) | REX_B(s);
             reg = ((modrm >> 3) & 7) | rex_r;
             if (CODE64(s))
-                ot = OT_QUAD;
+                ot = MO_64;
             else
-                ot = OT_LONG;
+                ot = MO_32;
             /* XXX: do it dynamically with CR4.DE bit */
             if (reg == 4 || reg == 5 || reg >= 8)
                 goto illegal_op;
@@ -8016,7 +8010,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x1c3: /* MOVNTI reg, mem */
         if (!(s->cpuid_features & CPUID_SSE2))
             goto illegal_op;
-        ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
+        ot = s->dflag == 2 ? MO_64 : MO_32;
         modrm = cpu_ldub_code(env, s->pc++);
         mod = (modrm >> 6) & 3;
         if (mod == 3)
@@ -8068,12 +8062,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 goto illegal_op;
             gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
             if (op == 2) {
-                gen_op_ld_T0_A0(s, OT_LONG);
+                gen_op_ld_T0_A0(s, MO_32);
                 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
                 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
             } else {
                 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
-                gen_op_st_T0_A0(s, OT_LONG);
+                gen_op_st_T0_A0(s, MO_32);
             }
             break;
         case 5: /* lfence */
@@ -8126,11 +8120,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         reg = ((modrm >> 3) & 7) | rex_r;
 
         if (s->prefix & PREFIX_DATA)
-            ot = OT_WORD;
+            ot = MO_16;
         else if (s->dflag != 2)
-            ot = OT_LONG;
+            ot = MO_32;
         else
-            ot = OT_QUAD;
+            ot = MO_64;
 
         gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
         gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
commit 096fc768184d5e9c47ccc4dd95d9f983fa83b9e1
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:15 2014 +0000

    target-arm: A64: Add support for FCVT between half, single and double
    
    Add support for FCVT between half, single and double precision.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index c6a6281..c708f15 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4089,6 +4089,26 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
     return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
 }
 
+float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, CPUARMState *env)
+{
+    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
+    float64 r = float16_to_float64(make_float16(a), ieee, &env->vfp.fp_status);
+    if (ieee) {
+        return float64_maybe_silence_nan(r);
+    }
+    return r;
+}
+
+uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, CPUARMState *env)
+{
+    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
+    float16 r = float64_to_float16(a, ieee, &env->vfp.fp_status);
+    if (ieee) {
+        r = float16_maybe_silence_nan(r);
+    }
+    return float16_val(r);
+}
+
 #define float32_two make_float32(0x40000000)
 #define float32_three make_float32(0x40400000)
 #define float32_one_point_five make_float32(0x3fc00000)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 7532e29..70872df 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -154,6 +154,8 @@ DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
 DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
 DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
+DEF_HELPER_FLAGS_2(vfp_fcvt_f16_to_f64, TCG_CALL_NO_RWG, f64, i32, env)
+DEF_HELPER_FLAGS_2(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, i32, f64, env)
 
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 345a47b..cf80c46 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -3498,6 +3498,72 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
     tcg_temp_free_i64(tcg_res);
 }
 
+static void handle_fp_fcvt(DisasContext *s, int opcode,
+                           int rd, int rn, int dtype, int ntype)
+{
+    switch (ntype) {
+    case 0x0:
+    {
+        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
+        if (dtype == 1) {
+            /* Single to double */
+            TCGv_i64 tcg_rd = tcg_temp_new_i64();
+            gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
+            write_fp_dreg(s, rd, tcg_rd);
+            tcg_temp_free_i64(tcg_rd);
+        } else {
+            /* Single to half */
+            TCGv_i32 tcg_rd = tcg_temp_new_i32();
+            gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
+            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
+            write_fp_sreg(s, rd, tcg_rd);
+            tcg_temp_free_i32(tcg_rd);
+        }
+        tcg_temp_free_i32(tcg_rn);
+        break;
+    }
+    case 0x1:
+    {
+        TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
+        TCGv_i32 tcg_rd = tcg_temp_new_i32();
+        if (dtype == 0) {
+            /* Double to single */
+            gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
+        } else {
+            /* Double to half */
+            gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
+            /* write_fp_sreg is OK here because top half of tcg_rd is zero */
+        }
+        write_fp_sreg(s, rd, tcg_rd);
+        tcg_temp_free_i32(tcg_rd);
+        tcg_temp_free_i64(tcg_rn);
+        break;
+    }
+    case 0x3:
+    {
+        TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
+        tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
+        if (dtype == 0) {
+            /* Half to single */
+            TCGv_i32 tcg_rd = tcg_temp_new_i32();
+            gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
+            write_fp_sreg(s, rd, tcg_rd);
+            tcg_temp_free_i32(tcg_rd);
+        } else {
+            /* Half to double */
+            TCGv_i64 tcg_rd = tcg_temp_new_i64();
+            gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
+            write_fp_dreg(s, rd, tcg_rd);
+            tcg_temp_free_i64(tcg_rd);
+        }
+        tcg_temp_free_i32(tcg_rn);
+        break;
+    }
+    default:
+        abort();
+    }
+}
+
 /* C3.6.25 Floating point data-processing (1 source)
  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
  * +---+---+---+-----------+------+---+--------+-----------+------+------+
@@ -3513,9 +3579,16 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
 
     switch (opcode) {
     case 0x4: case 0x5: case 0x7:
+    {
         /* FCVT between half, single and double precision */
-        unsupported_encoding(s, insn);
+        int dtype = extract32(opcode, 0, 2);
+        if (type == 2 || dtype == type) {
+            unallocated_encoding(s);
+            return;
+        }
+        handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
         break;
+    }
     case 0x0 ... 0x3:
     case 0x8 ... 0xc:
     case 0xe ... 0xf:
commit e97db91cbf7df456a35996d7243cd0f55d23ca1a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jan 7 17:19:14 2014 +0000

    target-arm: A64: Add 1-source 32-to-32 and 64-to-64 FP instructions
    
    This patch adds support for those instructions in the  "Floating-point
    data-processing (1 source)" group which are simple 32-bit-to-32-bit
    or 64-bit-to-64-bit operations (ie everything except FCVT between
    single/double/half precision).
    
    We put the new round-to-int helpers in helper.c because they will
    also be used by the new ARMv8 A32/T32 rounding instructions.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    [WN: Commit message tweak, merged single and double precision patches,
     updated to new infrastructure.]
    Signed-off-by: Will Newton <will.newton at linaro.org>
    [PMM: reworked decode, split FCVT out into their own patch]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2e76d0b..c6a6281 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4353,3 +4353,48 @@ float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
     float_status *fpst = fpstp;
     return float64_muladd(a, b, c, 0, fpst);
 }
+
+/* ARMv8 round to integral */
+float32 HELPER(rints_exact)(float32 x, void *fp_status)
+{
+    return float32_round_to_int(x, fp_status);
+}
+
+float64 HELPER(rintd_exact)(float64 x, void *fp_status)
+{
+    return float64_round_to_int(x, fp_status);
+}
+
+float32 HELPER(rints)(float32 x, void *fp_status)
+{
+    int old_flags = get_float_exception_flags(fp_status), new_flags;
+    float32 ret;
+
+    ret = float32_round_to_int(x, fp_status);
+
+    /* Suppress any inexact exceptions the conversion produced */
+    if (!(old_flags & float_flag_inexact)) {
+        new_flags = get_float_exception_flags(fp_status);
+        set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
+    }
+
+    return ret;
+}
+
+float64 HELPER(rintd)(float64 x, void *fp_status)
+{
+    int old_flags = get_float_exception_flags(fp_status), new_flags;
+    float64 ret;
+
+    ret = float64_round_to_int(x, fp_status);
+
+    new_flags = get_float_exception_flags(fp_status);
+
+    /* Suppress any inexact exceptions the conversion produced */
+    if (!(old_flags