[Spice-commits] 219 commits - MAINTAINERS Makefile backends/rng-egd.c backends/rng-random.c backends/rng.c block.c block/vvfat.c configure coroutine-ucontext.c default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak disas/s390.c docs/q35-chipset.cfg gdbstub.c hw/9pfs hw/Makefile.objs hw/a15mpcore.c hw/a9mpcore.c hw/ac97.c hw/acpi_piix4.c hw/ads7846.c hw/apb_pci.c hw/apic.c hw/apic_common.c hw/applesmc.c hw/arm11mpcore.c hw/arm_gic.c hw/arm_gic_common.c hw/arm_l2x0.c hw/arm_mptimer.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/armv7m_nvic.c hw/bitbang_i2c.c hw/cadence_gem.c hw/cadence_ttc.c hw/cadence_uart.c hw/ccid-card-emulated.c hw/ccid-card-passthru.c hw/cirrus_vga.c hw/cs4231.c hw/cs4231a.c hw/debugcon.c hw/debugexit.c hw/ds1225y.c hw/ds1338.c hw/e1000.c hw/eccmemctl.c hw/empty_slot.c hw/es1370.c hw/escc.c hw/etraxfs_eth.c hw/etraxfs_pic.c hw/etraxfs_ser.c hw/etraxfs_timer.c hw/exynos4210_combiner.c hw/exynos4210_fimd.c hw/exynos4210_gic.c hw/exynos4210_mct.c hw/exyn os4210_pmu.c hw/exynos4210_pwm.c hw/exynos4210_uart.c hw/fdc.c hw/fw_cfg.c hw/g364fb.c hw/grlib_apbuart.c hw/grlib_gptimer.c hw/grlib_irqmp.c hw/gus.c hw/hda-audio.c hw/highbank.c hw/hpet.c hw/i2c.c hw/i82374.c hw/i82378.c hw/i8254.c hw/i8254_common.c hw/i8259.c hw/i8259_common.c hw/ide hw/imx_ccm.c hw/imx_serial.c hw/integratorcp.c hw/intel-hda.c hw/ioapic.c hw/ioapic_common.c hw/ioh3420.c hw/isa-bus.c hw/ivshmem.c hw/jazz_led.c hw/kvm hw/kvmvapic.c hw/lan9118.c hw/lance.c hw/lm32_juart.c hw/lm32_pic.c hw/lm32_sys.c hw/lm32_timer.c hw/lm32_uart.c hw/lm832x.c hw/lsi53c895a.c hw/m48t59.c hw/macio.c hw/marvell_88w8618_audio.c hw/max111x.c hw/max7310.c hw/mc146818rtc.c hw/milkymist-ac97.c hw/milkymist-hpdmc.c hw/milkymist-memcard.c hw/milkymist-minimac2.c hw/milkymist-pfpu.c hw/milkymist-softusb.c hw/milkymist-sysctl.c hw/milkymist-tmu2.c hw/milkymist-uart.c hw/milkymist-vgafb.c hw/mips_malta.c hw/mipsnet.c hw/mpc8544_guts.c hw/mst_fpga.c hw/musicpal.c hw/nand.c hw/ne2000-isa.c hw/ne2000.c hw/omap1.c hw/omap_gpio.c hw/omap_i2c.c hw/omap_intc.c hw/onenand.c hw/opencores_eth.c hw/openpic.c hw/parallel.c hw/pc-testdev.c hw/pc.c hw/pc87312.c hw/pc87312.h hw/pc_piix.c hw/pc_q35.c hw/pc_sysfw.c hw/pci hw/pci_bridge_dev.c hw/pckbd.c hw/pcnet-pci.c hw/pcspk.c hw/piix4.c hw/pl011.c hw/pl022.c hw/pl031.c hw/pl041.c hw/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl181.c hw/pl190.c hw/ppc hw/ppc_booke.c hw/ppc_prep.c hw/ppce500_spin.c hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/qdev-core.h hw/qdev.c hw/qxl.c hw/realview_gic.c hw/rtl8139.c hw/s390-virtio-bus.c hw/s390x hw/sb16.c hw/sbi.c hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/serial-isa.c hw/serial-pci.c hw/sga.c hw/sh_pci.c hw/slavio_intctl.c hw/slavio_misc.c hw/slavio_timer.c hw/smbus.c hw/smbus_eeprom.c hw/smc91c111.c hw/spapr_llan.c hw/spapr_vio.c hw/spapr_vscsi.c hw/spapr_vty.c hw/sparc32_dma.c hw/spitz.c hw/ssd0303.c hw/ssd0323.c hw/ssi-sd.c hw/ssi.c hw/st ellaris.c hw/stellaris_enet.c hw/stream.c hw/strongarm.c hw/sun4c_intctl.c hw/sun4m.c hw/sun4m_iommu.c hw/sun4u.c hw/sysbus.c hw/tcx.c hw/tmp105.c hw/tosa.c hw/tusb6010.c hw/twl92230.c hw/usb hw/versatile_pci.c hw/versatilepb.c hw/vga-isa.c hw/vga-pci.c hw/virtio-console.c hw/virtio-pci.c hw/virtio-scsi.c hw/virtio-serial-bus.c hw/vmmouse.c hw/vmport.c hw/vmware_vga.c hw/vt82c686.c hw/wdt_i6300esb.c hw/wdt_ib700.c hw/wm8750.c hw/xen_apic.c hw/xen_platform.c hw/xen_pt.c hw/xgmac.c hw/xilinx_axidma.c hw/xilinx_axienet.c hw/xilinx_ethlite.c hw/xilinx_intc.c hw/xilinx_spi.c hw/xilinx_timer.c hw/xilinx_uartlite.c hw/xio3130_downstream.c hw/xio3130_upstream.c hw/z2.c hw/zaurus.c hw/zynq_slcr.c include/libfdt_env.h include/qemu include/qom include/ui linux-headers/asm-powerpc linux-headers/linux linux-user/main.c linux-user/qemu.h linux-user/s390x linux-user/signal.c linux-user/syscall_defs.h path.c qga/channel-posix.c qom/container.c readline.c rules.mak savevm.c scripts/update-li nux-headers.sh slirp/slirp.h target-arm/cpu.c target-arm/helper.c target-ppc/Makefile.objs target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/excp_helper.c target-ppc/helper.c target-ppc/helper.h target-ppc/kvm.c target-ppc/kvm_ppc.h target-ppc/mpic_helper.c target-ppc/translate_init.c target-s390x/cc_helper.c target-s390x/cpu.h target-s390x/fpu_helper.c target-s390x/helper.c target-s390x/helper.h target-s390x/insn-data.def target-s390x/insn-format.def target-s390x/int_helper.c target-s390x/mem_helper.c target-s390x/misc_helper.c target-s390x/translate.c tcg/i386 trace-events vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Jan 14 00:05:39 PST 2013


 MAINTAINERS                              |    2 
 Makefile                                 |    1 
 backends/rng-egd.c                       |    2 
 backends/rng-random.c                    |    2 
 backends/rng.c                           |    2 
 block.c                                  |   10 
 block/vvfat.c                            |    4 
 configure                                |   15 
 coroutine-ucontext.c                     |    4 
 default-configs/ppc-softmmu.mak          |    2 
 default-configs/ppc64-softmmu.mak        |    5 
 disas/s390.c                             |  173 
 docs/q35-chipset.cfg                     |  129 
 gdbstub.c                                |   78 
 hw/9pfs/virtio-9p-device.c               |    2 
 hw/Makefile.objs                         |    1 
 hw/a15mpcore.c                           |    2 
 hw/a9mpcore.c                            |    2 
 hw/ac97.c                                |    2 
 hw/acpi_piix4.c                          |    2 
 hw/ads7846.c                             |    2 
 hw/apb_pci.c                             |    6 
 hw/apic.c                                |    2 
 hw/apic_common.c                         |    2 
 hw/applesmc.c                            |    2 
 hw/arm11mpcore.c                         |    4 
 hw/arm_gic.c                             |    2 
 hw/arm_gic_common.c                      |    2 
 hw/arm_l2x0.c                            |    2 
 hw/arm_mptimer.c                         |    2 
 hw/arm_sysctl.c                          |    2 
 hw/arm_timer.c                           |    4 
 hw/armv7m.c                              |    2 
 hw/armv7m_nvic.c                         |    2 
 hw/bitbang_i2c.c                         |    2 
 hw/cadence_gem.c                         |    2 
 hw/cadence_ttc.c                         |    2 
 hw/cadence_uart.c                        |    2 
 hw/ccid-card-emulated.c                  |    2 
 hw/ccid-card-passthru.c                  |    2 
 hw/cirrus_vga.c                          |    4 
 hw/cs4231.c                              |    2 
 hw/cs4231a.c                             |    2 
 hw/debugcon.c                            |    2 
 hw/debugexit.c                           |    2 
 hw/ds1225y.c                             |    2 
 hw/ds1338.c                              |    2 
 hw/e1000.c                               |    2 
 hw/eccmemctl.c                           |    2 
 hw/empty_slot.c                          |    2 
 hw/es1370.c                              |    2 
 hw/escc.c                                |    2 
 hw/etraxfs_eth.c                         |    2 
 hw/etraxfs_pic.c                         |    2 
 hw/etraxfs_ser.c                         |    2 
 hw/etraxfs_timer.c                       |    2 
 hw/exynos4210_combiner.c                 |    2 
 hw/exynos4210_fimd.c                     |    2 
 hw/exynos4210_gic.c                      |    4 
 hw/exynos4210_mct.c                      |    2 
 hw/exynos4210_pmu.c                      |    2 
 hw/exynos4210_pwm.c                      |    2 
 hw/exynos4210_uart.c                     |    2 
 hw/fdc.c                                 |    6 
 hw/fw_cfg.c                              |    2 
 hw/g364fb.c                              |    2 
 hw/grlib_apbuart.c                       |    2 
 hw/grlib_gptimer.c                       |    2 
 hw/grlib_irqmp.c                         |    2 
 hw/gus.c                                 |    2 
 hw/hda-audio.c                           |    6 
 hw/highbank.c                            |    2 
 hw/hpet.c                                |    2 
 hw/i2c.c                                 |    2 
 hw/i82374.c                              |    2 
 hw/i82378.c                              |    2 
 hw/i8254.c                               |    2 
 hw/i8254_common.c                        |    2 
 hw/i8259.c                               |    2 
 hw/i8259_common.c                        |    2 
 hw/ide/ahci.c                            |    2 
 hw/ide/cmd646.c                          |    2 
 hw/ide/ich.c                             |    2 
 hw/ide/isa.c                             |    2 
 hw/ide/piix.c                            |    6 
 hw/ide/qdev.c                            |    8 
 hw/ide/via.c                             |    2 
 hw/imx_ccm.c                             |    2 
 hw/imx_serial.c                          |    2 
 hw/integratorcp.c                        |    4 
 hw/intel-hda.c                           |   43 
 hw/ioapic.c                              |    2 
 hw/ioapic_common.c                       |    2 
 hw/ioh3420.c                             |    2 
 hw/isa-bus.c                             |    4 
 hw/ivshmem.c                             |    2 
 hw/jazz_led.c                            |    2 
 hw/kvm/apic.c                            |    2 
 hw/kvm/clock.c                           |    2 
 hw/kvm/i8254.c                           |    2 
 hw/kvm/i8259.c                           |    2 
 hw/kvm/ioapic.c                          |    2 
 hw/kvmvapic.c                            |    2 
 hw/lan9118.c                             |    2 
 hw/lance.c                               |    2 
 hw/lm32_juart.c                          |    2 
 hw/lm32_pic.c                            |    2 
 hw/lm32_sys.c                            |    2 
 hw/lm32_timer.c                          |    2 
 hw/lm32_uart.c                           |    2 
 hw/lm832x.c                              |    2 
 hw/lsi53c895a.c                          |    2 
 hw/m48t59.c                              |    4 
 hw/macio.c                               |    2 
 hw/marvell_88w8618_audio.c               |    2 
 hw/max111x.c                             |    4 
 hw/max7310.c                             |    2 
 hw/mc146818rtc.c                         |    2 
 hw/milkymist-ac97.c                      |    2 
 hw/milkymist-hpdmc.c                     |    2 
 hw/milkymist-memcard.c                   |    2 
 hw/milkymist-minimac2.c                  |    2 
 hw/milkymist-pfpu.c                      |    2 
 hw/milkymist-softusb.c                   |    2 
 hw/milkymist-sysctl.c                    |    2 
 hw/milkymist-tmu2.c                      |    2 
 hw/milkymist-uart.c                      |    2 
 hw/milkymist-vgafb.c                     |    2 
 hw/mips_malta.c                          |    2 
 hw/mipsnet.c                             |    2 
 hw/mpc8544_guts.c                        |    2 
 hw/mst_fpga.c                            |    2 
 hw/musicpal.c                            |   16 
 hw/nand.c                                |    2 
 hw/ne2000-isa.c                          |    2 
 hw/ne2000.c                              |    2 
 hw/omap1.c                               |    2 
 hw/omap_gpio.c                           |    4 
 hw/omap_i2c.c                            |    2 
 hw/omap_intc.c                           |    4 
 hw/onenand.c                             |    2 
 hw/opencores_eth.c                       |    2 
 hw/openpic.c                             | 1034 ++-
 hw/parallel.c                            |    2 
 hw/pc-testdev.c                          |    2 
 hw/pc.c                                  |   14 
 hw/pc87312.c                             |  387 +
 hw/pc87312.h                             |   66 
 hw/pc_piix.c                             |    8 
 hw/pc_q35.c                              |    4 
 hw/pc_sysfw.c                            |    2 
 hw/pci/pci.c                             |    2 
 hw/pci_bridge_dev.c                      |    2 
 hw/pckbd.c                               |    2 
 hw/pcnet-pci.c                           |    2 
 hw/pcspk.c                               |    2 
 hw/piix4.c                               |    2 
 hw/pl011.c                               |    4 
 hw/pl022.c                               |    2 
 hw/pl031.c                               |    2 
 hw/pl041.c                               |    2 
 hw/pl050.c                               |    4 
 hw/pl061.c                               |    4 
 hw/pl080.c                               |    4 
 hw/pl110.c                               |    6 
 hw/pl181.c                               |    2 
 hw/pl190.c                               |    2 
 hw/ppc/e500.c                            |    8 
 hw/ppc_booke.c                           |   13 
 hw/ppc_prep.c                            |   39 
 hw/ppce500_spin.c                        |    2 
 hw/pxa2xx.c                              |    8 
 hw/pxa2xx_dma.c                          |    2 
 hw/pxa2xx_gpio.c                         |    2 
 hw/pxa2xx_pic.c                          |    2 
 hw/pxa2xx_timer.c                        |    4 
 hw/qdev-core.h                           |   12 
 hw/qdev.c                                |    9 
 hw/qxl.c                                 |    4 
 hw/realview_gic.c                        |    2 
 hw/rtl8139.c                             |    2 
 hw/s390-virtio-bus.c                     |   14 
 hw/s390x/event-facility.c                |    4 
 hw/s390x/sclp.c                          |    2 
 hw/s390x/sclpconsole.c                   |    2 
 hw/s390x/sclpquiesce.c                   |    2 
 hw/sb16.c                                |    2 
 hw/sbi.c                                 |    2 
 hw/scsi-bus.c                            |    2 
 hw/scsi-disk.c                           |    8 
 hw/scsi-generic.c                        |    2 
 hw/serial-isa.c                          |    2 
 hw/serial-pci.c                          |    6 
 hw/sga.c                                 |    2 
 hw/sh_pci.c                              |    4 
 hw/slavio_intctl.c                       |    2 
 hw/slavio_misc.c                         |    4 
 hw/slavio_timer.c                        |    2 
 hw/smbus.c                               |    2 
 hw/smbus_eeprom.c                        |    2 
 hw/smc91c111.c                           |    2 
 hw/spapr_llan.c                          |    2 
 hw/spapr_vio.c                           |    4 
 hw/spapr_vscsi.c                         |    2 
 hw/spapr_vty.c                           |    2 
 hw/sparc32_dma.c                         |    2 
 hw/spitz.c                               |    8 
 hw/ssd0303.c                             |    2 
 hw/ssd0323.c                             |    2 
 hw/ssi-sd.c                              |    2 
 hw/ssi.c                                 |    2 
 hw/stellaris.c                           |    6 
 hw/stellaris_enet.c                      |    2 
 hw/stream.c                              |    2 
 hw/strongarm.c                           |   12 
 hw/sun4c_intctl.c                        |    2 
 hw/sun4m.c                               |    8 
 hw/sun4m_iommu.c                         |    2 
 hw/sun4u.c                               |    6 
 hw/sysbus.c                              |    2 
 hw/tcx.c                                 |    2 
 hw/tmp105.c                              |    2 
 hw/tosa.c                                |    4 
 hw/tusb6010.c                            |    2 
 hw/twl92230.c                            |    2 
 hw/usb/bus.c                             |    2 
 hw/usb/dev-audio.c                       |    2 
 hw/usb/dev-bluetooth.c                   |    2 
 hw/usb/dev-hid.c                         |    6 
 hw/usb/dev-hub.c                         |    2 
 hw/usb/dev-network.c                     |    2 
 hw/usb/dev-serial.c                      |    4 
 hw/usb/dev-smartcard-reader.c            |    4 
 hw/usb/dev-storage.c                     |    2 
 hw/usb/dev-uas.c                         |    2 
 hw/usb/dev-wacom.c                       |    2 
 hw/usb/hcd-ohci.c                        |    4 
 hw/usb/hcd-xhci.c                        |    2 
 hw/usb/host-bsd.c                        |    2 
 hw/usb/host-linux.c                      |    2 
 hw/usb/redirect.c                        |    2 
 hw/versatile_pci.c                       |    6 
 hw/versatilepb.c                         |    2 
 hw/vga-isa.c                             |    2 
 hw/vga-pci.c                             |    2 
 hw/virtio-console.c                      |    4 
 hw/virtio-pci.c                          |   12 
 hw/virtio-scsi.c                         |    4 
 hw/virtio-serial-bus.c                   |    2 
 hw/vmmouse.c                             |    2 
 hw/vmport.c                              |    2 
 hw/vmware_vga.c                          |    2 
 hw/vt82c686.c                            |    8 
 hw/wdt_i6300esb.c                        |    2 
 hw/wdt_ib700.c                           |    2 
 hw/wm8750.c                              |    2 
 hw/xen_apic.c                            |    2 
 hw/xen_platform.c                        |    2 
 hw/xen_pt.c                              |    2 
 hw/xgmac.c                               |    2 
 hw/xilinx_axidma.c                       |    2 
 hw/xilinx_axienet.c                      |    2 
 hw/xilinx_ethlite.c                      |    2 
 hw/xilinx_intc.c                         |    2 
 hw/xilinx_spi.c                          |    2 
 hw/xilinx_timer.c                        |    2 
 hw/xilinx_uartlite.c                     |    2 
 hw/xio3130_downstream.c                  |    2 
 hw/xio3130_upstream.c                    |    2 
 hw/z2.c                                  |    4 
 hw/zaurus.c                              |    2 
 hw/zynq_slcr.c                           |    2 
 include/libfdt_env.h                     |   16 
 include/qemu/bswap.h                     |  480 -
 include/qom/object.h                     |    6 
 include/ui/qemu-pixman.h                 |    7 
 linux-headers/asm-powerpc/epapr_hcalls.h |   98 
 linux-headers/asm-powerpc/kvm.h          |   86 
 linux-headers/asm-powerpc/kvm_para.h     |   13 
 linux-headers/linux/kvm.h                |   21 
 linux-headers/linux/kvm_para.h           |    6 
 linux-headers/linux/vfio.h               |    6 
 linux-headers/linux/virtio_config.h      |    6 
 linux-headers/linux/virtio_ring.h        |    6 
 linux-user/main.c                        |  140 
 linux-user/qemu.h                        |   63 
 linux-user/s390x/syscall.h               |    2 
 linux-user/signal.c                      |   28 
 linux-user/syscall_defs.h                |    2 
 path.c                                   |    5 
 qga/channel-posix.c                      |    1 
 qom/container.c                          |    2 
 readline.c                               |    4 
 rules.mak                                |    7 
 savevm.c                                 |   30 
 scripts/update-linux-headers.sh          |    3 
 slirp/slirp.h                            |    1 
 target-arm/cpu.c                         |    2 
 target-arm/helper.c                      |    2 
 target-ppc/Makefile.objs                 |    4 
 target-ppc/cpu-qom.h                     |    5 
 target-ppc/cpu.h                         |    8 
 target-ppc/excp_helper.c                 |   35 
 target-ppc/helper.c                      |   50 
 target-ppc/helper.h                      |    1 
 target-ppc/kvm.c                         |   77 
 target-ppc/kvm_ppc.h                     |   14 
 target-ppc/mpic_helper.c                 |   35 
 target-ppc/translate_init.c              |  352 -
 target-s390x/cc_helper.c                 |  335 -
 target-s390x/cpu.h                       |  167 
 target-s390x/fpu_helper.c                |  960 +--
 target-s390x/helper.c                    |   67 
 target-s390x/helper.h                    |  220 
 target-s390x/insn-data.def               |  813 ++
 target-s390x/insn-format.def             |   55 
 target-s390x/int_helper.c                |  176 
 target-s390x/mem_helper.c                |  359 -
 target-s390x/misc_helper.c               |   94 
 target-s390x/translate.c                 | 8685 ++++++++++++++-----------------
 tcg/i386/tcg-target.c                    |    2 
 trace-events                             |    8 
 vl.c                                     |    9 
 323 files changed, 8807 insertions(+), 7500 deletions(-)

New commits:
commit 63fb2590839162afdf14d7c0ee02d460766c0956
Merge: 02e079c 314e229
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 12 12:47:07 2013 +0000

    Merge branch 'target-arm.next' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'target-arm.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
      target-arm: Fix SWI (SVC) instruction in M profile.
      target-arm: use type_register() instead of type_register_static()

commit 02e079c79cdb7ac8180f92edaed4b942ca6b7c71
Merge: 837d1f9 61993a6
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 12 12:47:02 2013 +0000

    Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf: (31 commits)
      PPC: linux-user: Calculate context pointer explicitly
      target-ppc: Error out for -cpu host on unknown PVR
      target-ppc: Slim conversion of model definitions to QOM subclasses
      PPC: Bring EPR support closer to reality
      PPC: KVM: set has-idle in guest device tree
      kvm: Update kernel headers
      openpic: fix CTPR and de-assertion of interrupts
      openpic: move IACK to its own function
      openpic: IRQ_check: search the queue a word at a time
      openpic: fix sense and priority bits
      openpic: add some bounds checking for IRQ numbers
      openpic: use standard bitmap operations
      Revert "openpic: Accelerate pending irq search"
      openpic: always call IRQ_check from IRQ_get_next
      openpic/fsl: critical interrupts ignore mask before v4.1
      openpic: make ctpr signed
      openpic: rework critical interrupt support
      openpic: make register names correspond better with hw docs
      ppc/booke: fix crit/mcheck/debug exceptions
      openpic: lower interrupt when reading the MSI register
      ...

commit 837d1f978224f7e7b020c71ffb10b291952cc596
Merge: a6fc23e 2b35e93
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 12 12:46:57 2013 +0000

    Merge branch 's390-reorg' of git://repo.or.cz/qemu/rth
    
    * 's390-reorg' of git://repo.or.cz/qemu/rth: (149 commits)
      target-s390: Claim maintainership
      target-s390: Use noreturn for exception and load_psw
      target-s390: Use TCG_CALL_NO_WG for misc helpers
      target-s390: Use TCG_CALL_NO_WG for integer helpers
      target-s390: Use TCG_CALL_NO_WG for floating-point helpers
      target-s390: Use TCG_CALL_NO_WG for memory helpers
      target-s390: Perform COMPARE AND SWAP inline
      target-s390: Optimize get_address
      target-s390: Optimize ADDC/SUBB
      target-s390: Optimize ADDU/SUBU CC testing
      target-s390: Tidy comparisons
      target-s390: Optmize emitting discards
      target-s390: Optimize XC
      target-s390: Fix cpu_clone_regs
      target-s390: Implement LOAD/SET FP AND SIGNAL
      target-s390: Implement SET ROUNDING MODE
      target-s390: Use uint64_to_float128
      target-s390: Implement LCDFR
      target-s390: Check insn operand specifications
      target-s390: Implement CPSDR
      ...

commit a6fc23e5dc76660792c8363d058adf22caa82945
Author: Julien Grall <julien.grall at citrix.com>
Date:   Fri Jan 11 16:41:43 2013 +0000

    hw/pc.c: add ULL suffix in ioport80_read and ioportF0_read return value
    
    The commit c02e1eac887b1b0aee7361b1fcf889e7d47fed9d broke the compilation
    for i386. ULL need to be specify for uint64_t value.
    
    Signed-off-by: Julien Grall <julien.grall at citrix.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/pc.c b/hw/pc.c
index dfa3144..ba1f19d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -105,7 +105,7 @@ static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
 
 static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
 {
-    return 0xffffffffffffffff;
+    return 0xffffffffffffffffULL;
 }
 
 /* MSDOS compatibility mode FPU exception support */
@@ -130,7 +130,7 @@ static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
 
 static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
 {
-    return 0xffffffffffffffff;
+    return 0xffffffffffffffffULL;
 }
 
 /* TSC handling */
commit 163fa4b09db3e36c612e178fd11b3af4247cbd56
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jan 11 15:05:06 2013 -0800

    tcg-i386: use LEA for 3-operand 64-bit addition
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index e083874..7aec304 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2099,7 +2099,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_st32_i64, { "ri", "r" } },
     { INDEX_op_st_i64, { "re", "r" } },
 
-    { INDEX_op_add_i64, { "r", "0", "re" } },
+    { INDEX_op_add_i64, { "r", "r", "re" } },
     { INDEX_op_mul_i64, { "r", "0", "re" } },
     { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
     { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
commit 092bb3068801bd6bfc90fcced2661e77bb811764
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jan 9 10:17:08 2013 +0100

    pixman: fix warning
    
    Cc: afaerber at suse.de
    Cc: agraf at suse.de
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index 3c05c83..016fd87 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -6,7 +6,14 @@
 #ifndef QEMU_PIXMAN_H
 #define QEMU_PIXMAN_H
 
+/* pixman-0.16.0 headers have a redundant declaration */
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
 #include <pixman.h>
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+#pragma GCC diagnostic error "-Wredundant-decls"
+#endif
 
 #include "console.h"
 
commit cc6e3ca93c1b40fba579e8724dd06ca9f0507b31
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jan 9 10:17:07 2013 +0100

    gcc: rename CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET to CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index ec8238e..ea42fe2 100755
--- a/configure
+++ b/configure
@@ -3078,7 +3078,7 @@ int main(void) {
 }
 EOF
 if compile_prog "-Werror" "" ; then
-    pragma_disable_unused_but_set=yes
+    pragma_diagnostic_available=yes
 fi
 
 ########################################
@@ -3648,8 +3648,8 @@ if test "$linux_magic_h" = "yes" ; then
   echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
 fi
 
-if test "$pragma_disable_unused_but_set" = "yes" ; then
-  echo "CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET=y" >> $config_host_mak
+if test "$pragma_diagnostic_available" = "yes" ; then
+  echo "CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE=y" >> $config_host_mak
 fi
 
 if test "$valgrind_h" = "yes" ; then
diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
index 2ed703a..a9c30e9 100644
--- a/coroutine-ucontext.c
+++ b/coroutine-ucontext.c
@@ -200,7 +200,7 @@ Coroutine *qemu_coroutine_new(void)
 }
 
 #ifdef CONFIG_VALGRIND_H
-#ifdef CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
 /* Work around an unused variable in the valgrind.h macro... */
 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #endif
@@ -208,7 +208,7 @@ static inline void valgrind_stack_deregister(CoroutineUContext *co)
 {
     VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
 }
-#ifdef CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET
+#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
 #pragma GCC diagnostic error "-Wunused-but-set-variable"
 #endif
 #endif
commit 3dd46c78525a30e98c68a44e1c3797d9fcfb0462
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 5 10:10:27 2013 +0000

    optionrom: build with discrete CPP and AS steps
    
    Build option ROM .S files with separate preprocessor and
    assembler steps because the C compiler could be unsuitable.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index b5bc9b9..ec8238e 100755
--- a/configure
+++ b/configure
@@ -264,6 +264,8 @@ else
 fi
 
 ar="${AR-${cross_prefix}ar}"
+as="${AS-${cross_prefix}as}"
+cpp="${CPP-$cc -E}"
 objcopy="${OBJCOPY-${cross_prefix}objcopy}"
 ld="${LD-${cross_prefix}ld}"
 libtool="${LIBTOOL-${cross_prefix}libtool}"
@@ -3726,6 +3728,8 @@ echo "CC_I386=$cc_i386" >> $config_host_mak
 echo "HOST_CC=$host_cc" >> $config_host_mak
 echo "OBJCC=$objcc" >> $config_host_mak
 echo "AR=$ar" >> $config_host_mak
+echo "AS=$as" >> $config_host_mak
+echo "CPP=$cpp" >> $config_host_mak
 echo "OBJCOPY=$objcopy" >> $config_host_mak
 echo "LD=$ld" >> $config_host_mak
 echo "WINDRES=$windres" >> $config_host_mak
@@ -4277,9 +4281,10 @@ for rom in seabios vgabios ; do
     config_mak=roms/$rom/config.mak
     echo "# Automatically generated by configure - do not modify" > $config_mak
     echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak
+    echo "AS=$as" >> $config_mak
     echo "CC=$cc" >> $config_mak
     echo "BCC=bcc" >> $config_mak
-    echo "CPP=${cross_prefix}cpp" >> $config_mak
+    echo "CPP=$cpp" >> $config_mak
     echo "OBJCOPY=objcopy" >> $config_mak
     echo "IASL=iasl" >> $config_mak
     echo "LD=$ld" >> $config_mak
diff --git a/rules.mak b/rules.mak
index 8448b94..fe0c881 100644
--- a/rules.mak
+++ b/rules.mak
@@ -28,8 +28,11 @@ else
 	$(call quiet-command,$(LIBTOOL) --mode=compile --quiet --tag=CC $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  lt CC $@")
 endif
 
-%.o: %.S
-	$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  AS    $(TARGET_DIR)$@")
+%.asm: %.S
+	$(call quiet-command,$(CPP) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -o $@ $<,"  CPP   $(TARGET_DIR)$@")
+
+%.o: %.asm
+	$(call quiet-command,$(AS) $(ASFLAGS) -o $@ $<,"  AS    $(TARGET_DIR)$@")
 
 %.o: %.m
 	$(call quiet-command,$(OBJCC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<,"  OBJC  $(TARGET_DIR)$@")
commit b6d9439c0d221b477c479a41a46797eee228bf88
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 5 14:48:22 2013 +0000

    slirp: remove unused field tt
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/slirp/slirp.h b/slirp/slirp.h
index dfc3e3a..fe0e65d 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -215,7 +215,6 @@ struct Slirp {
     char client_hostname[33];
 
     int restricted;
-    struct timeval tt;
     struct ex_list *exec_list;
 
     /* mbuf states */
commit 338d80dd353c50b6397723ffecf7e5bc3ba1651d
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:33 2013 -0800

    user: Consider symbolic links as possible directories
    
    Commit 2296f194dfde4c0a54f249d3fdb8c8ca21dc611b reduced the number
    of syscalls performed during user emulation startup, but failed to
    consider the use of symbolic links in creating directory structures.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/path.c b/path.c
index ef3f277..4c5b0f6 100644
--- a/path.c
+++ b/path.c
@@ -58,9 +58,10 @@ static struct pathelem *new_entry(const char *root,
 #define streq(a,b) (strcmp((a), (b)) == 0)
 
 /* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN)
+#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
 # define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type)  ((type) == DT_DIR || (type) == DT_UNKNOWN)
+# define is_dir_maybe(type) \
+    ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
 #else
 # define dirent_type(dirent) (1)
 # define is_dir_maybe(type)  (type)
commit d2565875ec5a483ddcdf3cec821830bd1f082cf6
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:32 2013 -0800

    alpha-linux-user: Fix sigaction
    
    Unconditional bswap replaced by __get_user/__put_user.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 95e2ffa..407619a 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -607,28 +607,22 @@ int do_sigaction(int sig, const struct target_sigaction *act,
             sig, act, oact);
 #endif
     if (oact) {
-        oact->_sa_handler = tswapal(k->_sa_handler);
-#if defined(TARGET_MIPS) || defined (TARGET_ALPHA)
-        oact->sa_flags = bswap32(k->sa_flags);
-#else
-        oact->sa_flags = tswapal(k->sa_flags);
-#endif
+        __put_user(k->_sa_handler, &oact->_sa_handler);
+        __put_user(k->sa_flags, &oact->sa_flags);
 #if !defined(TARGET_MIPS)
-        oact->sa_restorer = tswapal(k->sa_restorer);
+        __put_user(k->sa_restorer, &oact->sa_restorer);
 #endif
+        /* Not swapped.  */
         oact->sa_mask = k->sa_mask;
     }
     if (act) {
         /* FIXME: This is not threadsafe.  */
-        k->_sa_handler = tswapal(act->_sa_handler);
-#if defined(TARGET_MIPS) || defined (TARGET_ALPHA)
-        k->sa_flags = bswap32(act->sa_flags);
-#else
-        k->sa_flags = tswapal(act->sa_flags);
-#endif
+        __get_user(k->_sa_handler, &act->_sa_handler);
+        __get_user(k->sa_flags, &act->sa_flags);
 #if !defined(TARGET_MIPS)
-        k->sa_restorer = tswapal(act->sa_restorer);
+        __get_user(k->sa_restorer, &act->sa_restorer);
 #endif
+        /* To be swapped in target_to_host_sigset.  */
         k->sa_mask = act->sa_mask;
 
         /* we update the host linux signal state */
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index d4589e7..f8f5539 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -544,7 +544,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
 struct target_old_sigaction {
     abi_ulong _sa_handler;
     abi_ulong sa_mask;
-    abi_ulong sa_flags;
+    int32_t sa_flags;
 };
 
 struct target_rt_sigaction {
commit 658f2dc970996d547a641b5685e384ebe6f2648e
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:31 2013 -0800

    linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr
    
    The previous formuation with multiple assignments to __typeof(*hptr) falls
    down when hptr is qualified const.  E.g. with const struct S *p, p->f is
    also qualified const.
    
    With this formulation, there's no assignment to any local variable.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 8a3538c..31a220a 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -287,36 +287,39 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
                             (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
 }
 
-/* NOTE __get_user and __put_user use host pointers and don't check access. */
-/* These are usually used to access struct data members once the
- * struct has been locked - usually with lock_user_struct().
- */
-#define __put_user(x, hptr)\
-({ __typeof(*hptr) pu_ = (x);\
-    switch(sizeof(*hptr)) {\
-    case 1: break;\
-    case 2: pu_ = tswap16(pu_); break; \
-    case 4: pu_ = tswap32(pu_); break; \
-    case 8: pu_ = tswap64(pu_); break; \
-    default: abort();\
-    }\
-    memcpy(hptr, &pu_, sizeof(pu_)); \
-    0;\
-})
-
-#define __get_user(x, hptr) \
-({ __typeof(*hptr) gu_; \
-    memcpy(&gu_, hptr, sizeof(gu_)); \
-    switch(sizeof(*hptr)) {\
-    case 1: break; \
-    case 2: gu_ = tswap16(gu_); break; \
-    case 4: gu_ = tswap32(gu_); break; \
-    case 8: gu_ = tswap64(gu_); break; \
-    default: abort();\
-    }\
-    (x) = gu_; \
-    0;\
-})
+/* NOTE __get_user and __put_user use host pointers and don't check access.
+   These are usually used to access struct data members once the struct has
+   been locked - usually with lock_user_struct.  */
+
+/* Tricky points:
+   - Use __builtin_choose_expr to avoid type promotion from ?:,
+   - Invalid sizes result in a compile time error stemming from
+     the fact that abort has no parameters.
+   - It's easier to use the endian-specific unaligned load/store
+     functions than host-endian unaligned load/store plus tswapN.  */
+
+#define __put_user_e(x, hptr, e)                                        \
+  (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p,                   \
+   __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p,             \
+   __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p,             \
+   __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort))))   \
+     ((hptr), (x)), 0)
+
+#define __get_user_e(x, hptr, e)                                        \
+  ((x) =                                                                \
+   __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p,                  \
+   __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p,            \
+   __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p,             \
+   __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort))))   \
+     (hptr), 0)
+
+#ifdef TARGET_WORDS_BIGENDIAN
+# define __put_user(x, hptr)  __put_user_e(x, hptr, be)
+# define __get_user(x, hptr)  __get_user_e(x, hptr, be)
+#else
+# define __put_user(x, hptr)  __put_user_e(x, hptr, le)
+# define __get_user(x, hptr)  __get_user_e(x, hptr, le)
+#endif
 
 /* put_user()/get_user() take a guest address and check access */
 /* These are usually used to access an atomic data type, such as an int,
commit c732a52d3e3b7ed42d7daa94ba40a83408cd6f22
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:30 2013 -0800

    bswap: Rewrite cpu_to_<endian><type>u with {ld,st}<type>_<endian>_p
    
    We've now optimized the ld/st versions; reuse that for the "legacy"
    versions.  Always use inlines so that we get the type checking that
    we expect.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 68cda6a..be9b035 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -121,100 +121,6 @@ CPU_CONVERT(le, 16, uint16_t)
 CPU_CONVERT(le, 32, uint32_t)
 CPU_CONVERT(le, 64, uint64_t)
 
-/* unaligned versions (optimized for frequent unaligned accesses)*/
-
-#if defined(__i386__) || defined(_ARCH_PPC)
-
-#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
-#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
-#define le16_to_cpupu(p) le16_to_cpup(p)
-#define le32_to_cpupu(p) le32_to_cpup(p)
-#define be32_to_cpupu(p) be32_to_cpup(p)
-
-#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
-#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
-#define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
-
-#else
-
-static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
-{
-    uint8_t *p1 = (uint8_t *)p;
-
-    p1[0] = v & 0xff;
-    p1[1] = v >> 8;
-}
-
-static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
-{
-    uint8_t *p1 = (uint8_t *)p;
-
-    p1[0] = v & 0xff;
-    p1[1] = v >> 8;
-    p1[2] = v >> 16;
-    p1[3] = v >> 24;
-}
-
-static inline uint16_t le16_to_cpupu(const uint16_t *p)
-{
-    const uint8_t *p1 = (const uint8_t *)p;
-    return p1[0] | (p1[1] << 8);
-}
-
-static inline uint32_t le32_to_cpupu(const uint32_t *p)
-{
-    const uint8_t *p1 = (const uint8_t *)p;
-    return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
-}
-
-static inline uint32_t be32_to_cpupu(const uint32_t *p)
-{
-    const uint8_t *p1 = (const uint8_t *)p;
-    return p1[3] | (p1[2] << 8) | (p1[1] << 16) | (p1[0] << 24);
-}
-
-static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
-{
-    uint8_t *p1 = (uint8_t *)p;
-
-    p1[0] = v >> 8;
-    p1[1] = v & 0xff;
-}
-
-static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
-{
-    uint8_t *p1 = (uint8_t *)p;
-
-    p1[0] = v >> 24;
-    p1[1] = v >> 16;
-    p1[2] = v >> 8;
-    p1[3] = v & 0xff;
-}
-
-static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
-{
-    uint8_t *p1 = (uint8_t *)p;
-
-    p1[0] = v >> 56;
-    p1[1] = v >> 48;
-    p1[2] = v >> 40;
-    p1[3] = v >> 32;
-    p1[4] = v >> 24;
-    p1[5] = v >> 16;
-    p1[6] = v >> 8;
-    p1[7] = v & 0xff;
-}
-
-#endif
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define cpu_to_32wu cpu_to_be32wu
-#define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
-#else
-#define cpu_to_32wu cpu_to_le32wu
-#define leul_to_cpu(v) (v)
-#endif
-
 /* len must be one of 1, 2, 4 */
 static inline uint32_t qemu_bswap_len(uint32_t value, int len)
 {
@@ -310,6 +216,7 @@ typedef union {
  *   be   : big endian
  *   le   : little endian
  */
+
 static inline int ldub_p(const void *ptr)
 {
     return *(uint8_t *)ptr;
@@ -502,6 +409,58 @@ static inline void stfq_be_p(void *ptr, float64 v)
     stq_be_p(ptr, u.ll);
 }
 
+/* Legacy unaligned versions.  Note that we never had a complete set.  */
+
+static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
+{
+    stw_le_p(p, v);
+}
+
+static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
+{
+    stl_le_p(p, v);
+}
+
+static inline uint16_t le16_to_cpupu(const uint16_t *p)
+{
+    return lduw_le_p(p);
+}
+
+static inline uint32_t le32_to_cpupu(const uint32_t *p)
+{
+    return ldl_le_p(p);
+}
+
+static inline uint32_t be32_to_cpupu(const uint32_t *p)
+{
+    return ldl_be_p(p);
+}
+
+static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
+{
+    stw_be_p(p, v);
+}
+
+static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
+{
+    stl_be_p(p, v);
+}
+
+static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
+{
+    stq_be_p(p, v);
+}
+
+static inline void cpu_to_32wu(uint32_t *p, uint32_t v)
+{
+    stl_p(p, v);
+}
+
+static inline unsigned long leul_to_cpu(unsigned long v)
+{
+    return le_bswap(v, HOST_LONG_BITS);
+}
+
 #undef le_bswap
 #undef be_bswap
 #undef le_bswaps
commit 612d590ebc6cef179cf5f7823522237e622ab430
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:29 2013 -0800

    bswap: Rewrite all ld<type>_<endian>_p functions
    
    Use the new host endian unaligned access functions instead of
    open coding byte-by-byte references.  Remove assembly special
    cases for i386 and ppc -- we've now exposed the operation to
    the compiler sufficiently for these to be optimized automatically.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 381554b..68cda6a 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -215,11 +215,6 @@ static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
 #define leul_to_cpu(v) (v)
 #endif
 
-#undef le_bswap
-#undef be_bswap
-#undef le_bswaps
-#undef be_bswaps
-
 /* len must be one of 1, 2, 4 */
 static inline uint32_t qemu_bswap_len(uint32_t value, int len)
 {
@@ -377,115 +372,61 @@ static inline void stq_p(void *ptr, uint64_t v)
     memcpy(ptr, &v, sizeof(v));
 }
 
-/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
-   kernel handles unaligned load/stores may give better results, but
-   it is a system wide setting : bad */
-#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-/* conservative code for little endian unaligned accesses */
 static inline int lduw_le_p(const void *ptr)
 {
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8);
-#endif
+    return (uint16_t)le_bswap(lduw_p(ptr), 16);
 }
 
 static inline int ldsw_le_p(const void *ptr)
 {
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *p = ptr;
-    return (int16_t)(p[0] | (p[1] << 8));
-#endif
+    return (int16_t)le_bswap(lduw_p(ptr), 16);
 }
 
 static inline int ldl_le_p(const void *ptr)
 {
-#ifdef _ARCH_PPC
-    int val;
-    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
-    return val;
-#else
-    const uint8_t *p = ptr;
-    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-#endif
+    return le_bswap(ldl_p(ptr), 32);
 }
 
 static inline uint64_t ldq_le_p(const void *ptr)
 {
-    const uint8_t *p = ptr;
-    uint32_t v1, v2;
-    v1 = ldl_le_p(p);
-    v2 = ldl_le_p(p + 4);
-    return v1 | ((uint64_t)v2 << 32);
+    return le_bswap(ldq_p(ptr), 64);
 }
 
 static inline void stw_le_p(void *ptr, int v)
 {
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-#endif
+    stw_p(ptr, le_bswap(v, 16));
 }
 
 static inline void stl_le_p(void *ptr, int v)
 {
-#ifdef _ARCH_PPC
-    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
-#else
-    uint8_t *p = ptr;
-    p[0] = v;
-    p[1] = v >> 8;
-    p[2] = v >> 16;
-    p[3] = v >> 24;
-#endif
+    stl_p(ptr, le_bswap(v, 32));
 }
 
 static inline void stq_le_p(void *ptr, uint64_t v)
 {
-    uint8_t *p = ptr;
-    stl_le_p(p, (uint32_t)v);
-    stl_le_p(p + 4, v >> 32);
+    stq_p(ptr, le_bswap(v, 64));
 }
 
 /* float access */
 
 static inline float32 ldfl_le_p(const void *ptr)
 {
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_le_p(ptr);
+    CPU_FloatU u;
+    u.l = ldl_le_p(ptr);
     return u.f;
 }
 
 static inline void stfl_le_p(void *ptr, float32 v)
 {
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
+    CPU_FloatU u;
     u.f = v;
-    stl_le_p(ptr, u.i);
+    stl_le_p(ptr, u.l);
 }
 
 static inline float64 ldfq_le_p(const void *ptr)
 {
     CPU_DoubleU u;
-    u.l.lower = ldl_le_p(ptr);
-    u.l.upper = ldl_le_p(ptr + 4);
+    u.ll = ldq_le_p(ptr);
     return u.d;
 }
 
@@ -493,188 +434,64 @@ static inline void stfq_le_p(void *ptr, float64 v)
 {
     CPU_DoubleU u;
     u.d = v;
-    stl_le_p(ptr, u.l.lower);
-    stl_le_p(ptr + 4, u.l.upper);
+    stq_le_p(ptr, u.ll);
 }
 
-#else
-
-static inline int lduw_le_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
-}
-#endif
-
-#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
 static inline int lduw_be_p(const void *ptr)
 {
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return ((b[0] << 8) | b[1]);
-#endif
+    return (uint16_t)be_bswap(lduw_p(ptr), 16);
 }
 
 static inline int ldsw_be_p(const void *ptr)
 {
-#if defined(__i386__)
-    int val;
-    asm volatile ("movzwl %1, %0\n"
-                  "xchgb %b0, %h0\n"
-                  : "=q" (val)
-                  : "m" (*(uint16_t *)ptr));
-    return (int16_t)val;
-#else
-    const uint8_t *b = ptr;
-    return (int16_t)((b[0] << 8) | b[1]);
-#endif
+    return (int16_t)be_bswap(lduw_p(ptr), 16);
 }
 
 static inline int ldl_be_p(const void *ptr)
 {
-#if defined(__i386__) || defined(__x86_64__)
-    int val;
-    asm volatile ("movl %1, %0\n"
-                  "bswap %0\n"
-                  : "=r" (val)
-                  : "m" (*(uint32_t *)ptr));
-    return val;
-#else
-    const uint8_t *b = ptr;
-    return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
-#endif
+    return be_bswap(ldl_p(ptr), 32);
 }
 
 static inline uint64_t ldq_be_p(const void *ptr)
 {
-    uint32_t a,b;
-    a = ldl_be_p(ptr);
-    b = ldl_be_p((uint8_t *)ptr + 4);
-    return (((uint64_t)a<<32)|b);
+    return be_bswap(ldq_p(ptr), 64);
 }
 
 static inline void stw_be_p(void *ptr, int v)
 {
-#if defined(__i386__)
-    asm volatile ("xchgb %b0, %h0\n"
-                  "movw %w0, %1\n"
-                  : "=q" (v)
-                  : "m" (*(uint16_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 8;
-    d[1] = v;
-#endif
+    stw_p(ptr, be_bswap(v, 16));
 }
 
 static inline void stl_be_p(void *ptr, int v)
 {
-#if defined(__i386__) || defined(__x86_64__)
-    asm volatile ("bswap %0\n"
-                  "movl %0, %1\n"
-                  : "=r" (v)
-                  : "m" (*(uint32_t *)ptr), "0" (v));
-#else
-    uint8_t *d = (uint8_t *) ptr;
-    d[0] = v >> 24;
-    d[1] = v >> 16;
-    d[2] = v >> 8;
-    d[3] = v;
-#endif
+    stl_p(ptr, be_bswap(v, 32));
 }
 
 static inline void stq_be_p(void *ptr, uint64_t v)
 {
-    stl_be_p(ptr, v >> 32);
-    stl_be_p((uint8_t *)ptr + 4, v);
+    stq_p(ptr, be_bswap(v, 64));
 }
 
 /* float access */
 
 static inline float32 ldfl_be_p(const void *ptr)
 {
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
-    u.i = ldl_be_p(ptr);
+    CPU_FloatU u;
+    u.l = ldl_be_p(ptr);
     return u.f;
 }
 
 static inline void stfl_be_p(void *ptr, float32 v)
 {
-    union {
-        float32 f;
-        uint32_t i;
-    } u;
+    CPU_FloatU u;
     u.f = v;
-    stl_be_p(ptr, u.i);
+    stl_be_p(ptr, u.l);
 }
 
 static inline float64 ldfq_be_p(const void *ptr)
 {
     CPU_DoubleU u;
-    u.l.upper = ldl_be_p(ptr);
-    u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
+    u.ll = ldq_be_p(ptr);
     return u.d;
 }
 
@@ -682,69 +499,12 @@ static inline void stfq_be_p(void *ptr, float64 v)
 {
     CPU_DoubleU u;
     u.d = v;
-    stl_be_p(ptr, u.l.upper);
-    stl_be_p((uint8_t *)ptr + 4, u.l.lower);
-}
-
-#else
-
-static inline int lduw_be_p(const void *ptr)
-{
-    return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
-    return *(int16_t *)ptr;
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
-    return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
-    return *(uint64_t *)ptr;
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
-    *(uint16_t *)ptr = v;
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
-    *(uint32_t *)ptr = v;
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
-    *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
-    return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
-    return *(float64 *)ptr;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
-    *(float32 *)ptr = v;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
-    *(float64 *)ptr = v;
+    stq_be_p(ptr, u.ll);
 }
 
-#endif
+#undef le_bswap
+#undef be_bswap
+#undef le_bswaps
+#undef be_bswaps
 
 #endif /* BSWAP_H */
commit 7db2145a6826b14efceb8dd64bfe6ad8647072eb
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:28 2013 -0800

    bswap: Add host endian unaligned access functions
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index b2a8f94..381554b 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -226,6 +226,8 @@ static inline uint32_t qemu_bswap_len(uint32_t value, int len)
     return bswap32(value) >> (32 - 8 * len);
 }
 
+/* Unions for reinterpreting between floats and integers.  */
+
 typedef union {
     float32 f;
     uint32_t l;
@@ -309,7 +311,7 @@ typedef union {
  *   q: 64 bits
  *
  * endian is:
- * (empty): 8 bit access
+ * (empty): host endian
  *   be   : big endian
  *   le   : little endian
  */
@@ -328,6 +330,53 @@ static inline void stb_p(void *ptr, int v)
     *(uint8_t *)ptr = v;
 }
 
+/* Any compiler worth its salt will turn these memcpy into native unaligned
+   operations.  Thus we don't need to play games with packed attributes, or
+   inline byte-by-byte stores.  */
+
+static inline int lduw_p(const void *ptr)
+{
+    uint16_t r;
+    memcpy(&r, ptr, sizeof(r));
+    return r;
+}
+
+static inline int ldsw_p(const void *ptr)
+{
+    int16_t r;
+    memcpy(&r, ptr, sizeof(r));
+    return r;
+}
+
+static inline void stw_p(void *ptr, uint16_t v)
+{
+    memcpy(ptr, &v, sizeof(v));
+}
+
+static inline int ldl_p(const void *ptr)
+{
+    int32_t r;
+    memcpy(&r, ptr, sizeof(r));
+    return r;
+}
+
+static inline void stl_p(void *ptr, uint32_t v)
+{
+    memcpy(ptr, &v, sizeof(v));
+}
+
+static inline uint64_t ldq_p(const void *ptr)
+{
+    uint64_t r;
+    memcpy(&r, ptr, sizeof(r));
+    return r;
+}
+
+static inline void stq_p(void *ptr, uint64_t v)
+{
+    memcpy(ptr, &v, sizeof(v));
+}
+
 /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
    kernel handles unaligned load/stores may give better results, but
    it is a system wide setting : bad */
commit cdfe2851c6c33c133bd90c2643cb0486c0f5b325
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:27 2013 -0800

    bswap: Tidy base definitions of bswapN
    
    Move the bswap_N -> bswapN wrappers inside CONFIG_BYTESWAP_H.
    
    Change the ultimate fallback defintions from macros to inline functions.
    The proper types recieved by the function arguments means we can remove
    unnecessary casts, making the code more readable.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 2006fcd..b2a8f94 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -7,48 +7,11 @@
 #include "fpu/softfloat.h"
 
 #ifdef CONFIG_MACHINE_BSWAP_H
-#include <sys/endian.h>
-#include <sys/types.h>
-#include <machine/bswap.h>
-#else
-
-#ifdef CONFIG_BYTESWAP_H
-#include <byteswap.h>
-#else
-
-#define bswap_16(x) \
-({ \
-	uint16_t __x = (x); \
-	((uint16_t)( \
-		(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
-		(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
-})
-
-#define bswap_32(x) \
-({ \
-	uint32_t __x = (x); \
-	((uint32_t)( \
-		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
-		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
-		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
-		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
-})
-
-#define bswap_64(x) \
-({ \
-	uint64_t __x = (x); \
-	((uint64_t)( \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
-	        (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
-		(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
-})
-
-#endif /* !CONFIG_BYTESWAP_H */
+# include <sys/endian.h>
+# include <sys/types.h>
+# include <machine/bswap.h>
+#elif defined(CONFIG_BYTESWAP_H)
+# include <byteswap.h>
 
 static inline uint16_t bswap16(uint16_t x)
 {
@@ -64,7 +27,32 @@ static inline uint64_t bswap64(uint64_t x)
 {
     return bswap_64(x);
 }
+# else
+static inline uint16_t bswap16(uint16_t x)
+{
+    return (((x & 0x00ff) << 8) |
+            ((x & 0xff00) >> 8));
+}
 
+static inline uint32_t bswap32(uint32_t x)
+{
+    return (((x & 0x000000ffU) << 24) |
+            ((x & 0x0000ff00U) <<  8) |
+            ((x & 0x00ff0000U) >>  8) |
+            ((x & 0xff000000U) >> 24));
+}
+
+static inline uint64_t bswap64(uint64_t x)
+{
+    return (((x & 0x00000000000000ffULL) << 56) |
+            ((x & 0x000000000000ff00ULL) << 40) |
+            ((x & 0x0000000000ff0000ULL) << 24) |
+            ((x & 0x00000000ff000000ULL) <<  8) |
+            ((x & 0x000000ff00000000ULL) >>  8) |
+            ((x & 0x0000ff0000000000ULL) >> 24) |
+            ((x & 0x00ff000000000000ULL) >> 40) |
+            ((x & 0xff00000000000000ULL) >> 56));
+}
 #endif /* ! CONFIG_MACHINE_BSWAP_H */
 
 static inline void bswap16s(uint16_t *s)
commit fedb88bd32d331131d77a9b567d12e682fd102ac
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Jan 4 16:39:26 2013 -0800

    fdt: Use bswapN instead of bswap_N
    
    Fixes the libfdt enabled build for hosts that have <machine/bswap.h>.
    
    The code at the beginning of qemu/bswap.h is attempting to standardize
    on bswapN.  In the case of CONFIG_MACHINE_BSWAP_H, this is all we get.
    In the case of CONFIG_BYTESWAP_H, we get bswap_N from the system header
    and then wrap these with inline functions to get bswapN.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 7938d73..3667d4c 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -22,15 +22,15 @@
 #include "qemu/bswap.h"
 
 #ifdef HOST_WORDS_BIGENDIAN
-#define fdt32_to_cpu(x)		(x)
-#define cpu_to_fdt32(x)		(x)
-#define fdt64_to_cpu(x)		(x)
-#define cpu_to_fdt64(x)		(x)
+#define fdt32_to_cpu(x)  (x)
+#define cpu_to_fdt32(x)  (x)
+#define fdt64_to_cpu(x)  (x)
+#define cpu_to_fdt64(x)  (x)
 #else
-#define fdt32_to_cpu(x)		(bswap_32((x)))
-#define cpu_to_fdt32(x)		(bswap_32((x)))
-#define fdt64_to_cpu(x)		(bswap_64((x)))
-#define cpu_to_fdt64(x)		(bswap_64((x)))
+#define fdt32_to_cpu(x)  bswap32(x)
+#define cpu_to_fdt32(x)  bswap32(x)
+#define fdt64_to_cpu(x)  bswap64(x)
+#define cpu_to_fdt64(x)  bswap64(x)
 #endif
 
 #endif /* _LIBFDT_ENV_H */
commit 314e2296dc945e286b605563d7b6e6b269d29816
Author: Alex_Rozenman at mentor.com <Alex_Rozenman at mentor.com>
Date:   Fri Jan 11 15:21:22 2013 +0000

    target-arm: Fix SWI (SVC) instruction in M profile.
    
    When do_interrupt_v7m is called with EXCP_SWI, the PC already
    points to the next instruction. Don't modify it here.
    
    Signed-off-by: Alex Rozenman <Alex_Rozenman at mentor.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0525aec..66ab78e 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1736,7 +1736,7 @@ static void do_interrupt_v7m(CPUARMState *env)
         armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
         return;
     case EXCP_SWI:
-        env->regs[15] += 2;
+        /* The PC already points to the next instruction.  */
         armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
         return;
     case EXCP_PREFETCH_ABORT:
commit 918fd0839eeafc83bd4984364321a947d29041fe
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Fri Jan 11 15:21:22 2013 +0000

    target-arm: use type_register() instead of type_register_static()
    
    The type_register_static() interface is documented as:
    
      type_register_static:
      @info: The #TypeInfo of the new type.
    
      @info and all of the strings it points to should exist for the life
      time that the type is registered.
    
    But cpu_register() uses a stack variable for the 'info' argument, so it
    has to use type_register() instead of type_register_static().
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 17875ed..94536bb 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -778,7 +778,7 @@ static void cpu_register(const ARMCPUInfo *info)
         .class_size = sizeof(ARMCPUClass),
     };
 
-    type_register_static(&type_info);
+    type_register(&type_info);
 }
 
 static const TypeInfo arm_cpu_type_info = {
commit fedf2de31023b4ee71a4e578db013976243a8143
Merge: e2848a7 c02e1ea
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 11 08:43:18 2013 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    * stefanha/trivial-patches:
      hw/pc.c: Fix converting of ioport_register* to MemoryRegion
      Replace remaining gmtime, localtime by gmtime_r, localtime_r
      savevm: Remove MinGW specific code which is no longer needed
      qga/channel-posix.c: Explicitly include string.h
      configure: Fix comment (copy+paste bug)
      readline: avoid memcpy() of overlapping regions
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit e2848a78b0a6715f94623bdf43ef74d3d08cfe4d
Merge: 80ec243 7e973bb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 11 08:36:52 2013 -0600

    Merge remote-tracking branch 'kraxel/q35.1' into staging
    
    * kraxel/q35.1:
      Makefile: install the "acpi-dsdt.aml" and "q35-acpi-dsdt.aml" blobs too
      pc: rename machine types
      q35: document chipset devices
      q35: add ich9 intel hda controller
    
    Conflicts:
    	hw/intel-hda.c
    
    aliguori: resolve conflict with static const change from Andreas.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --cc hw/intel-hda.c
index 0a533df,eed1d38..784c229
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@@ -1249,11 -1246,40 +1246,40 @@@ static void intel_hda_class_init_common
      dc->props = intel_hda_properties;
  }
  
- static const TypeInfo intel_hda_info = {
+ static void intel_hda_class_init_ich6(ObjectClass *klass, void *data)
+ {
+     DeviceClass *dc = DEVICE_CLASS(klass);
+     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ 
+     intel_hda_class_init_common(klass);
+     k->device_id = 0x2668;
+     k->revision = 1;
+     dc->desc = "Intel HD Audio Controller (ich6)";
+ }
+ 
+ static void intel_hda_class_init_ich9(ObjectClass *klass, void *data)
+ {
+     DeviceClass *dc = DEVICE_CLASS(klass);
+     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ 
+     intel_hda_class_init_common(klass);
+     k->device_id = 0x293e;
+     k->revision = 3;
+     dc->desc = "Intel HD Audio Controller (ich9)";
+ }
+ 
 -static TypeInfo intel_hda_info_ich6 = {
++static const TypeInfo intel_hda_info_ich6 = {
      .name          = "intel-hda",
      .parent        = TYPE_PCI_DEVICE,
      .instance_size = sizeof(IntelHDAState),
-     .class_init    = intel_hda_class_init,
+     .class_init    = intel_hda_class_init_ich6,
+ };
+ 
 -static TypeInfo intel_hda_info_ich9 = {
++static const TypeInfo intel_hda_info_ich9 = {
+     .name          = "ich9-intel-hda",
+     .parent        = TYPE_PCI_DEVICE,
+     .instance_size = sizeof(IntelHDAState),
+     .class_init    = intel_hda_class_init_ich9,
  };
  
  static void hda_codec_device_class_init(ObjectClass *klass, void *data)
commit 80ec24328607937690d0d620b99e8c24ab29e8f5
Merge: 47a150a 63e3555
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Jan 11 08:23:16 2013 -0600

    Merge remote-tracking branch 'afaerber-or/prep-up' into staging
    
    * afaerber-or/prep-up:
      prep: Use pc87312 device instead of collection of random ISA devices
      prep: Add pc87312 Super I/O emulation
      prep: Include devices for ppc64 as well
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit c02e1eac887b1b0aee7361b1fcf889e7d47fed9d
Author: Julien Grall <julien.grall at citrix.com>
Date:   Wed Jan 9 18:10:22 2013 +0000

    hw/pc.c: Fix converting of ioport_register* to MemoryRegion
    
    The commit 258711 introduced MemoryRegion to replace ioport_region*
    for ioport 80h and F0h.
    A MemoryRegion needs to have both read and write callback otherwise a segfault
    will occur when an access is made.
    
    The previous behaviour of this both ioport is to return 0xffffffffffffffff.
    So keep this behaviour.
    
    Reported-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Signed-off-by: Julien Grall <julien.grall at citrix.com>
    Tested-by: Adam Lackorzynski <adam at os.inf.tu-dresden.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/pc.c b/hw/pc.c
index df0c48e..90b1bf7 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -103,6 +103,11 @@ static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
 {
 }
 
+static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffff;
+}
+
 /* MSDOS compatibility mode FPU exception support */
 static qemu_irq ferr_irq;
 
@@ -123,6 +128,11 @@ static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
     qemu_irq_lower(ferr_irq);
 }
 
+static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0xffffffffffffffff;
+}
+
 /* TSC handling */
 uint64_t cpu_get_tsc(CPUX86State *env)
 {
@@ -960,6 +970,7 @@ static void cpu_request_exit(void *opaque, int irq, int level)
 
 static const MemoryRegionOps ioport80_io_ops = {
     .write = ioport80_write,
+    .read = ioport80_read,
     .endianness = DEVICE_NATIVE_ENDIAN,
     .impl = {
         .min_access_size = 1,
@@ -969,6 +980,7 @@ static const MemoryRegionOps ioport80_io_ops = {
 
 static const MemoryRegionOps ioportF0_io_ops = {
     .write = ioportF0_write,
+    .read = ioportF0_read,
     .endianness = DEVICE_NATIVE_ENDIAN,
     .impl = {
         .min_access_size = 1,
commit eb7ff6fb0bddb33991fa44586ac8e2e02019dc97
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Jan 7 23:08:13 2013 +0100

    Replace remaining gmtime, localtime by gmtime_r, localtime_r
    
    This allows removing of MinGW specific code and improves
    reentrancy for POSIX hosts.
    
    [Removed unused ret variable in qemu_get_timedate() to fix warning:
    vl.c: In function ‘qemu_get_timedate’:
    vl.c:451:16: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable]
    -- Stefan Hajnoczi]
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 4e28c55..60873ea 100644
--- a/block.c
+++ b/block.c
@@ -3338,11 +3338,7 @@ char *get_human_readable_size(char *buf, int buf_size, int64_t size)
 char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
 {
     char buf1[128], date_buf[128], clock_buf[128];
-#ifdef _WIN32
-    struct tm *ptm;
-#else
     struct tm tm;
-#endif
     time_t ti;
     int64_t secs;
 
@@ -3352,15 +3348,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
                  "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
     } else {
         ti = sn->date_sec;
-#ifdef _WIN32
-        ptm = localtime(&ti);
-        strftime(date_buf, sizeof(date_buf),
-                 "%Y-%m-%d %H:%M:%S", ptm);
-#else
         localtime_r(&ti, &tm);
         strftime(date_buf, sizeof(date_buf),
                  "%Y-%m-%d %H:%M:%S", &tm);
-#endif
         secs = sn->vm_clock_nsec / 1000000000;
         snprintf(clock_buf, sizeof(clock_buf),
                  "%02d:%02d:%02d.%03d",
diff --git a/block/vvfat.c b/block/vvfat.c
index 83706ce..06e6654 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -529,13 +529,9 @@ static inline uint8_t fat_chksum(const direntry_t* entry)
 /* if return_time==0, this returns the fat_date, else the fat_time */
 static uint16_t fat_datetime(time_t time,int return_time) {
     struct tm* t;
-#ifdef _WIN32
-    t=localtime(&time); /* this is not thread safe */
-#else
     struct tm t1;
     t = &t1;
     localtime_r(&time,t);
-#endif
     if(return_time)
 	return cpu_to_le16((t->tm_sec/2)|(t->tm_min<<5)|(t->tm_hour<<11));
     return cpu_to_le16((t->tm_mday)|((t->tm_mon+1)<<5)|((t->tm_year-80)<<9));
diff --git a/hw/omap1.c b/hw/omap1.c
index 8536e96..e85f2e2 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -2830,7 +2830,7 @@ static void omap_rtc_tick(void *opaque)
         s->round = 0;
     }
 
-    memcpy(&s->current_tm, localtime(&s->ti), sizeof(s->current_tm));
+    localtime_r(&s->ti, &s->current_tm);
 
     if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
         s->status |= 0x40;
diff --git a/vl.c b/vl.c
index f056c95..aed4182 100644
--- a/vl.c
+++ b/vl.c
@@ -448,21 +448,18 @@ StatusInfo *qmp_query_status(Error **errp)
 void qemu_get_timedate(struct tm *tm, int offset)
 {
     time_t ti;
-    struct tm *ret;
 
     time(&ti);
     ti += offset;
     if (rtc_date_offset == -1) {
         if (rtc_utc)
-            ret = gmtime(&ti);
+            gmtime_r(&ti, tm);
         else
-            ret = localtime(&ti);
+            localtime_r(&ti, tm);
     } else {
         ti -= rtc_date_offset;
-        ret = gmtime(&ti);
+        gmtime_r(&ti, tm);
     }
-
-    memcpy(tm, ret, sizeof(struct tm));
 }
 
 int qemu_timedate_diff(struct tm *tm)
commit 68b891ec3937aa2e18eed5a403b1d9fd9b875084
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Jan 7 22:20:27 2013 +0100

    savevm: Remove MinGW specific code which is no longer needed
    
    QEMU provides a portable function qemu_gettimeofday instead of
    gettimeofday and also an implementation of localtime_r for MinGW.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/savevm.c b/savevm.c
index 529d60e..4e970ca 100644
--- a/savevm.c
+++ b/savevm.c
@@ -23,15 +23,6 @@
  */
 
 #include "config-host.h"
-
-#ifndef _WIN32
-#include <arpa/inet.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
 #include "qemu-common.h"
 #include "hw/hw.h"
 #include "hw/qdev.h"
@@ -2093,13 +2084,8 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     QEMUFile *f;
     int saved_vm_running;
     uint64_t vm_state_size;
-#ifdef _WIN32
-    struct _timeb tb;
-    struct tm *ptm;
-#else
-    struct timeval tv;
+    qemu_timeval tv;
     struct tm tm;
-#endif
     const char *name = qdict_get_try_str(qdict, "name");
 
     /* Verify if there is a device that doesn't support snapshots and is writable */
@@ -2129,15 +2115,9 @@ void do_savevm(Monitor *mon, const QDict *qdict)
     memset(sn, 0, sizeof(*sn));
 
     /* fill auxiliary fields */
-#ifdef _WIN32
-    _ftime(&tb);
-    sn->date_sec = tb.time;
-    sn->date_nsec = tb.millitm * 1000000;
-#else
-    gettimeofday(&tv, NULL);
+    qemu_gettimeofday(&tv);
     sn->date_sec = tv.tv_sec;
     sn->date_nsec = tv.tv_usec * 1000;
-#endif
     sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
 
     if (name) {
@@ -2149,15 +2129,9 @@ void do_savevm(Monitor *mon, const QDict *qdict)
             pstrcpy(sn->name, sizeof(sn->name), name);
         }
     } else {
-#ifdef _WIN32
-        time_t t = tb.time;
-        ptm = localtime(&t);
-        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
-#else
         /* cast below needed for OpenBSD where tv_sec is still 'long' */
         localtime_r((const time_t *)&tv.tv_sec, &tm);
         strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
-#endif
     }
 
     /* Delete old snapshots of the same name */
commit 1d57db193f2eb619ccc9a60e76120379b757d9f2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jan 7 17:29:55 2013 +0000

    qga/channel-posix.c: Explicitly include string.h
    
    Explicitly include string.h to avoid warnings under MacOS X/clang
    about implicit declarations of strerror() and strlen().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index d4fd628..ca9e4aa 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -4,6 +4,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#include <string.h>
 #include "qemu/osdep.h"
 #include "qemu/sockets.h"
 #include "qga/channel.h"
commit 75f13596452692fb7375ee558e9fb37cd649e603
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Jan 5 12:17:38 2013 +0100

    configure: Fix comment (copy+paste bug)
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index fe18ed2..148d5aa 100755
--- a/configure
+++ b/configure
@@ -2705,7 +2705,7 @@ if compile_prog "" "" ; then
   byteswap_h=yes
 fi
 
-# Search for bswap_32 function
+# Search for bswap32 function
 bswap_h=no
 cat > $TMPC << EOF
 #include <sys/endian.h>
commit 7e973bb2e17f929f47376a3872f7ccdff25a51ab
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Tue Jan 8 19:52:20 2013 +0100

    Makefile: install the "acpi-dsdt.aml" and "q35-acpi-dsdt.aml" blobs too
    
    The WARNING message from commit f7e4dd6c made me notice.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/Makefile b/Makefile
index ee06448..0200bf3 100644
--- a/Makefile
+++ b/Makefile
@@ -280,6 +280,7 @@ bepo
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
 vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
+acpi-dsdt.aml q35-acpi-dsdt.aml \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
 pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
 pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
commit 94dec5948aeb240c7e324ce9ecffeb3e066c1b69
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jan 8 08:53:13 2013 +0100

    pc: rename machine types
    
    Starting with release 1.4 we have a fully functional q35 machine type,
    i.e. "qemu -M q35" JustWorks[tm].  Update machine type names to reflect
    that:
    
      * pc-1.4 becomes pc-i440fx-1.4
      * q35-next becomes pc-q35-1.4
    
    The pc-1.3 (+older) names are maintained for compatibility reasons.
    For the same reason the "pc" and "q35" aliases are kept.  pc-piix-1.4
    continues to be the default machine type, again for compatibility
    reasons.
    
    Also updated the description (shown by "qemu -M ?") with host bridge
    name, south bridge name and chipset release year.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 2b3d58b..e630aea 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -282,10 +282,10 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
 }
 #endif
 
-static QEMUMachine pc_machine_v1_4 = {
-    .name = "pc-1.4",
+static QEMUMachine pc_i440fx_machine_v1_4 = {
+    .name = "pc-i440fx-1.4",
     .alias = "pc",
-    .desc = "Standard PC",
+    .desc = "Standard PC (i440FX + PIIX, 1996)",
     .init = pc_init_pci_1_3,
     .max_cpus = 255,
     .is_default = 1,
@@ -646,7 +646,7 @@ static QEMUMachine xenfv_machine = {
 
 static void pc_machine_init(void)
 {
-    qemu_register_machine(&pc_machine_v1_4);
+    qemu_register_machine(&pc_i440fx_machine_v1_4);
     qemu_register_machine(&pc_machine_v1_3);
     qemu_register_machine(&pc_machine_v1_2);
     qemu_register_machine(&pc_machine_v1_1);
diff --git a/hw/pc_q35.c b/hw/pc_q35.c
index ef540b6..52d9976 100644
--- a/hw/pc_q35.c
+++ b/hw/pc_q35.c
@@ -209,9 +209,9 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
 }
 
 static QEMUMachine pc_q35_machine = {
-    .name = "q35-next",
+    .name = "pc-q35-1.4",
     .alias = "q35",
-    .desc = "Q35 chipset PC",
+    .desc = "Standard PC (Q35 + ICH9, 2009)",
     .init = pc_q35_init,
     .max_cpus = 255,
 };
commit 7d9f7b51cc62ec23ac72e3338165a2f3007631a2
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jan 8 09:38:19 2013 +0100

    q35: document chipset devices
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/docs/q35-chipset.cfg b/docs/q35-chipset.cfg
new file mode 100644
index 0000000..1b6efc0
--- /dev/null
+++ b/docs/q35-chipset.cfg
@@ -0,0 +1,129 @@
+################################################################
+#
+# qemu -M q35 creates a bare machine with just the very essential
+# chipset devices being present:
+#
+#     00.0 - Host bridge
+#     1f.0 - ISA bridge / LPC
+#     1f.2 - SATA (AHCI) controller
+#     1f.3 - SMBus controller
+#
+# This config file documents the other devices and how they are
+# created.  You can simply use "-readconfig $thisfile" to create
+# them all.  Here is a overview:
+#
+#     19.0 - Ethernet controller (not created, our e1000 emulation
+#                                 doesn't emulate the ich9 device).
+#     1a.* - USB Controller #2 (ehci + uhci companions)
+#     1b.0 - HD Audio Controller
+#     1c.* - PCI Express Ports
+#     1d.* - USB Controller #1 (ehci + uhci companions,
+#                               "qemu -M q35 -usb" creates these too)
+#     1e.0 - PCI Bridge
+#
+
+[device "ich9-ehci-2"]
+  driver = "ich9-usb-ehci2"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1a.7"
+
+[device "ich9-uhci-4"]
+  driver = "ich9-usb-uhci4"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1a.0"
+  masterbus = "ich9-ehci-2.0"
+  firstport = "0"
+
+[device "ich9-uhci-5"]
+  driver = "ich9-usb-uhci5"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1a.1"
+  masterbus = "ich9-ehci-2.0"
+  firstport = "2"
+
+[device "ich9-uhci-6"]
+  driver = "ich9-usb-uhci6"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1a.2"
+  masterbus = "ich9-ehci-2.0"
+  firstport = "4"
+
+
+[device "ich9-hda-audio"]
+  driver = "ich9-intel-hda"
+  bus = "pcie.0"
+  addr = "1b.0"
+
+
+[device "ich9-pcie-port-1"]
+  driver = "ioh3420"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1c.0"
+  port = "1"
+  chassis = "1"
+
+[device "ich9-pcie-port-2"]
+  driver = "ioh3420"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1c.1"
+  port = "2"
+  chassis = "2"
+
+[device "ich9-pcie-port-3"]
+  driver = "ioh3420"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1c.2"
+  port = "3"
+  chassis = "3"
+
+[device "ich9-pcie-port-4"]
+  driver = "ioh3420"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1c.3"
+  port = "4"
+  chassis = "4"
+
+
+[device "ich9-ehci-1"]
+  driver = "ich9-usb-ehci1"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1d.7"
+
+[device "ich9-uhci-1"]
+  driver = "ich9-usb-uhci1"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1d.0"
+  masterbus = "ich9-ehci-1.0"
+  firstport = "0"
+
+[device "ich9-uhci-2"]
+  driver = "ich9-usb-uhci2"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1d.1"
+  masterbus = "ich9-ehci-1.0"
+  firstport = "2"
+
+[device "ich9-uhci-3"]
+  driver = "ich9-usb-uhci3"
+  multifunction = "on"
+  bus = "pcie.0"
+  addr = "1d.2"
+  masterbus = "ich9-ehci-1.0"
+  firstport = "4"
+
+
+[device "ich9-pci-bridge"]
+  driver = "i82801b11-bridge"
+  bus = "pcie.0"
+  addr = "1e.0"
commit 8b07eaa110df41b027ee62cbf3549cc3e48ec147
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Tue Jan 8 09:25:16 2013 +0100

    q35: add ich9 intel hda controller
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 98ff936..eed1d38 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1232,7 +1232,7 @@ static Property intel_hda_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void intel_hda_class_init(ObjectClass *klass, void *data)
+static void intel_hda_class_init_common(ObjectClass *klass)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -1240,20 +1240,46 @@ static void intel_hda_class_init(ObjectClass *klass, void *data)
     k->init = intel_hda_init;
     k->exit = intel_hda_exit;
     k->vendor_id = PCI_VENDOR_ID_INTEL;
-    k->device_id = 0x2668;
-    k->revision = 1;
     k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO;
-    dc->desc = "Intel HD Audio Controller";
     dc->reset = intel_hda_reset;
     dc->vmsd = &vmstate_intel_hda;
     dc->props = intel_hda_properties;
 }
 
-static TypeInfo intel_hda_info = {
+static void intel_hda_class_init_ich6(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    intel_hda_class_init_common(klass);
+    k->device_id = 0x2668;
+    k->revision = 1;
+    dc->desc = "Intel HD Audio Controller (ich6)";
+}
+
+static void intel_hda_class_init_ich9(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    intel_hda_class_init_common(klass);
+    k->device_id = 0x293e;
+    k->revision = 3;
+    dc->desc = "Intel HD Audio Controller (ich9)";
+}
+
+static TypeInfo intel_hda_info_ich6 = {
     .name          = "intel-hda",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(IntelHDAState),
-    .class_init    = intel_hda_class_init,
+    .class_init    = intel_hda_class_init_ich6,
+};
+
+static TypeInfo intel_hda_info_ich9 = {
+    .name          = "ich9-intel-hda",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(IntelHDAState),
+    .class_init    = intel_hda_class_init_ich9,
 };
 
 static void hda_codec_device_class_init(ObjectClass *klass, void *data)
@@ -1277,7 +1303,8 @@ static TypeInfo hda_codec_device_type_info = {
 static void intel_hda_register_types(void)
 {
     type_register_static(&hda_codec_bus_info);
-    type_register_static(&intel_hda_info);
+    type_register_static(&intel_hda_info_ich6);
+    type_register_static(&intel_hda_info_ich9);
     type_register_static(&hda_codec_device_type_info);
 }
 
commit 47a150a4bbb06e45ef439a8222e9f46a7c4cca3f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jan 10 15:49:08 2013 +0100

    virtio-scsi: abort in-flight I/O when the device is reset
    
    When the device is reset, the SCSI bus should also be reset so
    that in-flight I/O is cancelled.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index bfe1860..0715865 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -565,6 +565,10 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
 
+    s->resetting++;
+    qbus_reset_all(&s->bus.qbus);
+    s->resetting--;
+
     s->sense_size = VIRTIO_SCSI_SENSE_SIZE;
     s->cdb_size = VIRTIO_SCSI_CDB_SIZE;
     s->events_dropped = false;
commit d0508c3664290baad379f6513c92cae6e5aac95b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jan 10 15:49:07 2013 +0100

    qdev: add qbus_reset_all
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index fdf14ec..853bd08 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -182,6 +182,18 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
 int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
                        qbus_walkerfn *busfn, void *opaque);
 void qdev_reset_all(DeviceState *dev);
+
+/**
+ * @qbus_reset_all:
+ * @bus: Bus to be reset.
+ *
+ * Reset @bus and perform a bus-level ("hard") reset of all devices connected
+ * to it, including recursive processing of all buses below @bus itself.  A
+ * hard reset means that qbus_reset_all will reset all state of the device.
+ * For PCI devices, for example, this will include the base address registers
+ * or configuration space.
+ */
+void qbus_reset_all(BusState *bus);
 void qbus_reset_all_fn(void *opaque);
 
 void qbus_free(BusState *bus);
diff --git a/hw/qdev.c b/hw/qdev.c
index b027ead..1b68d02 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -228,10 +228,15 @@ void qdev_reset_all(DeviceState *dev)
     qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
 }
 
+void qbus_reset_all(BusState *bus)
+{
+    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
+}
+
 void qbus_reset_all_fn(void *opaque)
 {
     BusState *bus = opaque;
-    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
+    qbus_reset_all(bus);
 }
 
 /* can be used as ->unplug() callback for the simple cases */
commit 8c43a6f05d5ef3c9484bd2be9d4e818d58e62016
Author: Andreas Färber <afaerber at suse.de>
Date:   Thu Jan 10 16:19:07 2013 +0100

    Make all static TypeInfos const
    
    Since 39bffca2030950ef6efe57c2fac8327a45ae1015 (qdev: register all
    types natively through QEMU Object Model), TypeInfo as used in
    the common, non-iterative pattern is no longer amended with information
    and should therefore be const.
    
    Fix the documented QOM examples:
    
     sed -i 's/static TypeInfo/static const TypeInfo/g' include/qom/object.h
    
    Since frequently the wrong examples are being copied by contributors of
    new devices, fix all types in the tree:
    
     sed -i 's/^static TypeInfo/static const TypeInfo/g' */*.c
     sed -i 's/^static TypeInfo/static const TypeInfo/g' */*/*.c
    
    This also avoids to piggy-back these changes onto real functional
    changes or other refactorings.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index fd41b53..5e012e9 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -207,7 +207,7 @@ static void rng_egd_class_init(ObjectClass *klass, void *data)
     rbc->opened = rng_egd_opened;
 }
 
-static TypeInfo rng_egd_info = {
+static const TypeInfo rng_egd_info = {
     .name = TYPE_RNG_EGD,
     .parent = TYPE_RNG_BACKEND,
     .instance_size = sizeof(RngEgd),
diff --git a/backends/rng-random.c b/backends/rng-random.c
index d479ce8..0d11088 100644
--- a/backends/rng-random.c
+++ b/backends/rng-random.c
@@ -144,7 +144,7 @@ static void rng_random_class_init(ObjectClass *klass, void *data)
     rbc->opened = rng_random_opened;
 }
 
-static TypeInfo rng_random_info = {
+static const TypeInfo rng_random_info = {
     .name = TYPE_RNG_RANDOM,
     .parent = TYPE_RNG_BACKEND,
     .instance_size = sizeof(RndRandom),
diff --git a/backends/rng.c b/backends/rng.c
index 48a5840..3d33898 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -76,7 +76,7 @@ static void rng_backend_init(Object *obj)
                              NULL);
 }
 
-static TypeInfo rng_backend_info = {
+static const TypeInfo rng_backend_info = {
     .name = TYPE_RNG_BACKEND,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(RngBackend),
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 6761bce..2a7c2a3 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -177,7 +177,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
     dc->reset = virtio_pci_reset;
 }
 
-static TypeInfo virtio_9p_info = {
+static const TypeInfo virtio_9p_info = {
     .name          = "virtio-9p-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index fc0a02a..30983ef 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -93,7 +93,7 @@ static void a15mp_priv_class_init(ObjectClass *klass, void *data)
     /* We currently have no savable state */
 }
 
-static TypeInfo a15mp_priv_info = {
+static const TypeInfo a15mp_priv_info = {
     .name  = "a15mpcore_priv",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(A15MPPrivState),
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index f802de0..184734f 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -226,7 +226,7 @@ static void a9mp_priv_class_init(ObjectClass *klass, void *data)
     dc->reset = a9mp_priv_reset;
 }
 
-static TypeInfo a9mp_priv_info = {
+static const TypeInfo a9mp_priv_info = {
     .name          = "a9mpcore_priv",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(a9mp_priv_state),
diff --git a/hw/ac97.c b/hw/ac97.c
index 5cd19c1..6c565e7 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1423,7 +1423,7 @@ static void ac97_class_init (ObjectClass *klass, void *data)
     dc->props = ac97_properties;
 }
 
-static TypeInfo ac97_info = {
+static const TypeInfo ac97_info = {
     .name          = "AC97",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof (AC97LinkState),
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 06a8aca..2f84b4e 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -487,7 +487,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
     dc->props = piix4_pm_properties;
 }
 
-static TypeInfo piix4_pm_info = {
+static const TypeInfo piix4_pm_info = {
     .name          = "PIIX4_PM",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PIIX4PMState),
diff --git a/hw/ads7846.c b/hw/ads7846.c
index fa137e6..29e5585 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -162,7 +162,7 @@ static void ads7846_class_init(ObjectClass *klass, void *data)
     k->transfer = ads7846_transfer;
 }
 
-static TypeInfo ads7846_info = {
+static const TypeInfo ads7846_info = {
     .name          = "ads7846",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(ADS7846State),
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index c22e2b0..b9a7ee6 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -486,7 +486,7 @@ static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_BRIDGE_HOST;
 }
 
-static TypeInfo pbm_pci_host_info = {
+static const TypeInfo pbm_pci_host_info = {
     .name          = "pbm-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -502,7 +502,7 @@ static void pbm_host_class_init(ObjectClass *klass, void *data)
     dc->reset = pci_pbm_reset;
 }
 
-static TypeInfo pbm_host_info = {
+static const TypeInfo pbm_host_info = {
     .name          = "pbm",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(APBState),
@@ -525,7 +525,7 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pci_device;
 }
 
-static TypeInfo pbm_pci_bridge_info = {
+static const TypeInfo pbm_pci_bridge_info = {
     .name          = "pbm-bridge",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIBridge),
diff --git a/hw/apic.c b/hw/apic.c
index 81b82f6..fd14b73 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -895,7 +895,7 @@ static void apic_class_init(ObjectClass *klass, void *data)
     k->post_load = apic_post_load;
 }
 
-static TypeInfo apic_info = {
+static const TypeInfo apic_info = {
     .name          = "apic",
     .instance_size = sizeof(APICCommonState),
     .parent        = TYPE_APIC_COMMON,
diff --git a/hw/apic_common.c b/hw/apic_common.c
index 0658be9..6e1b1e0 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -385,7 +385,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
     sc->init = apic_init_common;
 }
 
-static TypeInfo apic_common_type = {
+static const TypeInfo apic_common_type = {
     .name = TYPE_APIC_COMMON,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(APICCommonState),
diff --git a/hw/applesmc.c b/hw/applesmc.c
index c564b60..5a8c4ff 100644
--- a/hw/applesmc.c
+++ b/hw/applesmc.c
@@ -236,7 +236,7 @@ static void qdev_applesmc_class_init(ObjectClass *klass, void *data)
     dc->props = applesmc_isa_properties;
 }
 
-static TypeInfo applesmc_isa_info = {
+static const TypeInfo applesmc_isa_info = {
     .name          = "isa-applesmc",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(struct AppleSMCStatus),
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 0933311..469f6bf 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -222,7 +222,7 @@ static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
     dc->props = mpcore_rirq_properties;
 }
 
-static TypeInfo mpcore_rirq_info = {
+static const TypeInfo mpcore_rirq_info = {
     .name          = "realview_mpcore",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mpcore_rirq_state),
@@ -252,7 +252,7 @@ static void mpcore_priv_class_init(ObjectClass *klass, void *data)
     dc->props = mpcore_priv_properties;
 }
 
-static TypeInfo mpcore_priv_info = {
+static const TypeInfo mpcore_priv_info = {
     .name          = "arm11mpcore_priv",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mpcore_priv_state),
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index b6062c4..466dbf7 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -703,7 +703,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo arm_gic_info = {
+static const TypeInfo arm_gic_info = {
     .name = TYPE_ARM_GIC,
     .parent = TYPE_ARM_GIC_COMMON,
     .instance_size = sizeof(GICState),
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 73ae331..41799ad 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -171,7 +171,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
     sc->init = arm_gic_common_init;
 }
 
-static TypeInfo arm_gic_common_type = {
+static const TypeInfo arm_gic_common_type = {
     .name = TYPE_ARM_GIC_COMMON,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GICState),
diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c
index 6abf0ee..ae1e51d 100644
--- a/hw/arm_l2x0.c
+++ b/hw/arm_l2x0.c
@@ -179,7 +179,7 @@ static void l2x0_class_init(ObjectClass *klass, void *data)
     dc->reset = l2x0_priv_reset;
 }
 
-static TypeInfo l2x0_info = {
+static const TypeInfo l2x0_info = {
     .name = "l2x0",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(l2x0_state),
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index 1febaeb..0cd3853 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -329,7 +329,7 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data)
     dc->props = arm_mptimer_properties;
 }
 
-static TypeInfo arm_mptimer_info = {
+static const TypeInfo arm_mptimer_info = {
     .name          = "arm_mptimer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(arm_mptimer_state),
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index b733617..a196fcc 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -410,7 +410,7 @@ static void arm_sysctl_class_init(ObjectClass *klass, void *data)
     dc->props = arm_sysctl_properties;
 }
 
-static TypeInfo arm_sysctl_info = {
+static const TypeInfo arm_sysctl_info = {
     .name          = "realview_sysctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(arm_sysctl_state),
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 37e28e9..c1e56be 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -361,7 +361,7 @@ static void icp_pit_class_init(ObjectClass *klass, void *data)
     sdc->init = icp_pit_init;
 }
 
-static TypeInfo icp_pit_info = {
+static const TypeInfo icp_pit_info = {
     .name          = "integrator_pit",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(icp_pit_state),
@@ -383,7 +383,7 @@ static void sp804_class_init(ObjectClass *klass, void *data)
     k->props = sp804_properties;
 }
 
-static TypeInfo sp804_info = {
+static const TypeInfo sp804_info = {
     .name          = "sp804",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(sp804_state),
diff --git a/hw/armv7m.c b/hw/armv7m.c
index ce2ec9b..98fe483 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -269,7 +269,7 @@ static void bitband_class_init(ObjectClass *klass, void *data)
     dc->props = bitband_properties;
 }
 
-static TypeInfo bitband_info = {
+static const TypeInfo bitband_info = {
     .name          = "ARM,bitband-memory",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(BitBandState),
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index 0907e42..d5798d0 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -535,7 +535,7 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
     dc->reset = armv7m_nvic_reset;
 }
 
-static TypeInfo armv7m_nvic_info = {
+static const TypeInfo armv7m_nvic_info = {
     .name          = TYPE_NVIC,
     .parent        = TYPE_ARM_GIC_COMMON,
     .instance_init = armv7m_nvic_instance_init,
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 44ed7f4..114508f 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -230,7 +230,7 @@ static void gpio_i2c_class_init(ObjectClass *klass, void *data)
     dc->desc = "Virtual GPIO to I2C bridge";
 }
 
-static TypeInfo gpio_i2c_info = {
+static const TypeInfo gpio_i2c_info = {
     .name          = "gpio_i2c",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GPIOI2CState),
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index 40a2399..2beee62 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -1218,7 +1218,7 @@ static void gem_class_init(ObjectClass *klass, void *data)
     dc->reset = gem_reset;
 }
 
-static TypeInfo gem_info = {
+static const TypeInfo gem_info = {
     .class_init = gem_class_init,
     .name  = "cadence_gem",
     .parent = TYPE_SYS_BUS_DEVICE,
diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c
index 9e1cb1f..2a8fadd 100644
--- a/hw/cadence_ttc.c
+++ b/hw/cadence_ttc.c
@@ -474,7 +474,7 @@ static void cadence_ttc_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_cadence_ttc;
 }
 
-static TypeInfo cadence_ttc_info = {
+static const TypeInfo cadence_ttc_info = {
     .name  = "cadence_ttc",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(CadenceTTCState),
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
index 7dd2fe5..cf2f53c 100644
--- a/hw/cadence_uart.c
+++ b/hw/cadence_uart.c
@@ -501,7 +501,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_cadence_uart;
 }
 
-static TypeInfo cadence_uart_info = {
+static const TypeInfo cadence_uart_info = {
     .name          = "cadence_uart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(UartState),
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
index 6fd4469..c8f8ba3 100644
--- a/hw/ccid-card-emulated.c
+++ b/hw/ccid-card-emulated.c
@@ -587,7 +587,7 @@ static void emulated_class_initfn(ObjectClass *klass, void *data)
     dc->props = emulated_card_properties;
 }
 
-static TypeInfo emulated_card_info = {
+static const TypeInfo emulated_card_info = {
     .name          = EMULATED_DEV_NAME,
     .parent        = TYPE_CCID_CARD,
     .instance_size = sizeof(EmulatedState),
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
index 4be0547..984bd0b 100644
--- a/hw/ccid-card-passthru.c
+++ b/hw/ccid-card-passthru.c
@@ -336,7 +336,7 @@ static void passthru_class_initfn(ObjectClass *klass, void *data)
     dc->props = passthru_card_properties;
 }
 
-static TypeInfo passthru_card_info = {
+static const TypeInfo passthru_card_info = {
     .name          = PASSTHRU_DEV_NAME,
     .parent        = TYPE_CCID_CARD,
     .instance_size = sizeof(PassthruState),
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 80510bc..2a2c8da 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2933,7 +2933,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data)
     dc->props = isa_vga_cirrus_properties;
 }
 
-static TypeInfo isa_cirrus_vga_info = {
+static const TypeInfo isa_cirrus_vga_info = {
     .name          = "isa-cirrus-vga",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISACirrusVGAState),
@@ -3003,7 +3003,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data)
     dc->props = pci_vga_cirrus_properties;
 }
 
-static TypeInfo cirrus_vga_info = {
+static const TypeInfo cirrus_vga_info = {
     .name          = "cirrus-vga",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCICirrusVGAState),
diff --git a/hw/cs4231.c b/hw/cs4231.c
index 23570d5..ae384b9 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -166,7 +166,7 @@ static void cs4231_class_init(ObjectClass *klass, void *data)
     dc->props = cs4231_properties;
 }
 
-static TypeInfo cs4231_info = {
+static const TypeInfo cs4231_info = {
     .name          = "SUNW,CS4231",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(CSState),
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 9d528c4..73f0859 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -682,7 +682,7 @@ static void cs4231a_class_initfn (ObjectClass *klass, void *data)
     dc->props = cs4231a_properties;
 }
 
-static TypeInfo cs4231a_info = {
+static const TypeInfo cs4231a_info = {
     .name          = "cs4231a",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof (CSState),
diff --git a/hw/debugcon.c b/hw/debugcon.c
index e8a855e..81b2bb0 100644
--- a/hw/debugcon.c
+++ b/hw/debugcon.c
@@ -119,7 +119,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data)
     dc->props = debugcon_isa_properties;
 }
 
-static TypeInfo debugcon_isa_info = {
+static const TypeInfo debugcon_isa_info = {
     .name          = TYPE_ISA_DEBUGCON_DEVICE,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISADebugconState),
diff --git a/hw/debugexit.c b/hw/debugexit.c
index 90642eb..c1b489d 100644
--- a/hw/debugexit.c
+++ b/hw/debugexit.c
@@ -60,7 +60,7 @@ static void debug_exit_class_initfn(ObjectClass *klass, void *data)
     dc->props = debug_exit_properties;
 }
 
-static TypeInfo debug_exit_info = {
+static const TypeInfo debug_exit_info = {
     .name          = TYPE_ISA_DEBUG_EXIT_DEVICE,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISADebugExitState),
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 4b3f69b..a6219a7 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -150,7 +150,7 @@ static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
     dc->props = nvram_sysbus_properties;
 }
 
-static TypeInfo nvram_sysbus_info = {
+static const TypeInfo nvram_sysbus_info = {
     .name          = "ds1225y",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusNvRamState),
diff --git a/hw/ds1338.c b/hw/ds1338.c
index 1aefa3b..3792206 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -221,7 +221,7 @@ static void ds1338_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_ds1338;
 }
 
-static TypeInfo ds1338_info = {
+static const TypeInfo ds1338_info = {
     .name          = "ds1338",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(DS1338State),
diff --git a/hw/e1000.c b/hw/e1000.c
index 0f177ff..ef06ca1 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1327,7 +1327,7 @@ static void e1000_class_init(ObjectClass *klass, void *data)
     dc->props = e1000_properties;
 }
 
-static TypeInfo e1000_info = {
+static const TypeInfo e1000_info = {
     .name          = "e1000",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(E1000State),
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index 000bd08..dbac2c2 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -324,7 +324,7 @@ static void ecc_class_init(ObjectClass *klass, void *data)
     dc->props = ecc_properties;
 }
 
-static TypeInfo ecc_info = {
+static const TypeInfo ecc_info = {
     .name          = "eccmemctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ECCState),
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 23978eb..3cb6ccb 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -83,7 +83,7 @@ static void empty_slot_class_init(ObjectClass *klass, void *data)
     k->init = empty_slot_init1;
 }
 
-static TypeInfo empty_slot_info = {
+static const TypeInfo empty_slot_info = {
     .name          = "empty_slot",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(EmptySlot),
diff --git a/hw/es1370.c b/hw/es1370.c
index 59c3f23..977d2e3 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -1073,7 +1073,7 @@ static void es1370_class_init (ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_es1370;
 }
 
-static TypeInfo es1370_info = {
+static const TypeInfo es1370_info = {
     .name          = "ES1370",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof (ES1370State),
diff --git a/hw/escc.c b/hw/escc.c
index f09904a..c81088b 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -923,7 +923,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
     dc->props = escc_properties;
 }
 
-static TypeInfo escc_info = {
+static const TypeInfo escc_info = {
     .name          = "escc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SerialState),
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 289a810..ec23fa6 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -630,7 +630,7 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data)
     dc->props = etraxfs_eth_properties;
 }
 
-static TypeInfo etraxfs_eth_info = {
+static const TypeInfo etraxfs_eth_info = {
     .name          = "etraxfs-eth",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct fs_eth),
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 62a62a3..64af31c 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -165,7 +165,7 @@ static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
     dc->props = etraxfs_pic_properties;
 }
 
-static TypeInfo etraxfs_pic_info = {
+static const TypeInfo etraxfs_pic_info = {
     .name          = "etraxfs,pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct etrax_pic),
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 7bde800..72c8868 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -233,7 +233,7 @@ static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
     dc->reset = etraxfs_ser_reset;
 }
 
-static TypeInfo etraxfs_ser_info = {
+static const TypeInfo etraxfs_ser_info = {
     .name          = "etraxfs,serial",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct etrax_serial),
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index e9273cd..d3dac52 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -336,7 +336,7 @@ static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
     sdc->init = etraxfs_timer_init;
 }
 
-static TypeInfo etraxfs_timer_info = {
+static const TypeInfo etraxfs_timer_info = {
     .name          = "etraxfs,timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof (struct etrax_timer),
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index 84d36ed..ba644b4 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -440,7 +440,7 @@ static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_exynos4210_combiner;
 }
 
-static TypeInfo exynos4210_combiner_info = {
+static const TypeInfo exynos4210_combiner_info = {
     .name          = "exynos4210.combiner",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210CombinerState),
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 5c29b5d..3d498b7 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1913,7 +1913,7 @@ static void exynos4210_fimd_class_init(ObjectClass *klass, void *data)
     k->init = exynos4210_fimd_init;
 }
 
-static TypeInfo exynos4210_fimd_info = {
+static const TypeInfo exynos4210_fimd_info = {
     .name = "exynos4210.fimd",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210fimdState),
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 959de56..f67906e 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -346,7 +346,7 @@ static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
     dc->props = exynos4210_gic_properties;
 }
 
-static TypeInfo exynos4210_gic_info = {
+static const TypeInfo exynos4210_gic_info = {
     .name          = "exynos4210.gic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210GicState),
@@ -447,7 +447,7 @@ static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
     dc->props = exynos4210_irq_gate_properties;
 }
 
-static TypeInfo exynos4210_irq_gate_info = {
+static const TypeInfo exynos4210_irq_gate_info = {
     .name          = "exynos4210.irq_gate",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210IRQGateState),
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index 41cd142..d7d5904 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -1467,7 +1467,7 @@ static void exynos4210_mct_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_exynos4210_mct_state;
 }
 
-static TypeInfo exynos4210_mct_info = {
+static const TypeInfo exynos4210_mct_info = {
     .name          = "exynos4210.mct",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210MCTState),
diff --git a/hw/exynos4210_pmu.c b/hw/exynos4210_pmu.c
index a22b8f1..7c81a1b 100644
--- a/hw/exynos4210_pmu.c
+++ b/hw/exynos4210_pmu.c
@@ -484,7 +484,7 @@ static void exynos4210_pmu_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &exynos4210_pmu_vmstate;
 }
 
-static TypeInfo exynos4210_pmu_info = {
+static const TypeInfo exynos4210_pmu_info = {
     .name          = "exynos4210.pmu",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210PmuState),
diff --git a/hw/exynos4210_pwm.c b/hw/exynos4210_pwm.c
index 3a3eb8c..c865624 100644
--- a/hw/exynos4210_pwm.c
+++ b/hw/exynos4210_pwm.c
@@ -407,7 +407,7 @@ static void exynos4210_pwm_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_exynos4210_pwm_state;
 }
 
-static TypeInfo exynos4210_pwm_info = {
+static const TypeInfo exynos4210_pwm_info = {
     .name          = "exynos4210.pwm",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210PWMState),
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index 4f23079..adaab24 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -661,7 +661,7 @@ static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_exynos4210_uart;
 }
 
-static TypeInfo exynos4210_uart_info = {
+static const TypeInfo exynos4210_uart_info = {
     .name          = "exynos4210.uart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Exynos4210UartState),
diff --git a/hw/fdc.c b/hw/fdc.c
index ddc0cc3..976a587 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -2210,7 +2210,7 @@ static void isabus_fdc_class_init1(ObjectClass *klass, void *data)
     dc->props = isa_fdc_properties;
 }
 
-static TypeInfo isa_fdc_info = {
+static const TypeInfo isa_fdc_info = {
     .name          = "isa-fdc",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(FDCtrlISABus),
@@ -2244,7 +2244,7 @@ static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
     dc->props = sysbus_fdc_properties;
 }
 
-static TypeInfo sysbus_fdc_info = {
+static const TypeInfo sysbus_fdc_info = {
     .name          = "sysbus-fdc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FDCtrlSysBus),
@@ -2267,7 +2267,7 @@ static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
     dc->props = sun4m_fdc_properties;
 }
 
-static TypeInfo sun4m_fdc_info = {
+static const TypeInfo sun4m_fdc_info = {
     .name          = "SUNW,fdtwo",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FDCtrlSysBus),
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 26f7125..7c9480c 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -575,7 +575,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data)
     dc->props = fw_cfg_properties;
 }
 
-static TypeInfo fw_cfg_info = {
+static const TypeInfo fw_cfg_info = {
     .name          = "fw_cfg",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(FWCfgState),
diff --git a/hw/g364fb.c b/hw/g364fb.c
index b46a044..0c0c8ba 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -597,7 +597,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
     dc->props = g364fb_sysbus_properties;
 }
 
-static TypeInfo g364fb_sysbus_info = {
+static const TypeInfo g364fb_sysbus_info = {
     .name          = "sysbus-g364",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(G364SysBusState),
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
index 88c4678..760bed0 100644
--- a/hw/grlib_apbuart.c
+++ b/hw/grlib_apbuart.c
@@ -256,7 +256,7 @@ static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
     dc->props = grlib_gptimer_properties;
 }
 
-static TypeInfo grlib_gptimer_info = {
+static const TypeInfo grlib_gptimer_info = {
     .name          = "grlib,apbuart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(UART),
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
index 252ba89..7962b74 100644
--- a/hw/grlib_gptimer.c
+++ b/hw/grlib_gptimer.c
@@ -389,7 +389,7 @@ static void grlib_gptimer_class_init(ObjectClass *klass, void *data)
     dc->props = grlib_gptimer_properties;
 }
 
-static TypeInfo grlib_gptimer_info = {
+static const TypeInfo grlib_gptimer_info = {
     .name          = "grlib,gptimer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GPTimerUnit),
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index 23a6a02..b5427c8 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -370,7 +370,7 @@ static void grlib_irqmp_class_init(ObjectClass *klass, void *data)
     dc->props = grlib_irqmp_properties;
 }
 
-static TypeInfo grlib_irqmp_info = {
+static const TypeInfo grlib_irqmp_info = {
     .name          = "grlib,irqmp",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IRQMP),
diff --git a/hw/gus.c b/hw/gus.c
index 840d098..aa13fcc 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -317,7 +317,7 @@ static void gus_class_initfn (ObjectClass *klass, void *data)
     dc->props = gus_properties;
 }
 
-static TypeInfo gus_info = {
+static const TypeInfo gus_info = {
     .name          = "gus",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof (GUSState),
diff --git a/hw/hda-audio.c b/hw/hda-audio.c
index 92a91b5..3190bd1 100644
--- a/hw/hda-audio.c
+++ b/hw/hda-audio.c
@@ -1039,7 +1039,7 @@ static void hda_audio_output_class_init(ObjectClass *klass, void *data)
     dc->props = hda_audio_properties;
 }
 
-static TypeInfo hda_audio_output_info = {
+static const TypeInfo hda_audio_output_info = {
     .name          = "hda-output",
     .parent        = TYPE_HDA_CODEC_DEVICE,
     .instance_size = sizeof(HDAAudioState),
@@ -1060,7 +1060,7 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data)
     dc->props = hda_audio_properties;
 }
 
-static TypeInfo hda_audio_duplex_info = {
+static const TypeInfo hda_audio_duplex_info = {
     .name          = "hda-duplex",
     .parent        = TYPE_HDA_CODEC_DEVICE,
     .instance_size = sizeof(HDAAudioState),
@@ -1081,7 +1081,7 @@ static void hda_audio_micro_class_init(ObjectClass *klass, void *data)
     dc->props = hda_audio_properties;
 }
 
-static TypeInfo hda_audio_micro_info = {
+static const TypeInfo hda_audio_micro_info = {
     .name          = "hda-micro",
     .parent        = TYPE_HDA_CODEC_DEVICE,
     .instance_size = sizeof(HDAAudioState),
diff --git a/hw/highbank.c b/hw/highbank.c
index 6005622..98deca8 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -168,7 +168,7 @@ static void highbank_regs_class_init(ObjectClass *klass, void *data)
     dc->reset = highbank_regs_reset;
 }
 
-static TypeInfo highbank_regs_info = {
+static const TypeInfo highbank_regs_info = {
     .name          = "highbank-regs",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(HighbankRegsState),
diff --git a/hw/hpet.c b/hw/hpet.c
index 78c0662..6efae55 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -745,7 +745,7 @@ static void hpet_device_class_init(ObjectClass *klass, void *data)
     dc->props = hpet_device_properties;
 }
 
-static TypeInfo hpet_device_info = {
+static const TypeInfo hpet_device_info = {
     .name          = "hpet",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(HPETState),
diff --git a/hw/i2c.c b/hw/i2c.c
index 296bece..119e96b 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -228,7 +228,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data)
     k->props = i2c_props;
 }
 
-static TypeInfo i2c_slave_type_info = {
+static const TypeInfo i2c_slave_type_info = {
     .name = TYPE_I2C_SLAVE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(I2CSlave),
diff --git a/hw/i82374.c b/hw/i82374.c
index 4a922c3..6a62ba2 100644
--- a/hw/i82374.c
+++ b/hw/i82374.c
@@ -153,7 +153,7 @@ static void i82374_class_init(ObjectClass *klass, void *data)
     dc->props = i82374_properties;
 }
 
-static TypeInfo i82374_isa_info = {
+static const TypeInfo i82374_isa_info = {
     .name  = "i82374",
     .parent = TYPE_ISA_DEVICE,
     .instance_size  = sizeof(ISAi82374State),
diff --git a/hw/i82378.c b/hw/i82378.c
index c6b0b5e..0914d7b 100644
--- a/hw/i82378.c
+++ b/hw/i82378.c
@@ -262,7 +262,7 @@ static void pci_i82378_class_init(ObjectClass *klass, void *data)
     dc->props = i82378_properties;
 }
 
-static TypeInfo pci_i82378_info = {
+static const TypeInfo pci_i82378_info = {
     .name = "i82378",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIi82378State),
diff --git a/hw/i8254.c b/hw/i8254.c
index 7c2aa62..394b2e8 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -347,7 +347,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
     dc->props = pit_properties;
 }
 
-static TypeInfo pit_info = {
+static const TypeInfo pit_info = {
     .name          = "isa-pit",
     .parent        = TYPE_PIT_COMMON,
     .instance_size = sizeof(PITCommonState),
diff --git a/hw/i8254_common.c b/hw/i8254_common.c
index 08ab8d1..8c2e45a 100644
--- a/hw/i8254_common.c
+++ b/hw/i8254_common.c
@@ -294,7 +294,7 @@ static void pit_common_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo pit_common_type = {
+static const TypeInfo pit_common_type = {
     .name          = TYPE_PIT_COMMON,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(PITCommonState),
diff --git a/hw/i8259.c b/hw/i8259.c
index 8fc6339..264879e 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -481,7 +481,7 @@ static void i8259_class_init(ObjectClass *klass, void *data)
     dc->reset = pic_reset;
 }
 
-static TypeInfo i8259_info = {
+static const TypeInfo i8259_info = {
     .name       = "isa-i8259",
     .instance_size = sizeof(PICCommonState),
     .parent     = TYPE_PIC_COMMON,
diff --git a/hw/i8259_common.c b/hw/i8259_common.c
index ab3d98b..fc91056 100644
--- a/hw/i8259_common.c
+++ b/hw/i8259_common.c
@@ -144,7 +144,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data)
     ic->init = pic_init_common;
 }
 
-static TypeInfo pic_common_type = {
+static const TypeInfo pic_common_type = {
     .name = TYPE_PIC_COMMON,
     .parent = TYPE_ISA_DEVICE,
     .instance_size = sizeof(PICCommonState),
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index d072449..21f50ea 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1247,7 +1247,7 @@ static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
     dc->reset = sysbus_ahci_reset;
 }
 
-static TypeInfo sysbus_ahci_info = {
+static const TypeInfo sysbus_ahci_info = {
     .name          = "sysbus-ahci",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysbusAHCIState),
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index ee855b6..745ef94 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -342,7 +342,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data)
     dc->props = cmd646_ide_properties;
 }
 
-static TypeInfo cmd646_ide_info = {
+static const TypeInfo cmd646_ide_info = {
     .name          = "cmd646-ide",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIIDEState),
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index de39b30..1fb803d 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -156,7 +156,7 @@ static void ich_ahci_class_init(ObjectClass *klass, void *data)
     dc->reset = pci_ich9_reset;
 }
 
-static TypeInfo ich_ahci_info = {
+static const TypeInfo ich_ahci_info = {
     .name          = "ich9-ahci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(AHCIPCIState),
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index aa0e7fa..fb7bb82 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -111,7 +111,7 @@ static void isa_ide_class_initfn(ObjectClass *klass, void *data)
     dc->props = isa_ide_properties;
 }
 
-static TypeInfo isa_ide_info = {
+static const TypeInfo isa_ide_info = {
     .name          = "isa-ide",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAIDEState),
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index df95aec..4d3e822 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -251,7 +251,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo piix3_ide_info = {
+static const TypeInfo piix3_ide_info = {
     .name          = "piix3-ide",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIIDEState),
@@ -271,7 +271,7 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
     dc->unplug = pci_piix3_xen_ide_unplug;
 }
 
-static TypeInfo piix3_ide_xen_info = {
+static const TypeInfo piix3_ide_xen_info = {
     .name          = "piix3-ide-xen",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIIDEState),
@@ -292,7 +292,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo piix4_ide_info = {
+static const TypeInfo piix4_ide_info = {
     .name          = "piix4-ide",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIIDEState),
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index d2fe773..c436b38 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -216,7 +216,7 @@ static void ide_hd_class_init(ObjectClass *klass, void *data)
     dc->props = ide_hd_properties;
 }
 
-static TypeInfo ide_hd_info = {
+static const TypeInfo ide_hd_info = {
     .name          = "ide-hd",
     .parent        = TYPE_IDE_DEVICE,
     .instance_size = sizeof(IDEDrive),
@@ -238,7 +238,7 @@ static void ide_cd_class_init(ObjectClass *klass, void *data)
     dc->props = ide_cd_properties;
 }
 
-static TypeInfo ide_cd_info = {
+static const TypeInfo ide_cd_info = {
     .name          = "ide-cd",
     .parent        = TYPE_IDE_DEVICE,
     .instance_size = sizeof(IDEDrive),
@@ -260,7 +260,7 @@ static void ide_drive_class_init(ObjectClass *klass, void *data)
     dc->props = ide_drive_properties;
 }
 
-static TypeInfo ide_drive_info = {
+static const TypeInfo ide_drive_info = {
     .name          = "ide-drive",
     .parent        = TYPE_IDE_DEVICE,
     .instance_size = sizeof(IDEDrive),
@@ -275,7 +275,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
     k->props = ide_props;
 }
 
-static TypeInfo ide_device_type_info = {
+static const TypeInfo ide_device_type_info = {
     .name = TYPE_IDE_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(IDEDevice),
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 14acb3a..f40c1ad 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -226,7 +226,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo via_ide_info = {
+static const TypeInfo via_ide_info = {
     .name          = "via-ide",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIIDEState),
diff --git a/hw/imx_ccm.c b/hw/imx_ccm.c
index 46962e4..477903a 100644
--- a/hw/imx_ccm.c
+++ b/hw/imx_ccm.c
@@ -306,7 +306,7 @@ static void imx_ccm_class_init(ObjectClass *klass, void *data)
     dc->desc = "i.MX Clock Control Module";
 }
 
-static TypeInfo imx_ccm_info = {
+static const TypeInfo imx_ccm_info = {
     .name = "imx_ccm",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IMXCCMState),
diff --git a/hw/imx_serial.c b/hw/imx_serial.c
index 124dbb2..77ed693 100644
--- a/hw/imx_serial.c
+++ b/hw/imx_serial.c
@@ -452,7 +452,7 @@ static void imx_serial_class_init(ObjectClass *klass, void *data)
     dc->props = imx32_serial_properties;
 }
 
-static TypeInfo imx_serial_info = {
+static const TypeInfo imx_serial_info = {
     .name = "imx-serial",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IMXSerialState),
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 47fc9cb..6c824dc 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -535,7 +535,7 @@ static void core_class_init(ObjectClass *klass, void *data)
     dc->props = core_properties;
 }
 
-static TypeInfo core_info = {
+static const TypeInfo core_info = {
     .name          = "integrator_core",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(integratorcm_state),
@@ -549,7 +549,7 @@ static void icp_pic_class_init(ObjectClass *klass, void *data)
     sdc->init = icp_pic_init;
 }
 
-static TypeInfo icp_pic_info = {
+static const TypeInfo icp_pic_info = {
     .name          = "integrator_pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(icp_pic_state),
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index 98ff936..0a533df 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1249,7 +1249,7 @@ static void intel_hda_class_init(ObjectClass *klass, void *data)
     dc->props = intel_hda_properties;
 }
 
-static TypeInfo intel_hda_info = {
+static const TypeInfo intel_hda_info = {
     .name          = "intel-hda",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(IntelHDAState),
@@ -1265,7 +1265,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data)
     k->props = hda_props;
 }
 
-static TypeInfo hda_codec_device_type_info = {
+static const TypeInfo hda_codec_device_type_info = {
     .name = TYPE_HDA_CODEC_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(HDACodecDevice),
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 7273095..f06c2dc 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -244,7 +244,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
     dc->reset = ioapic_reset_common;
 }
 
-static TypeInfo ioapic_info = {
+static const TypeInfo ioapic_info = {
     .name          = "ioapic",
     .parent        = TYPE_IOAPIC_COMMON,
     .instance_size = sizeof(IOAPICCommonState),
diff --git a/hw/ioapic_common.c b/hw/ioapic_common.c
index 653eef2..7dc552f 100644
--- a/hw/ioapic_common.c
+++ b/hw/ioapic_common.c
@@ -103,7 +103,7 @@ static void ioapic_common_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo ioapic_common_type = {
+static const TypeInfo ioapic_common_type = {
     .name = TYPE_IOAPIC_COMMON,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IOAPICCommonState),
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index d706e19..95bceb5 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -226,7 +226,7 @@ static void ioh3420_class_init(ObjectClass *klass, void *data)
     dc->props = ioh3420_properties;
 }
 
-static TypeInfo ioh3420_info = {
+static const TypeInfo ioh3420_info = {
     .name          = "ioh3420",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIESlot),
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 86b0bbd..fce311b 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -215,7 +215,7 @@ static void isabus_bridge_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo isabus_bridge_info = {
+static const TypeInfo isabus_bridge_info = {
     .name          = "isabus-bridge",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusDevice),
@@ -229,7 +229,7 @@ static void isa_device_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_ISA_BUS;
 }
 
-static TypeInfo isa_device_type_info = {
+static const TypeInfo isa_device_type_info = {
     .name = TYPE_ISA_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(ISADevice),
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index fcf5d05..3adcc98 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -807,7 +807,7 @@ static void ivshmem_class_init(ObjectClass *klass, void *data)
     dc->props = ivshmem_properties;
 }
 
-static TypeInfo ivshmem_info = {
+static const TypeInfo ivshmem_info = {
     .name          = "ivshmem",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(IVShmemState),
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index f4a0406..4822c48 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -277,7 +277,7 @@ static void jazz_led_class_init(ObjectClass *klass, void *data)
     dc->reset = jazz_led_reset;
 }
 
-static TypeInfo jazz_led_info = {
+static const TypeInfo jazz_led_info = {
     .name          = "jazz-led",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LedState),
diff --git a/hw/kvm/apic.c b/hw/kvm/apic.c
index a4e8347..d994ea7 100644
--- a/hw/kvm/apic.c
+++ b/hw/kvm/apic.c
@@ -194,7 +194,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data)
     k->external_nmi = kvm_apic_external_nmi;
 }
 
-static TypeInfo kvm_apic_info = {
+static const TypeInfo kvm_apic_info = {
     .name = "kvm-apic",
     .parent = TYPE_APIC_COMMON,
     .instance_size = sizeof(APICCommonState),
diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c
index be24973..fa40e28 100644
--- a/hw/kvm/clock.c
+++ b/hw/kvm/clock.c
@@ -118,7 +118,7 @@ static void kvmclock_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &kvmclock_vmsd;
 }
 
-static TypeInfo kvmclock_info = {
+static const TypeInfo kvmclock_info = {
     .name          = "kvmclock",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(KVMClockState),
diff --git a/hw/kvm/i8254.c b/hw/kvm/i8254.c
index 57faf64..04ad649 100644
--- a/hw/kvm/i8254.c
+++ b/hw/kvm/i8254.c
@@ -302,7 +302,7 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
     dc->props = kvm_pit_properties;
 }
 
-static TypeInfo kvm_pit_info = {
+static const TypeInfo kvm_pit_info = {
     .name          = "kvm-pit",
     .parent        = TYPE_PIT_COMMON,
     .instance_size = sizeof(KVMPITState),
diff --git a/hw/kvm/i8259.c b/hw/kvm/i8259.c
index 70e1d18..5ae8b68 100644
--- a/hw/kvm/i8259.c
+++ b/hw/kvm/i8259.c
@@ -123,7 +123,7 @@ static void kvm_i8259_class_init(ObjectClass *klass, void *data)
     k->post_load  = kvm_pic_put;
 }
 
-static TypeInfo kvm_i8259_info = {
+static const TypeInfo kvm_i8259_info = {
     .name  = "kvm-i8259",
     .parent = TYPE_PIC_COMMON,
     .instance_size = sizeof(PICCommonState),
diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c
index 30db623..23877d4 100644
--- a/hw/kvm/ioapic.c
+++ b/hw/kvm/ioapic.c
@@ -150,7 +150,7 @@ static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
     dc->props    = kvm_ioapic_properties;
 }
 
-static TypeInfo kvm_ioapic_info = {
+static const TypeInfo kvm_ioapic_info = {
     .name  = "kvm-ioapic",
     .parent = TYPE_IOAPIC_COMMON,
     .instance_size = sizeof(KVMIOAPICState),
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index 81f4bcf..1b5f416 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -804,7 +804,7 @@ static void vapic_class_init(ObjectClass *klass, void *data)
     sc->init    = vapic_init;
 }
 
-static TypeInfo vapic_type = {
+static const TypeInfo vapic_type = {
     .name          = "kvmvapic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(VAPICROMState),
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 5adf911..969b634 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -1368,7 +1368,7 @@ static void lan9118_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lan9118;
 }
 
-static TypeInfo lan9118_info = {
+static const TypeInfo lan9118_info = {
     .name          = "lan9118",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(lan9118_state),
diff --git a/hw/lance.c b/hw/lance.c
index b7265c0..a5997fd 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -155,7 +155,7 @@ static void lance_class_init(ObjectClass *klass, void *data)
     dc->props = lance_properties;
 }
 
-static TypeInfo lance_info = {
+static const TypeInfo lance_info = {
     .name          = "lance",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusPCNetState),
diff --git a/hw/lm32_juart.c b/hw/lm32_juart.c
index 7c2d202..8c82c85 100644
--- a/hw/lm32_juart.c
+++ b/hw/lm32_juart.c
@@ -144,7 +144,7 @@ static void lm32_juart_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lm32_juart;
 }
 
-static TypeInfo lm32_juart_info = {
+static const TypeInfo lm32_juart_info = {
     .name          = "lm32-juart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LM32JuartState),
diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
index 42d5602..8f13355 100644
--- a/hw/lm32_pic.c
+++ b/hw/lm32_pic.c
@@ -184,7 +184,7 @@ static void lm32_pic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lm32_pic;
 }
 
-static TypeInfo lm32_pic_info = {
+static const TypeInfo lm32_pic_info = {
     .name          = "lm32-pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LM32PicState),
diff --git a/hw/lm32_sys.c b/hw/lm32_sys.c
index e3a9db9..187ef6d 100644
--- a/hw/lm32_sys.c
+++ b/hw/lm32_sys.c
@@ -157,7 +157,7 @@ static void lm32_sys_class_init(ObjectClass *klass, void *data)
     dc->props = lm32_sys_properties;
 }
 
-static TypeInfo lm32_sys_info = {
+static const TypeInfo lm32_sys_info = {
     .name          = "lm32-sys",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LM32SysState),
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index bd4c346..db527e9 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -215,7 +215,7 @@ static void lm32_timer_class_init(ObjectClass *klass, void *data)
     dc->props = lm32_timer_properties;
 }
 
-static TypeInfo lm32_timer_info = {
+static const TypeInfo lm32_timer_info = {
     .name          = "lm32-timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LM32TimerState),
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 89605b8..9c89cca 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -281,7 +281,7 @@ static void lm32_uart_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lm32_uart;
 }
 
-static TypeInfo lm32_uart_info = {
+static const TypeInfo lm32_uart_info = {
     .name          = "lm32-uart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(LM32UartState),
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 3649e3d..af49dd6 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -506,7 +506,7 @@ static void lm8323_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lm_kbd;
 }
 
-static TypeInfo lm8323_info = {
+static const TypeInfo lm8323_info = {
     .name          = "lm8323",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(LM823KbdState),
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 0aafb00..89c657f 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2126,7 +2126,7 @@ static void lsi_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_lsi_scsi;
 }
 
-static TypeInfo lsi_info = {
+static const TypeInfo lsi_info = {
     .name          = "lsi53c895a",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(LSIState),
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 393c5c0..8f1ca3c 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -738,7 +738,7 @@ static void m48t59_init_class_isa1(ObjectClass *klass, void *data)
     dc->props = m48t59_isa_properties;
 }
 
-static TypeInfo m48t59_isa_info = {
+static const TypeInfo m48t59_isa_info = {
     .name          = "m48t59_isa",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(M48t59ISAState),
@@ -762,7 +762,7 @@ static void m48t59_class_init(ObjectClass *klass, void *data)
     dc->props = m48t59_properties;
 }
 
-static TypeInfo m48t59_info = {
+static const TypeInfo m48t59_info = {
     .name          = "m48t59",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(M48t59SysBusState),
diff --git a/hw/macio.c b/hw/macio.c
index 362afdc..675a71c 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -90,7 +90,7 @@ static void macio_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_OTHERS << 8;
 }
 
-static TypeInfo macio_info = {
+static const TypeInfo macio_info = {
     .name          = "macio",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(MacIOState),
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index de16cfa..511004b 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -288,7 +288,7 @@ static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
     dc->props = mv88w8618_audio_properties;
 }
 
-static TypeInfo mv88w8618_audio_info = {
+static const TypeInfo mv88w8618_audio_info = {
     .name          = "mv88w8618_audio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mv88w8618_audio_state),
diff --git a/hw/max111x.c b/hw/max111x.c
index 67640f1..de1be4d 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -162,7 +162,7 @@ static void max1110_class_init(ObjectClass *klass, void *data)
     k->transfer = max111x_transfer;
 }
 
-static TypeInfo max1110_info = {
+static const TypeInfo max1110_info = {
     .name          = "max1110",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(MAX111xState),
@@ -177,7 +177,7 @@ static void max1111_class_init(ObjectClass *klass, void *data)
     k->transfer = max111x_transfer;
 }
 
-static TypeInfo max1111_info = {
+static const TypeInfo max1111_info = {
     .name          = "max1111",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(MAX111xState),
diff --git a/hw/max7310.c b/hw/max7310.c
index 1ed18ba..de2221b 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -198,7 +198,7 @@ static void max7310_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_max7310;
 }
 
-static TypeInfo max7310_info = {
+static const TypeInfo max7310_info = {
     .name          = "max7310",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(MAX7310State),
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2ddd7de..2fb11f6 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -898,7 +898,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
     dc->props = mc146818rtc_properties;
 }
 
-static TypeInfo mc146818rtc_info = {
+static const TypeInfo mc146818rtc_info = {
     .name          = "mc146818rtc",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(RTCState),
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index f46af1c..d51d1ac 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -329,7 +329,7 @@ static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_ac97;
 }
 
-static TypeInfo milkymist_ac97_info = {
+static const TypeInfo milkymist_ac97_info = {
     .name          = "milkymist-ac97",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistAC97State),
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index fd54d31..ea4d210 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -155,7 +155,7 @@ static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_hpdmc;
 }
 
-static TypeInfo milkymist_hpdmc_info = {
+static const TypeInfo milkymist_hpdmc_info = {
     .name          = "milkymist-hpdmc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistHpdmcState),
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index f80befc..9d15309 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -288,7 +288,7 @@ static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_memcard;
 }
 
-static TypeInfo milkymist_memcard_info = {
+static const TypeInfo milkymist_memcard_info = {
     .name          = "milkymist-memcard",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistMemcardState),
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 4e92ac3..43d6c19 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -535,7 +535,7 @@ static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
     dc->props = milkymist_minimac2_properties;
 }
 
-static TypeInfo milkymist_minimac2_info = {
+static const TypeInfo milkymist_minimac2_info = {
     .name          = "milkymist-minimac2",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistMinimac2State),
diff --git a/hw/milkymist-pfpu.c b/hw/milkymist-pfpu.c
index 0521829..c347680 100644
--- a/hw/milkymist-pfpu.c
+++ b/hw/milkymist-pfpu.c
@@ -529,7 +529,7 @@ static void milkymist_pfpu_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_pfpu;
 }
 
-static TypeInfo milkymist_pfpu_info = {
+static const TypeInfo milkymist_pfpu_info = {
     .name          = "milkymist-pfpu",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistPFPUState),
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index b7beb4b..01660be 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -316,7 +316,7 @@ static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
     dc->props = milkymist_softusb_properties;
 }
 
-static TypeInfo milkymist_softusb_info = {
+static const TypeInfo milkymist_softusb_info = {
     .name          = "milkymist-softusb",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistSoftUsbState),
diff --git a/hw/milkymist-sysctl.c b/hw/milkymist-sysctl.c
index 796e795..e69ac6f 100644
--- a/hw/milkymist-sysctl.c
+++ b/hw/milkymist-sysctl.c
@@ -323,7 +323,7 @@ static void milkymist_sysctl_class_init(ObjectClass *klass, void *data)
     dc->props = milkymist_sysctl_properties;
 }
 
-static TypeInfo milkymist_sysctl_info = {
+static const TypeInfo milkymist_sysctl_info = {
     .name          = "milkymist-sysctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistSysctlState),
diff --git a/hw/milkymist-tmu2.c b/hw/milkymist-tmu2.c
index a11772a..42de10a 100644
--- a/hw/milkymist-tmu2.c
+++ b/hw/milkymist-tmu2.c
@@ -475,7 +475,7 @@ static void milkymist_tmu2_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_tmu2;
 }
 
-static TypeInfo milkymist_tmu2_info = {
+static const TypeInfo milkymist_tmu2_info = {
     .name          = "milkymist-tmu2",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistTMU2State),
diff --git a/hw/milkymist-uart.c b/hw/milkymist-uart.c
index 19e9dbd..e73eb84 100644
--- a/hw/milkymist-uart.c
+++ b/hw/milkymist-uart.c
@@ -228,7 +228,7 @@ static void milkymist_uart_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_milkymist_uart;
 }
 
-static TypeInfo milkymist_uart_info = {
+static const TypeInfo milkymist_uart_info = {
     .name          = "milkymist-uart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistUartState),
diff --git a/hw/milkymist-vgafb.c b/hw/milkymist-vgafb.c
index 5612851..4d0a5df 100644
--- a/hw/milkymist-vgafb.c
+++ b/hw/milkymist-vgafb.c
@@ -319,7 +319,7 @@ static void milkymist_vgafb_class_init(ObjectClass *klass, void *data)
     dc->props = milkymist_vgafb_properties;
 }
 
-static TypeInfo milkymist_vgafb_info = {
+static const TypeInfo milkymist_vgafb_info = {
     .name          = "milkymist-vgafb",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MilkymistVgafbState),
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 635143d..2250e67 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -1004,7 +1004,7 @@ static void mips_malta_class_init(ObjectClass *klass, void *data)
     k->init = mips_malta_sysbus_device_init;
 }
 
-static TypeInfo mips_malta_device = {
+static const TypeInfo mips_malta_device = {
     .name          = "mips-malta",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MaltaState),
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index bb752d3..feac815 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -269,7 +269,7 @@ static void mipsnet_class_init(ObjectClass *klass, void *data)
     dc->props = mipsnet_properties;
 }
 
-static TypeInfo mipsnet_info = {
+static const TypeInfo mipsnet_info = {
     .name          = "mipsnet",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MIPSnetState),
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index 84522e9..9c57d76 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -128,7 +128,7 @@ static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
     k->init = mpc8544_guts_initfn;
 }
 
-static TypeInfo mpc8544_guts_info = {
+static const TypeInfo mpc8544_guts_info = {
     .name          = "mpc8544-guts",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GutsState),
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index fb4b739..7ae05e3 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -248,7 +248,7 @@ static void mst_fpga_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_mst_fpga_regs;
 }
 
-static TypeInfo mst_fpga_info = {
+static const TypeInfo mst_fpga_info = {
     .name          = "mainstone-fpga",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mst_irq_state),
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 77a585e..24a1722 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -428,7 +428,7 @@ static void mv88w8618_eth_class_init(ObjectClass *klass, void *data)
     dc->props = mv88w8618_eth_properties;
 }
 
-static TypeInfo mv88w8618_eth_info = {
+static const TypeInfo mv88w8618_eth_info = {
     .name          = "mv88w8618_eth",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mv88w8618_eth_state),
@@ -643,7 +643,7 @@ static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &musicpal_lcd_vmsd;
 }
 
-static TypeInfo musicpal_lcd_info = {
+static const TypeInfo musicpal_lcd_info = {
     .name          = "musicpal_lcd",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(musicpal_lcd_state),
@@ -762,7 +762,7 @@ static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &mv88w8618_pic_vmsd;
 }
 
-static TypeInfo mv88w8618_pic_info = {
+static const TypeInfo mv88w8618_pic_info = {
     .name          = "mv88w8618_pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mv88w8618_pic_state),
@@ -939,7 +939,7 @@ static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &mv88w8618_pit_vmsd;
 }
 
-static TypeInfo mv88w8618_pit_info = {
+static const TypeInfo mv88w8618_pit_info = {
     .name          = "mv88w8618_pit",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mv88w8618_pit_state),
@@ -1019,7 +1019,7 @@ static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &mv88w8618_flashcfg_vmsd;
 }
 
-static TypeInfo mv88w8618_flashcfg_info = {
+static const TypeInfo mv88w8618_flashcfg_info = {
     .name          = "mv88w8618_flashcfg",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(mv88w8618_flashcfg_state),
@@ -1341,7 +1341,7 @@ static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &musicpal_gpio_vmsd;
 }
 
-static TypeInfo musicpal_gpio_info = {
+static const TypeInfo musicpal_gpio_info = {
     .name          = "musicpal_gpio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(musicpal_gpio_state),
@@ -1495,7 +1495,7 @@ static void musicpal_key_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &musicpal_key_vmsd;
 }
 
-static TypeInfo musicpal_key_info = {
+static const TypeInfo musicpal_key_info = {
     .name          = "musicpal_key",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(musicpal_key_state),
@@ -1674,7 +1674,7 @@ static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
     sdc->init = mv88w8618_wlan_init;
 }
 
-static TypeInfo mv88w8618_wlan_info = {
+static const TypeInfo mv88w8618_wlan_info = {
     .name          = "mv88w8618_wlan",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusDevice),
diff --git a/hw/nand.c b/hw/nand.c
index 16950c5..6054f46 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -435,7 +435,7 @@ static void nand_class_init(ObjectClass *klass, void *data)
     dc->props = nand_properties;
 }
 
-static TypeInfo nand_info = {
+static const TypeInfo nand_info = {
     .name          = "nand",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(NANDFlashState),
diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c
index c2c00c2..7c11229 100644
--- a/hw/ne2000-isa.c
+++ b/hw/ne2000-isa.c
@@ -97,7 +97,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
     dc->props = ne2000_isa_properties;
 }
 
-static TypeInfo ne2000_isa_info = {
+static const TypeInfo ne2000_isa_info = {
     .name          = "ne2k_isa",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISANE2000State),
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 00efa74..872115c 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -773,7 +773,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data)
     dc->props = ne2000_properties;
 }
 
-static TypeInfo ne2000_info = {
+static const TypeInfo ne2000_info = {
     .name          = "ne2k_pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCINE2000State),
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 2565532..15bdd62 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -747,7 +747,7 @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
     dc->props = omap_gpio_properties;
 }
 
-static TypeInfo omap_gpio_info = {
+static const TypeInfo omap_gpio_info = {
     .name          = "omap-gpio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct omap_gpif_s),
@@ -776,7 +776,7 @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
     dc->props = omap2_gpio_properties;
 }
 
-static TypeInfo omap2_gpio_info = {
+static const TypeInfo omap2_gpio_info = {
     .name          = "omap2-gpio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct omap2_gpif_s),
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index ba08e64..e0a5087 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -471,7 +471,7 @@ static void omap_i2c_class_init(ObjectClass *klass, void *data)
     dc->reset = omap_i2c_reset;
 }
 
-static TypeInfo omap_i2c_info = {
+static const TypeInfo omap_i2c_info = {
     .name = "omap_i2c",
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OMAPI2CState),
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 61e0daf..113725e 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -389,7 +389,7 @@ static void omap_intc_class_init(ObjectClass *klass, void *data)
     dc->props = omap_intc_properties;
 }
 
-static TypeInfo omap_intc_info = {
+static const TypeInfo omap_intc_info = {
     .name          = "omap-intc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct omap_intr_handler_s),
@@ -633,7 +633,7 @@ static void omap2_intc_class_init(ObjectClass *klass, void *data)
     dc->props = omap2_intc_properties;
 }
 
-static TypeInfo omap2_intc_info = {
+static const TypeInfo omap2_intc_info = {
     .name          = "omap2-intc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct omap_intr_handler_s),
diff --git a/hw/onenand.c b/hw/onenand.c
index 26bf991..b82bf7d 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -821,7 +821,7 @@ static void onenand_class_init(ObjectClass *klass, void *data)
     dc->props = onenand_properties;
 }
 
-static TypeInfo onenand_info = {
+static const TypeInfo onenand_info = {
     .name          = "onenand",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OneNANDState),
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index a0dfdce..746a959 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -718,7 +718,7 @@ static void open_eth_class_init(ObjectClass *klass, void *data)
     dc->props = open_eth_properties;
 }
 
-static TypeInfo open_eth_info = {
+static const TypeInfo open_eth_info = {
     .name          = "open_eth",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OpenEthState),
diff --git a/hw/openpic.c b/hw/openpic.c
index 9c956b9..a8c5959 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1270,7 +1270,7 @@ static void openpic_class_init(ObjectClass *klass, void *data)
     dc->reset = openpic_reset;
 }
 
-static TypeInfo openpic_info = {
+static const TypeInfo openpic_info = {
     .name          = "openpic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OpenPICState),
diff --git a/hw/parallel.c b/hw/parallel.c
index 64a46c6..3a4e06b 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -599,7 +599,7 @@ static void parallel_isa_class_initfn(ObjectClass *klass, void *data)
     dc->props = parallel_isa_properties;
 }
 
-static TypeInfo parallel_isa_info = {
+static const TypeInfo parallel_isa_info = {
     .name          = "isa-parallel",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAParallelState),
diff --git a/hw/pc-testdev.c b/hw/pc-testdev.c
index 1928489..ec0bc4b 100644
--- a/hw/pc-testdev.c
+++ b/hw/pc-testdev.c
@@ -172,7 +172,7 @@ static void testdev_class_init(ObjectClass *klass, void *data)
     k->init = init_test_device;
 }
 
-static TypeInfo testdev_info = {
+static const TypeInfo testdev_info = {
     .name           = TYPE_TESTDEV,
     .parent         = TYPE_ISA_DEVICE,
     .instance_size  = sizeof(struct PCTestdev),
diff --git a/hw/pc.c b/hw/pc.c
index df0c48e..68984e4 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -501,7 +501,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_port92_isa;
 }
 
-static TypeInfo port92_info = {
+static const TypeInfo port92_info = {
     .name          = "port92",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(Port92State),
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 7567593..7f6c12c 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -256,7 +256,7 @@ static void pcsysfw_class_init (ObjectClass *klass, void *data)
     dc->props = pcsysfw_properties;
 }
 
-static TypeInfo pcsysfw_info = {
+static const TypeInfo pcsysfw_info = {
     .name          = "pc-sysfw",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof (PcSysFwDevice),
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 94840c4..5fd1bcf 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -2150,7 +2150,7 @@ void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque)
     bus->dma_context_opaque = opaque;
 }
 
-static TypeInfo pci_device_type_info = {
+static const TypeInfo pci_device_type_info = {
     .name = TYPE_PCI_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(PCIDevice),
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 7818dcc..1a7b2cd 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -156,7 +156,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &pci_bridge_dev_vmstate;
 }
 
-static TypeInfo pci_bridge_dev_info = {
+static const TypeInfo pci_bridge_dev_info = {
     .name = "pci-bridge",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIBridgeDev),
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 6db7bbc..3bad09b 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -512,7 +512,7 @@ static void i8042_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_kbd_isa;
 }
 
-static TypeInfo i8042_info = {
+static const TypeInfo i8042_info = {
     .name          = "i8042",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAKBDState),
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 40a0e6e..a94f642 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -361,7 +361,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data)
     dc->props = pcnet_properties;
 }
 
-static TypeInfo pcnet_info = {
+static const TypeInfo pcnet_info = {
     .name          = "pcnet",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIPCNetState),
diff --git a/hw/pcspk.c b/hw/pcspk.c
index 6d55ebe..dfab955 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -187,7 +187,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
     dc->props = pcspk_properties;
 }
 
-static TypeInfo pcspk_info = {
+static const TypeInfo pcspk_info = {
     .name           = "isa-pcspk",
     .parent         = TYPE_ISA_DEVICE,
     .instance_size  = sizeof(PCSpkState),
diff --git a/hw/piix4.c b/hw/piix4.c
index 799ed17..c1cb94d 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -117,7 +117,7 @@ static void piix4_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_piix4;
 }
 
-static TypeInfo piix4_info = {
+static const TypeInfo piix4_info = {
     .name          = "PIIX4",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PIIX4State),
diff --git a/hw/pl011.c b/hw/pl011.c
index 35835f3..002a50e 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -300,7 +300,7 @@ static void pl011_arm_class_init(ObjectClass *klass, void *data)
     sdc->init = pl011_arm_init;
 }
 
-static TypeInfo pl011_arm_info = {
+static const TypeInfo pl011_arm_info = {
     .name          = "pl011",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl011_state),
@@ -314,7 +314,7 @@ static void pl011_luminary_class_init(ObjectClass *klass, void *data)
     sdc->init = pl011_luminary_init;
 }
 
-static TypeInfo pl011_luminary_info = {
+static const TypeInfo pl011_luminary_info = {
     .name          = "pl011_luminary",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl011_state),
diff --git a/hw/pl022.c b/hw/pl022.c
index fbd7ded..c160e90 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -293,7 +293,7 @@ static void pl022_class_init(ObjectClass *klass, void *data)
     sdc->init = pl022_init;
 }
 
-static TypeInfo pl022_info = {
+static const TypeInfo pl022_info = {
     .name          = "pl022",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl022_state),
diff --git a/hw/pl031.c b/hw/pl031.c
index 3a23ecd..757867f 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -250,7 +250,7 @@ static void pl031_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl031;
 }
 
-static TypeInfo pl031_info = {
+static const TypeInfo pl031_info = {
     .name          = "pl031",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl031_state),
diff --git a/hw/pl041.c b/hw/pl041.c
index 4436d97..0b71c45 100644
--- a/hw/pl041.c
+++ b/hw/pl041.c
@@ -632,7 +632,7 @@ static void pl041_device_class_init(ObjectClass *klass, void *data)
     dc->props = pl041_device_properties;
 }
 
-static TypeInfo pl041_device_info = {
+static const TypeInfo pl041_device_info = {
     .name          = "pl041",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl041_state),
diff --git a/hw/pl050.c b/hw/pl050.c
index 47032f1..5d06bc9 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -168,7 +168,7 @@ static void pl050_kbd_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl050;
 }
 
-static TypeInfo pl050_kbd_info = {
+static const TypeInfo pl050_kbd_info = {
     .name          = "pl050_keyboard",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl050_state),
@@ -184,7 +184,7 @@ static void pl050_mouse_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl050;
 }
 
-static TypeInfo pl050_mouse_info = {
+static const TypeInfo pl050_mouse_info = {
     .name          = "pl050_mouse",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl050_state),
diff --git a/hw/pl061.c b/hw/pl061.c
index f1ed5ce..a78e819 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -304,7 +304,7 @@ static void pl061_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl061;
 }
 
-static TypeInfo pl061_info = {
+static const TypeInfo pl061_info = {
     .name          = "pl061",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl061_state),
@@ -320,7 +320,7 @@ static void pl061_luminary_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl061;
 }
 
-static TypeInfo pl061_luminary_info = {
+static const TypeInfo pl061_luminary_info = {
     .name          = "pl061_luminary",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl061_state),
diff --git a/hw/pl080.c b/hw/pl080.c
index 26150af..f6bbf98 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -386,7 +386,7 @@ static void pl080_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl080;
 }
 
-static TypeInfo pl080_info = {
+static const TypeInfo pl080_info = {
     .name          = "pl080",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl080_state),
@@ -403,7 +403,7 @@ static void pl081_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl080;
 }
 
-static TypeInfo pl081_info = {
+static const TypeInfo pl081_info = {
     .name          = "pl081",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl080_state),
diff --git a/hw/pl110.c b/hw/pl110.c
index 098e335..3d0ac00 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -480,7 +480,7 @@ static void pl110_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl110;
 }
 
-static TypeInfo pl110_info = {
+static const TypeInfo pl110_info = {
     .name          = "pl110",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl110_state),
@@ -497,7 +497,7 @@ static void pl110_versatile_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl110;
 }
 
-static TypeInfo pl110_versatile_info = {
+static const TypeInfo pl110_versatile_info = {
     .name          = "pl110_versatile",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl110_state),
@@ -514,7 +514,7 @@ static void pl111_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl110;
 }
 
-static TypeInfo pl111_info = {
+static const TypeInfo pl111_info = {
     .name          = "pl111",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl110_state),
diff --git a/hw/pl181.c b/hw/pl181.c
index cbddb74..98529f7 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -500,7 +500,7 @@ static void pl181_class_init(ObjectClass *klass, void *data)
     k->no_user = 1;
 }
 
-static TypeInfo pl181_info = {
+static const TypeInfo pl181_info = {
     .name          = "pl181",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl181_state),
diff --git a/hw/pl190.c b/hw/pl190.c
index 4019930..76ac159 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -274,7 +274,7 @@ static void pl190_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pl190;
 }
 
-static TypeInfo pl190_info = {
+static const TypeInfo pl190_info = {
     .name          = "pl190",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(pl190_state),
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 177aa2d..1b2c34f 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -212,7 +212,7 @@ static void ppce500_spin_class_init(ObjectClass *klass, void *data)
     k->init = ppce500_spin_initfn;
 }
 
-static TypeInfo ppce500_spin_info = {
+static const TypeInfo ppce500_spin_info = {
     .name          = "e500-spin",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SpinState),
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 3c51bc8..f3dffef 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1194,7 +1194,7 @@ static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pxa2xx_rtc_regs;
 }
 
-static TypeInfo pxa2xx_rtc_sysbus_info = {
+static const TypeInfo pxa2xx_rtc_sysbus_info = {
     .name          = "pxa2xx_rtc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxRTCState),
@@ -1442,7 +1442,7 @@ static void pxa2xx_i2c_slave_class_init(ObjectClass *klass, void *data)
     k->send = pxa2xx_i2c_tx;
 }
 
-static TypeInfo pxa2xx_i2c_slave_info = {
+static const TypeInfo pxa2xx_i2c_slave_info = {
     .name          = "pxa2xx-i2c-slave",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(PXA2xxI2CSlaveState),
@@ -1510,7 +1510,7 @@ static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
     dc->props = pxa2xx_i2c_properties;
 }
 
-static TypeInfo pxa2xx_i2c_info = {
+static const TypeInfo pxa2xx_i2c_info = {
     .name          = "pxa2xx_i2c",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxI2CState),
@@ -2273,7 +2273,7 @@ static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
     sdc->init = pxa2xx_ssp_init;
 }
 
-static TypeInfo pxa2xx_ssp_info = {
+static const TypeInfo pxa2xx_ssp_info = {
     .name          = "pxa2xx-ssp",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxSSPState),
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index dbea1d2..693b1c2 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -559,7 +559,7 @@ static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
     dc->props = pxa2xx_dma_properties;
 }
 
-static TypeInfo pxa2xx_dma_info = {
+static const TypeInfo pxa2xx_dma_info = {
     .name          = "pxa2xx-dma",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxDMAState),
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 7aaf409..016833d 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -334,7 +334,7 @@ static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
     dc->props = pxa2xx_gpio_properties;
 }
 
-static TypeInfo pxa2xx_gpio_info = {
+static const TypeInfo pxa2xx_gpio_info = {
     .name          = "pxa2xx-gpio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxGPIOInfo),
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 70b2b79..138245b 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -319,7 +319,7 @@ static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_pxa2xx_pic_regs;
 }
 
-static TypeInfo pxa2xx_pic_info = {
+static const TypeInfo pxa2xx_pic_info = {
     .name          = "pxa2xx_pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxPICState),
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index e4ffb15..32c1872 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -495,7 +495,7 @@ static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
     dc->props = pxa25x_timer_dev_properties;
 }
 
-static TypeInfo pxa25x_timer_dev_info = {
+static const TypeInfo pxa25x_timer_dev_info = {
     .name          = "pxa25x-timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxTimerInfo),
@@ -520,7 +520,7 @@ static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
     dc->props = pxa27x_timer_dev_properties;
 }
 
-static TypeInfo pxa27x_timer_dev_info = {
+static const TypeInfo pxa27x_timer_dev_info = {
     .name          = "pxa27x-timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PXA2xxTimerInfo),
diff --git a/hw/qdev.c b/hw/qdev.c
index e2a5c57..b027ead 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -732,7 +732,7 @@ Object *qdev_get_machine(void)
     return dev;
 }
 
-static TypeInfo device_type_info = {
+static const TypeInfo device_type_info = {
     .name = TYPE_DEVICE,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(DeviceState),
diff --git a/hw/qxl.c b/hw/qxl.c
index d08b9bd..00e517a 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -2310,7 +2310,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data)
     dc->props = qxl_properties;
 }
 
-static TypeInfo qxl_primary_info = {
+static const TypeInfo qxl_primary_info = {
     .name          = "qxl-vga",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIQXLDevice),
@@ -2332,7 +2332,7 @@ static void qxl_secondary_class_init(ObjectClass *klass, void *data)
     dc->props = qxl_properties;
 }
 
-static TypeInfo qxl_secondary_info = {
+static const TypeInfo qxl_secondary_info = {
     .name          = "qxl",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIQXLDevice),
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 5bc37a7..b1b74d8 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -59,7 +59,7 @@ static void realview_gic_class_init(ObjectClass *klass, void *data)
     sdc->init = realview_gic_init;
 }
 
-static TypeInfo realview_gic_info = {
+static const TypeInfo realview_gic_info = {
     .name          = "realview_gic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(RealViewGICState),
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 3e08062..cfbf3f4 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3540,7 +3540,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data)
     dc->props = rtl8139_properties;
 }
 
-static TypeInfo rtl8139_info = {
+static const TypeInfo rtl8139_info = {
     .name          = "rtl8139",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(RTL8139State),
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 7e99175..bcb09f2 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -419,7 +419,7 @@ static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
     dc->props = s390_virtio_net_properties;
 }
 
-static TypeInfo s390_virtio_net = {
+static const TypeInfo s390_virtio_net = {
     .name          = "virtio-net-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -445,7 +445,7 @@ static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
     dc->props = s390_virtio_blk_properties;
 }
 
-static TypeInfo s390_virtio_blk = {
+static const TypeInfo s390_virtio_blk = {
     .name          = "virtio-blk-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -467,7 +467,7 @@ static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
     dc->props = s390_virtio_serial_properties;
 }
 
-static TypeInfo s390_virtio_serial = {
+static const TypeInfo s390_virtio_serial = {
     .name          = "virtio-serial-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -489,7 +489,7 @@ static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
     k->init = s390_virtio_rng_init;
 }
 
-static TypeInfo s390_virtio_rng = {
+static const TypeInfo s390_virtio_rng = {
     .name          = "virtio-rng-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -514,7 +514,7 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
     dc->unplug = qdev_simple_unplug_cb;
 }
 
-static TypeInfo virtio_s390_device_info = {
+static const TypeInfo virtio_s390_device_info = {
     .name = TYPE_VIRTIO_S390_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -537,7 +537,7 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
     dc->props = s390_virtio_scsi_properties;
 }
 
-static TypeInfo s390_virtio_scsi = {
+static const TypeInfo s390_virtio_scsi = {
     .name          = "virtio-scsi-s390",
     .parent        = TYPE_VIRTIO_S390_DEVICE,
     .instance_size = sizeof(VirtIOS390Device),
@@ -562,7 +562,7 @@ static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo s390_virtio_bridge_info = {
+static const TypeInfo s390_virtio_bridge_info = {
     .name          = "s390-virtio-bridge",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusDevice),
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 89b1b66..6b56995 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -345,7 +345,7 @@ static void init_event_facility_class(ObjectClass *klass, void *data)
     k->init = init_event_facility;
 }
 
-static TypeInfo s390_sclp_event_facility_info = {
+static const TypeInfo s390_sclp_event_facility_info = {
     .name          = "s390-sclp-event-facility",
     .parent        = TYPE_DEVICE_S390_SCLP,
     .instance_size = sizeof(S390SCLPDevice),
@@ -380,7 +380,7 @@ static void event_class_init(ObjectClass *klass, void *data)
     dc->exit = event_qdev_exit;
 }
 
-static TypeInfo s390_sclp_event_type_info = {
+static const TypeInfo s390_sclp_event_type_info = {
     .name = TYPE_SCLP_EVENT,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(SCLPEvent),
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 7ad791d..a9d3a6a 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -146,7 +146,7 @@ static void s390_sclp_device_class_init(ObjectClass *klass, void *data)
     dc->init = s390_sclp_dev_init;
 }
 
-static TypeInfo s390_sclp_device_info = {
+static const TypeInfo s390_sclp_device_info = {
     .name = TYPE_DEVICE_S390_SCLP,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(S390SCLPDevice),
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
index aa70e16..adc0ee8 100644
--- a/hw/s390x/sclpconsole.c
+++ b/hw/s390x/sclpconsole.c
@@ -291,7 +291,7 @@ static void console_class_init(ObjectClass *klass, void *data)
     ec->write_event_data = write_event_data;
 }
 
-static TypeInfo sclp_console_info = {
+static const TypeInfo sclp_console_info = {
     .name          = "sclpconsole",
     .parent        = TYPE_SCLP_EVENT,
     .instance_size = sizeof(SCLPConsole),
diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c
index 6e6f562..2538498 100644
--- a/hw/s390x/sclpquiesce.c
+++ b/hw/s390x/sclpquiesce.c
@@ -107,7 +107,7 @@ static void quiesce_class_init(ObjectClass *klass, void *data)
     k->write_event_data = NULL;
 }
 
-static TypeInfo sclp_quiesce_info = {
+static const TypeInfo sclp_quiesce_info = {
     .name          = "sclpquiesce",
     .parent        = TYPE_SCLP_EVENT,
     .instance_size = sizeof(SCLPEvent),
diff --git a/hw/sb16.c b/hw/sb16.c
index bb460cc..52dfedf 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1409,7 +1409,7 @@ static void sb16_class_initfn (ObjectClass *klass, void *data)
     dc->props = sb16_properties;
 }
 
-static TypeInfo sb16_info = {
+static const TypeInfo sb16_info = {
     .name          = "sb16",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof (SB16State),
diff --git a/hw/sbi.c b/hw/sbi.c
index ca78a38..d58184a 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -141,7 +141,7 @@ static void sbi_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_sbi;
 }
 
-static TypeInfo sbi_info = {
+static const TypeInfo sbi_info = {
     .name          = "sbi",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SBIState),
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 970c1fc..267a942 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1863,7 +1863,7 @@ static void scsi_device_class_init(ObjectClass *klass, void *data)
     k->props    = scsi_props;
 }
 
-static TypeInfo scsi_device_type_info = {
+static const TypeInfo scsi_device_type_info = {
     .name = TYPE_SCSI_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(SCSIDevice),
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a69735b..f8d7ef3 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -2389,7 +2389,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
-static TypeInfo scsi_hd_info = {
+static const TypeInfo scsi_hd_info = {
     .name          = "scsi-hd",
     .parent        = TYPE_SCSI_DEVICE,
     .instance_size = sizeof(SCSIDiskState),
@@ -2418,7 +2418,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
-static TypeInfo scsi_cd_info = {
+static const TypeInfo scsi_cd_info = {
     .name          = "scsi-cd",
     .parent        = TYPE_SCSI_DEVICE,
     .instance_size = sizeof(SCSIDiskState),
@@ -2447,7 +2447,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
-static TypeInfo scsi_block_info = {
+static const TypeInfo scsi_block_info = {
     .name          = "scsi-block",
     .parent        = TYPE_SCSI_DEVICE,
     .instance_size = sizeof(SCSIDiskState),
@@ -2481,7 +2481,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd  = &vmstate_scsi_disk_state;
 }
 
-static TypeInfo scsi_disk_info = {
+static const TypeInfo scsi_disk_info = {
     .name          = "scsi-disk",
     .parent        = TYPE_SCSI_DEVICE,
     .instance_size = sizeof(SCSIDiskState),
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 4c702be..8175474 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -499,7 +499,7 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd  = &vmstate_scsi_device;
 }
 
-static TypeInfo scsi_generic_info = {
+static const TypeInfo scsi_generic_info = {
     .name          = "scsi-generic",
     .parent        = TYPE_SCSI_DEVICE,
     .instance_size = sizeof(SCSIDevice),
diff --git a/hw/serial-isa.c b/hw/serial-isa.c
index 96c78f7..5a6f51f 100644
--- a/hw/serial-isa.c
+++ b/hw/serial-isa.c
@@ -99,7 +99,7 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data)
     dc->props = serial_isa_properties;
 }
 
-static TypeInfo serial_isa_info = {
+static const TypeInfo serial_isa_info = {
     .name          = "isa-serial",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISASerialState),
diff --git a/hw/serial-pci.c b/hw/serial-pci.c
index 6a2548a..c62cc9e 100644
--- a/hw/serial-pci.c
+++ b/hw/serial-pci.c
@@ -221,21 +221,21 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
     dc->props = multi_4x_serial_pci_properties;
 }
 
-static TypeInfo serial_pci_info = {
+static const TypeInfo serial_pci_info = {
     .name          = "pci-serial",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCISerialState),
     .class_init    = serial_pci_class_initfn,
 };
 
-static TypeInfo multi_2x_serial_pci_info = {
+static const TypeInfo multi_2x_serial_pci_info = {
     .name          = "pci-serial-2x",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIMultiSerialState),
     .class_init    = multi_2x_serial_pci_class_initfn,
 };
 
-static TypeInfo multi_4x_serial_pci_info = {
+static const TypeInfo multi_4x_serial_pci_info = {
     .name          = "pci-serial-4x",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIMultiSerialState),
diff --git a/hw/sga.c b/hw/sga.c
index d5c91ed..29bc3e0 100644
--- a/hw/sga.c
+++ b/hw/sga.c
@@ -48,7 +48,7 @@ static void sga_class_initfn(ObjectClass *klass, void *data)
     dc->desc = "Serial Graphics Adapter";
 }
 
-static TypeInfo sga_info = {
+static const TypeInfo sga_info = {
     .name          = "sga",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISASGAState),
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 018b1c1..077d957 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -156,7 +156,7 @@ static void sh_pci_host_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
 }
 
-static TypeInfo sh_pci_host_info = {
+static const TypeInfo sh_pci_host_info = {
     .name          = "sh_pci_host",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -170,7 +170,7 @@ static void sh_pci_device_class_init(ObjectClass *klass, void *data)
     sdc->init = sh_pci_device_init;
 }
 
-static TypeInfo sh_pci_device_info = {
+static const TypeInfo sh_pci_device_info = {
     .name          = "sh_pci",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SHPCIState),
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index a44ce95..d67c8cc 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -456,7 +456,7 @@ static void slavio_intctl_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_intctl;
 }
 
-static TypeInfo slavio_intctl_info = {
+static const TypeInfo slavio_intctl_info = {
     .name          = "slavio_intctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SLAVIO_INTCTLState),
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 704f2b1..af24cc1 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -478,7 +478,7 @@ static void slavio_misc_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_misc;
 }
 
-static TypeInfo slavio_misc_info = {
+static const TypeInfo slavio_misc_info = {
     .name          = "slavio_misc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MiscState),
@@ -492,7 +492,7 @@ static void apc_class_init(ObjectClass *klass, void *data)
     k->init = apc_init1;
 }
 
-static TypeInfo apc_info = {
+static const TypeInfo apc_info = {
     .name          = "apc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(MiscState),
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 584629f..68a4c0c 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -420,7 +420,7 @@ static void slavio_timer_class_init(ObjectClass *klass, void *data)
     dc->props = slavio_timer_properties;
 }
 
-static TypeInfo slavio_timer_info = {
+static const TypeInfo slavio_timer_info = {
     .name          = "slavio_timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SLAVIO_TIMERState),
diff --git a/hw/smbus.c b/hw/smbus.c
index e3cf6a2..a908591 100644
--- a/hw/smbus.c
+++ b/hw/smbus.c
@@ -318,7 +318,7 @@ static void smbus_device_class_init(ObjectClass *klass, void *data)
     sc->send = smbus_i2c_send;
 }
 
-static TypeInfo smbus_device_type_info = {
+static const TypeInfo smbus_device_type_info = {
     .name = TYPE_SMBUS_DEVICE,
     .parent = TYPE_I2C_SLAVE,
     .instance_size = sizeof(SMBusDevice),
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 11adab0..d36dc7b 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -123,7 +123,7 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data)
     dc->props = smbus_eeprom_properties;
 }
 
-static TypeInfo smbus_eeprom_info = {
+static const TypeInfo smbus_eeprom_info = {
     .name          = "smbus-eeprom",
     .parent        = TYPE_SMBUS_DEVICE,
     .instance_size = sizeof(SMBusEEPROMDevice),
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 2161b4a..a34698f 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -774,7 +774,7 @@ static void smc91c111_class_init(ObjectClass *klass, void *data)
     dc->props = smc91c111_properties;
 }
 
-static TypeInfo smc91c111_info = {
+static const TypeInfo smc91c111_info = {
     .name          = "smc91c111",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(smc91c111_state),
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 8077eb9..db34b48 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -502,7 +502,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
     k->rtce_window_size = 0x10000000;
 }
 
-static TypeInfo spapr_vlan_info = {
+static const TypeInfo spapr_vlan_info = {
     .name          = "spapr-vlan",
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VIOsPAPRVLANDevice),
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index a58621d..3a1a486 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -536,7 +536,7 @@ static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo spapr_vio_bridge_info = {
+static const TypeInfo spapr_vio_bridge_info = {
     .name          = "spapr-vio-bridge",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusDevice),
@@ -552,7 +552,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
     k->props = spapr_vio_props;
 }
 
-static TypeInfo spapr_vio_type_info = {
+static const TypeInfo spapr_vio_type_info = {
     .name = TYPE_VIO_SPAPR_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(VIOsPAPRDevice),
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 2d81132..7fc0e13 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -967,7 +967,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
     k->rtce_window_size = 0x10000000;
 }
 
-static TypeInfo spapr_vscsi_info = {
+static const TypeInfo spapr_vscsi_info = {
     .name          = "spapr-vscsi",
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VSCSIState),
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index ec81a7e..5c63eaa 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -150,7 +150,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
     dc->props = spapr_vty_properties;
 }
 
-static TypeInfo spapr_vty_info = {
+static const TypeInfo spapr_vty_info = {
     .name          = "spapr-vty",
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VIOsPAPRVTYDevice),
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index d11a302..6d0df51 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -300,7 +300,7 @@ static void sparc32_dma_class_init(ObjectClass *klass, void *data)
     dc->props = sparc32_dma_properties;
 }
 
-static TypeInfo sparc32_dma_info = {
+static const TypeInfo sparc32_dma_info = {
     .name          = "sparc32_dma",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(DMAState),
diff --git a/hw/spitz.c b/hw/spitz.c
index 8e1be7f..f1659c4 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -1022,7 +1022,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data)
     dc->props = sl_nand_properties;
 }
 
-static TypeInfo sl_nand_info = {
+static const TypeInfo sl_nand_info = {
     .name          = "sl-nand",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SLNANDState),
@@ -1057,7 +1057,7 @@ static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
     dc->props = spitz_keyboard_properties;
 }
 
-static TypeInfo spitz_keyboard_info = {
+static const TypeInfo spitz_keyboard_info = {
     .name          = "spitz-keyboard",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SpitzKeyboardState),
@@ -1086,7 +1086,7 @@ static void corgi_ssp_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_corgi_ssp_regs;
 }
 
-static TypeInfo corgi_ssp_info = {
+static const TypeInfo corgi_ssp_info = {
     .name          = "corgi-ssp",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(CorgiSSPState),
@@ -1116,7 +1116,7 @@ static void spitz_lcdtg_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_spitz_lcdtg_regs;
 }
 
-static TypeInfo spitz_lcdtg_info = {
+static const TypeInfo spitz_lcdtg_info = {
     .name          = "spitz-lcdtg",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(SpitzLCDTG),
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index cbdf49a..8777b16 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -306,7 +306,7 @@ static void ssd0303_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_ssd0303;
 }
 
-static TypeInfo ssd0303_info = {
+static const TypeInfo ssd0303_info = {
     .name          = "ssd0303",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(ssd0303_state),
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index fe6f801..84c86a5 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -357,7 +357,7 @@ static void ssd0323_class_init(ObjectClass *klass, void *data)
     k->cs_polarity = SSI_CS_HIGH;
 }
 
-static TypeInfo ssd0323_info = {
+static const TypeInfo ssd0323_info = {
     .name          = "ssd0323",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(ssd0323_state),
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index d61c332..dca8906 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -259,7 +259,7 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data)
     k->cs_polarity = SSI_CS_LOW;
 }
 
-static TypeInfo ssi_sd_info = {
+static const TypeInfo ssi_sd_info = {
     .name          = "ssi-sd",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(ssi_sd_state),
diff --git a/hw/ssi.c b/hw/ssi.c
index 2b56357..0b18176 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -78,7 +78,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data)
     }
 }
 
-static TypeInfo ssi_slave_info = {
+static const TypeInfo ssi_slave_info = {
     .name = TYPE_SSI_SLAVE,
     .parent = TYPE_DEVICE,
     .class_init = ssi_slave_class_init,
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 26da3c7..12e4568 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1354,7 +1354,7 @@ static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
     sdc->init = stellaris_i2c_init;
 }
 
-static TypeInfo stellaris_i2c_info = {
+static const TypeInfo stellaris_i2c_info = {
     .name          = "stellaris-i2c",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(stellaris_i2c_state),
@@ -1368,7 +1368,7 @@ static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
     sdc->init = stellaris_gptm_init;
 }
 
-static TypeInfo stellaris_gptm_info = {
+static const TypeInfo stellaris_gptm_info = {
     .name          = "stellaris-gptm",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(gptm_state),
@@ -1382,7 +1382,7 @@ static void stellaris_adc_class_init(ObjectClass *klass, void *data)
     sdc->init = stellaris_adc_init;
 }
 
-static TypeInfo stellaris_adc_info = {
+static const TypeInfo stellaris_adc_info = {
     .name          = "stellaris-adc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(stellaris_adc_state),
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index d7e1e21..5e9053f 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -434,7 +434,7 @@ static void stellaris_enet_class_init(ObjectClass *klass, void *data)
     dc->props = stellaris_enet_properties;
 }
 
-static TypeInfo stellaris_enet_info = {
+static const TypeInfo stellaris_enet_info = {
     .name          = "stellaris_enet",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(stellaris_enet_state),
diff --git a/hw/stream.c b/hw/stream.c
index be57e8b..d4cf84d 100644
--- a/hw/stream.c
+++ b/hw/stream.c
@@ -8,7 +8,7 @@ stream_push(StreamSlave *sink, uint8_t *buf, size_t len, uint32_t *app)
     k->push(sink, buf, len, app);
 }
 
-static TypeInfo stream_slave_info = {
+static const TypeInfo stream_slave_info = {
     .name          = TYPE_STREAM_SLAVE,
     .parent        = TYPE_INTERFACE,
     .class_size = sizeof(StreamSlaveClass),
diff --git a/hw/strongarm.c b/hw/strongarm.c
index 804c1a3..af688ac 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -212,7 +212,7 @@ static void strongarm_pic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_strongarm_pic_regs;
 }
 
-static TypeInfo strongarm_pic_info = {
+static const TypeInfo strongarm_pic_info = {
     .name          = "strongarm_pic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMPICState),
@@ -433,7 +433,7 @@ static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_strongarm_rtc_regs;
 }
 
-static TypeInfo strongarm_rtc_sysbus_info = {
+static const TypeInfo strongarm_rtc_sysbus_info = {
     .name          = "strongarm-rtc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMRTCState),
@@ -674,7 +674,7 @@ static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
     dc->desc = "StrongARM GPIO controller";
 }
 
-static TypeInfo strongarm_gpio_info = {
+static const TypeInfo strongarm_gpio_info = {
     .name          = "strongarm-gpio",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMGPIOInfo),
@@ -840,7 +840,7 @@ static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
     dc->desc = "StrongARM PPC controller";
 }
 
-static TypeInfo strongarm_ppc_info = {
+static const TypeInfo strongarm_ppc_info = {
     .name          = "strongarm-ppc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMPPCInfo),
@@ -1299,7 +1299,7 @@ static void strongarm_uart_class_init(ObjectClass *klass, void *data)
     dc->props = strongarm_uart_properties;
 }
 
-static TypeInfo strongarm_uart_info = {
+static const TypeInfo strongarm_uart_info = {
     .name          = "strongarm-uart",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMUARTState),
@@ -1538,7 +1538,7 @@ static void strongarm_ssp_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_strongarm_ssp_regs;
 }
 
-static TypeInfo strongarm_ssp_info = {
+static const TypeInfo strongarm_ssp_info = {
     .name          = "strongarm-ssp",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(StrongARMSSPState),
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index b78d54f..f8f4d02 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -193,7 +193,7 @@ static void sun4c_intctl_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_sun4c_intctl;
 }
 
-static TypeInfo sun4c_intctl_info = {
+static const TypeInfo sun4c_intctl_info = {
     .name          = "sun4c_intctl",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(Sun4c_INTCTLState),
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 0d84b37..5925d29 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -633,7 +633,7 @@ static void idreg_class_init(ObjectClass *klass, void *data)
     k->init = idreg_init1;
 }
 
-static TypeInfo idreg_info = {
+static const TypeInfo idreg_info = {
     .name          = "macio_idreg",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IDRegState),
@@ -675,7 +675,7 @@ static void afx_class_init(ObjectClass *klass, void *data)
     k->init = afx_init1;
 }
 
-static TypeInfo afx_info = {
+static const TypeInfo afx_info = {
     .name          = "tcx_afx",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(AFXState),
@@ -752,7 +752,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
     dc->props = prom_properties;
 }
 
-static TypeInfo prom_info = {
+static const TypeInfo prom_info = {
     .name          = "openprom",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PROMState),
@@ -816,7 +816,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
     dc->props = ram_properties;
 }
 
-static TypeInfo ram_info = {
+static const TypeInfo ram_info = {
     .name          = "memory",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(RamDevice),
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index ce6819e..8f9635f 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -373,7 +373,7 @@ static void iommu_class_init(ObjectClass *klass, void *data)
     dc->props = iommu_properties;
 }
 
-static TypeInfo iommu_info = {
+static const TypeInfo iommu_info = {
     .name          = "iommu",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(IOMMUState),
diff --git a/hw/sun4u.c b/hw/sun4u.c
index cbfd217..3a06d70 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -618,7 +618,7 @@ static void ebus_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_BRIDGE_OTHER;
 }
 
-static TypeInfo ebus_info = {
+static const TypeInfo ebus_info = {
     .name          = "ebus",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(EbusState),
@@ -695,7 +695,7 @@ static void prom_class_init(ObjectClass *klass, void *data)
     dc->props = prom_properties;
 }
 
-static TypeInfo prom_info = {
+static const TypeInfo prom_info = {
     .name          = "openprom",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PROMState),
@@ -752,7 +752,7 @@ static void ram_class_init(ObjectClass *klass, void *data)
     dc->props = ram_properties;
 }
 
-static TypeInfo ram_info = {
+static const TypeInfo ram_info = {
     .name          = "memory",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(RamDevice),
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 49a4177..f0ab8a8 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -255,7 +255,7 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data)
     k->bus_type = TYPE_SYSTEM_BUS;
 }
 
-static TypeInfo sysbus_device_type_info = {
+static const TypeInfo sysbus_device_type_info = {
     .name = TYPE_SYS_BUS_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(SysBusDevice),
diff --git a/hw/tcx.c b/hw/tcx.c
index 185588b..0ce2952 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -716,7 +716,7 @@ static void tcx_class_init(ObjectClass *klass, void *data)
     dc->props = tcx_properties;
 }
 
-static TypeInfo tcx_info = {
+static const TypeInfo tcx_info = {
     .name          = "SUNW,tcx",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(TCXState),
diff --git a/hw/tmp105.c b/hw/tmp105.c
index 9c67e64..0ade4eb 100644
--- a/hw/tmp105.c
+++ b/hw/tmp105.c
@@ -239,7 +239,7 @@ static void tmp105_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_tmp105;
 }
 
-static TypeInfo tmp105_info = {
+static const TypeInfo tmp105_info = {
     .name          = "tmp105",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TMP105State),
diff --git a/hw/tosa.c b/hw/tosa.c
index 6ee4693..7048b79 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -270,7 +270,7 @@ static void tosa_dac_class_init(ObjectClass *klass, void *data)
     k->send = tosa_dac_send;
 }
 
-static TypeInfo tosa_dac_info = {
+static const TypeInfo tosa_dac_info = {
     .name          = "tosa_dac",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(TosaDACState),
@@ -285,7 +285,7 @@ static void tosa_ssp_class_init(ObjectClass *klass, void *data)
     k->transfer = tosa_ssp_tansfer;
 }
 
-static TypeInfo tosa_ssp_info = {
+static const TypeInfo tosa_ssp_info = {
     .name          = "tosa-ssp",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(SSISlave),
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 990d506..7d05b31 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -798,7 +798,7 @@ static void tusb6010_class_init(ObjectClass *klass, void *data)
     dc->reset = tusb6010_reset;
 }
 
-static TypeInfo tusb6010_info = {
+static const TypeInfo tusb6010_info = {
     .name          = "tusb6010",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(TUSBState),
diff --git a/hw/twl92230.c b/hw/twl92230.c
index c71e4a2..70d9b03 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -867,7 +867,7 @@ static void twl92230_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_menelaus;
 }
 
-static TypeInfo twl92230_info = {
+static const TypeInfo twl92230_info = {
     .name          = "twl92230",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(MenelausState),
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 180d1d7..2dc7675 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -628,7 +628,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data)
     k->props    = usb_props;
 }
 
-static TypeInfo usb_device_type_info = {
+static const TypeInfo usb_device_type_info = {
     .name = TYPE_USB_DEVICE,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(USBDevice),
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index b669601..b8c79b8 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -684,7 +684,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data)
     k->set_interface  = usb_audio_set_interface;
 }
 
-static TypeInfo usb_audio_info = {
+static const TypeInfo usb_audio_info = {
     .name          = "usb-audio",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBAudioState),
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index a0d7a88..adbf9d4 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -555,7 +555,7 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_bt;
 }
 
-static TypeInfo bt_info = {
+static const TypeInfo bt_info = {
     .name          = "usb-bt-dongle",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(struct USBBtState),
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index b4ace04..29b6481 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -657,7 +657,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
     dc->props = usb_tablet_properties;
 }
 
-static TypeInfo usb_tablet_info = {
+static const TypeInfo usb_tablet_info = {
     .name          = "usb-tablet",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHIDState),
@@ -676,7 +676,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_ptr;
 }
 
-static TypeInfo usb_mouse_info = {
+static const TypeInfo usb_mouse_info = {
     .name          = "usb-mouse",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHIDState),
@@ -695,7 +695,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_kbd;
 }
 
-static TypeInfo usb_keyboard_info = {
+static const TypeInfo usb_keyboard_info = {
     .name          = "usb-kbd",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHIDState),
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 470fbbb..79f2f46 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -568,7 +568,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_hub;
 }
 
-static TypeInfo hub_info = {
+static const TypeInfo hub_info = {
     .name          = "usb-hub",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHubState),
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 1c54863..9dede4c 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1433,7 +1433,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data)
     dc->props = net_properties;
 }
 
-static TypeInfo net_info = {
+static const TypeInfo net_info = {
     .name          = "usb-net",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBNetState),
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 20cf533..47ac8c9 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -600,7 +600,7 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data)
     dc->props = serial_properties;
 }
 
-static TypeInfo serial_info = {
+static const TypeInfo serial_info = {
     .name          = "usb-serial",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBSerialState),
@@ -628,7 +628,7 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data)
     dc->props = braille_properties;
 }
 
-static TypeInfo braille_info = {
+static const TypeInfo braille_info = {
     .name          = "usb-braille",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBSerialState),
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index f26bb34..979a473 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1322,7 +1322,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data)
     dc->props = ccid_properties;
 }
 
-static TypeInfo ccid_info = {
+static const TypeInfo ccid_info = {
     .name          = CCID_DEV_NAME,
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBCCIDState),
@@ -1338,7 +1338,7 @@ static void ccid_card_class_init(ObjectClass *klass, void *data)
     k->props = ccid_props;
 }
 
-static TypeInfo ccid_card_type_info = {
+static const TypeInfo ccid_card_type_info = {
     .name = TYPE_CCID_CARD,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(CCIDCardState),
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 5025597..1b87352 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -716,7 +716,7 @@ static void usb_msd_class_initfn(ObjectClass *klass, void *data)
     dc->props = msd_properties;
 }
 
-static TypeInfo msd_info = {
+static const TypeInfo msd_info = {
     .name          = "usb-storage",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(MSDState),
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 9a00889..d904d1a 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -757,7 +757,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_uas;
 }
 
-static TypeInfo uas_info = {
+static const TypeInfo uas_info = {
     .name          = "usb-uas",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(UASDevice),
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 9ab368a..ab9fa2e 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -366,7 +366,7 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_usb_wacom;
 }
 
-static TypeInfo wacom_info = {
+static const TypeInfo wacom_info = {
     .name          = "usb-wacom-tablet",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBWacomState),
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 29bafa6..6a2f5f8 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1909,7 +1909,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data)
     dc->props = ohci_pci_properties;
 }
 
-static TypeInfo ohci_pci_info = {
+static const TypeInfo ohci_pci_info = {
     .name          = "pci-ohci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(OHCIPCIState),
@@ -1932,7 +1932,7 @@ static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
     dc->props = ohci_sysbus_properties;
 }
 
-static TypeInfo ohci_sysbus_info = {
+static const TypeInfo ohci_sysbus_info = {
     .name          = "sysbus-ohci",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(OHCISysBusState),
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 9132920..92f2eee 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3182,7 +3182,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     k->no_hotplug   = 1;
 }
 
-static TypeInfo xhci_info = {
+static const TypeInfo xhci_info = {
     .name          = "nec-usb-xhci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(XHCIState),
diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c
index 340c21a..172aecb 100644
--- a/hw/usb/host-bsd.c
+++ b/hw/usb/host-bsd.c
@@ -407,7 +407,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
     uc->handle_destroy = usb_host_handle_destroy;
 }
 
-static TypeInfo usb_host_dev_info = {
+static const TypeInfo usb_host_dev_info = {
     .name          = "usb-host",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHostDevice),
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 669fbd2..e8e6a42 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1534,7 +1534,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data)
     dc->props = usb_host_dev_properties;
 }
 
-static TypeInfo usb_host_dev_info = {
+static const TypeInfo usb_host_dev_info = {
     .name          = "usb-host",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHostDevice),
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index f1bf84c..8c0ead0 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2341,7 +2341,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
     dc->props          = usbredir_properties;
 }
 
-static TypeInfo usbredir_dev_info = {
+static const TypeInfo usbredir_dev_info = {
     .name          = "usb-redir",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBRedirDevice),
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 1f4d669..9d99159 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -119,7 +119,7 @@ static void versatile_pci_host_class_init(ObjectClass *klass, void *data)
     k->class_id = PCI_CLASS_PROCESSOR_CO;
 }
 
-static TypeInfo versatile_pci_host_info = {
+static const TypeInfo versatile_pci_host_info = {
     .name          = "versatile_pci_host",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIDevice),
@@ -133,7 +133,7 @@ static void pci_vpb_class_init(ObjectClass *klass, void *data)
     sdc->init = pci_vpb_init;
 }
 
-static TypeInfo pci_vpb_info = {
+static const TypeInfo pci_vpb_info = {
     .name          = "versatile_pci",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PCIVPBState),
@@ -147,7 +147,7 @@ static void pci_realview_class_init(ObjectClass *klass, void *data)
     sdc->init = pci_realview_init;
 }
 
-static TypeInfo pci_realview_info = {
+static const TypeInfo pci_realview_info = {
     .name          = "realview_pci",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(PCIVPBState),
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 5e89e74..bf72ebb 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -386,7 +386,7 @@ static void vpb_sic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_vpb_sic;
 }
 
-static TypeInfo vpb_sic_info = {
+static const TypeInfo vpb_sic_info = {
     .name          = "versatilepb_sic",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(vpb_sic_state),
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index cbe7b05..762e45a 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -86,7 +86,7 @@ static void vga_class_initfn(ObjectClass *klass, void *data)
     dc->props = vga_isa_properties;
 }
 
-static TypeInfo vga_info = {
+static const TypeInfo vga_info = {
     .name          = "isa-vga",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISAVGAState),
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 87c7c06..c491af2 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -200,7 +200,7 @@ static void vga_class_init(ObjectClass *klass, void *data)
     dc->props = vga_pci_properties;
 }
 
-static TypeInfo vga_info = {
+static const TypeInfo vga_info = {
     .name          = "VGA",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIVGAState),
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 002b028..46072a0 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -142,7 +142,7 @@ static void virtconsole_class_init(ObjectClass *klass, void *data)
     dc->props = virtconsole_properties;
 }
 
-static TypeInfo virtconsole_info = {
+static const TypeInfo virtconsole_info = {
     .name          = "virtconsole",
     .parent        = TYPE_VIRTIO_SERIAL_PORT,
     .instance_size = sizeof(VirtConsole),
@@ -166,7 +166,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
     dc->props = virtserialport_properties;
 }
 
-static TypeInfo virtserialport_info = {
+static const TypeInfo virtserialport_info = {
     .name          = "virtserialport",
     .parent        = TYPE_VIRTIO_SERIAL_PORT,
     .instance_size = sizeof(VirtConsole),
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c7f0c4d..08d2d1b 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -961,7 +961,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_blk_properties;
 }
 
-static TypeInfo virtio_blk_info = {
+static const TypeInfo virtio_blk_info = {
     .name          = "virtio-blk-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
@@ -995,7 +995,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_net_properties;
 }
 
-static TypeInfo virtio_net_info = {
+static const TypeInfo virtio_net_info = {
     .name          = "virtio-net-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
@@ -1026,7 +1026,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_serial_properties;
 }
 
-static TypeInfo virtio_serial_info = {
+static const TypeInfo virtio_serial_info = {
     .name          = "virtio-serial-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
@@ -1054,7 +1054,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_balloon_properties;
 }
 
-static TypeInfo virtio_balloon_info = {
+static const TypeInfo virtio_balloon_info = {
     .name          = "virtio-balloon-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
@@ -1097,7 +1097,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_rng_properties;
 }
 
-static TypeInfo virtio_rng_info = {
+static const TypeInfo virtio_rng_info = {
     .name          = "virtio-rng-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
@@ -1155,7 +1155,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
     dc->props = virtio_scsi_properties;
 }
 
-static TypeInfo virtio_scsi_info = {
+static const TypeInfo virtio_scsi_info = {
     .name          = "virtio-scsi-pci",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VirtIOPCIProxy),
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 7272bfd..aa7d0d7 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -1058,7 +1058,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
     k->props = virtser_props;
 }
 
-static TypeInfo virtio_serial_port_type_info = {
+static const TypeInfo virtio_serial_port_type_info = {
     .name = TYPE_VIRTIO_SERIAL_PORT,
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(VirtIOSerialPort),
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index 004d098..b9afc2c 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -286,7 +286,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data)
     dc->props = vmmouse_properties;
 }
 
-static TypeInfo vmmouse_info = {
+static const TypeInfo vmmouse_info = {
     .name          = "vmmouse",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(VMMouseState),
diff --git a/hw/vmport.c b/hw/vmport.c
index 7d42523..faead3a 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -155,7 +155,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data)
     dc->no_user = 1;
 }
 
-static TypeInfo vmport_info = {
+static const TypeInfo vmport_info = {
     .name          = "vmport",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(VMPortState),
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index b0e772f..62771bb 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1244,7 +1244,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data)
     dc->props = vga_vmware_properties;
 }
 
-static TypeInfo vmsvga_info = {
+static const TypeInfo vmsvga_info = {
     .name          = "vmware-svga",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(struct pci_vmsvga_state_s),
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index d3469d4..2d8e398 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -284,7 +284,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data)
     dc->desc = "AC97";
 }
 
-static TypeInfo via_ac97_info = {
+static const TypeInfo via_ac97_info = {
     .name          = "VT82C686B_AC97",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VT686AC97State),
@@ -325,7 +325,7 @@ static void via_mc97_class_init(ObjectClass *klass, void *data)
     dc->desc = "MC97";
 }
 
-static TypeInfo via_mc97_info = {
+static const TypeInfo via_mc97_info = {
     .name          = "VT82C686B_MC97",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VT686MC97State),
@@ -404,7 +404,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data)
     dc->props = via_pm_properties;
 }
 
-static TypeInfo via_pm_info = {
+static const TypeInfo via_pm_info = {
     .name          = "VT82C686B_PM",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VT686PMState),
@@ -471,7 +471,7 @@ static void via_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_via;
 }
 
-static TypeInfo via_info = {
+static const TypeInfo via_info = {
     .name          = "VT82C686B",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VT82C686BState),
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 54f0665..37ce362 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -439,7 +439,7 @@ static void i6300esb_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_i6300esb;
 }
 
-static TypeInfo i6300esb_info = {
+static const TypeInfo i6300esb_info = {
     .name          = "i6300esb",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(I6300State),
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index 4475f7b..599a86f 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -129,7 +129,7 @@ static void wdt_ib700_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_ib700;
 }
 
-static TypeInfo wdt_ib700_info = {
+static const TypeInfo wdt_ib700_info = {
     .name          = "ib700",
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(IB700State),
diff --git a/hw/wm8750.c b/hw/wm8750.c
index 44f138f..bb85064 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -701,7 +701,7 @@ static void wm8750_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_wm8750;
 }
 
-static TypeInfo wm8750_info = {
+static const TypeInfo wm8750_info = {
     .name          = "wm8750",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(WM8750State),
diff --git a/hw/xen_apic.c b/hw/xen_apic.c
index a6632fe..1d1d15c 100644
--- a/hw/xen_apic.c
+++ b/hw/xen_apic.c
@@ -80,7 +80,7 @@ static void xen_apic_class_init(ObjectClass *klass, void *data)
     k->external_nmi = xen_apic_external_nmi;
 }
 
-static TypeInfo xen_apic_info = {
+static const TypeInfo xen_apic_info = {
     .name = "xen-apic",
     .parent = TYPE_APIC_COMMON,
     .instance_size = sizeof(APICCommonState),
diff --git a/hw/xen_platform.c b/hw/xen_platform.c
index e7611bb..ca66047 100644
--- a/hw/xen_platform.c
+++ b/hw/xen_platform.c
@@ -420,7 +420,7 @@ static void xen_platform_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_xen_platform;
 }
 
-static TypeInfo xen_platform_info = {
+static const TypeInfo xen_platform_info = {
     .name          = "xen-platform",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIXenPlatformState),
diff --git a/hw/xen_pt.c b/hw/xen_pt.c
index 6fd8433..9db5f6e 100644
--- a/hw/xen_pt.c
+++ b/hw/xen_pt.c
@@ -829,7 +829,7 @@ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
     dc->props = xen_pci_passthrough_properties;
 };
 
-static TypeInfo xen_pci_passthrough_info = {
+static const TypeInfo xen_pci_passthrough_info = {
     .name = "xen-pci-passthrough",
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(XenPCIPassthroughState),
diff --git a/hw/xgmac.c b/hw/xgmac.c
index 9639b61..00dae77 100644
--- a/hw/xgmac.c
+++ b/hw/xgmac.c
@@ -418,7 +418,7 @@ static void xgmac_enet_class_init(ObjectClass *klass, void *data)
     dc->props = xgmac_properties;
 }
 
-static TypeInfo xgmac_enet_info = {
+static const TypeInfo xgmac_enet_info = {
     .name          = "xgmac",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct XgmacState),
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index ce02764..d0ee566 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -503,7 +503,7 @@ static void axidma_class_init(ObjectClass *klass, void *data)
     ssc->push = axidma_push;
 }
 
-static TypeInfo axidma_info = {
+static const TypeInfo axidma_info = {
     .name          = "xlnx.axi-dma",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct XilinxAXIDMA),
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 09e49b0..51c2896 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -893,7 +893,7 @@ static void xilinx_enet_class_init(ObjectClass *klass, void *data)
     ssc->push = axienet_stream_push;
 }
 
-static TypeInfo xilinx_enet_info = {
+static const TypeInfo xilinx_enet_info = {
     .name          = "xlnx.axi-ethernet",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct XilinxAXIEnet),
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 4de4a53..2254851 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -243,7 +243,7 @@ static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
     dc->props = xilinx_ethlite_properties;
 }
 
-static TypeInfo xilinx_ethlite_info = {
+static const TypeInfo xilinx_ethlite_info = {
     .name          = "xlnx.xps-ethernetlite",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct xlx_ethlite),
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 7765079..0c34149 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -175,7 +175,7 @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
     dc->props = xilinx_intc_properties;
 }
 
-static TypeInfo xilinx_intc_info = {
+static const TypeInfo xilinx_intc_info = {
     .name          = "xlnx.xps-intc",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct xlx_pic),
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
index 77f9178..be581c2 100644
--- a/hw/xilinx_spi.c
+++ b/hw/xilinx_spi.c
@@ -370,7 +370,7 @@ static void xilinx_spi_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_xilinx_spi;
 }
 
-static TypeInfo xilinx_spi_info = {
+static const TypeInfo xilinx_spi_info = {
     .name           = "xlnx.xps-spi",
     .parent         = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(XilinxSPI),
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 69294bb..aa162ef 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -240,7 +240,7 @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
     dc->props = xilinx_timer_properties;
 }
 
-static TypeInfo xilinx_timer_info = {
+static const TypeInfo xilinx_timer_info = {
     .name          = "xlnx.xps-timer",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(struct timerblock),
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index abd256a..9963982 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -216,7 +216,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
     sdc->init = xilinx_uartlite_init;
 }
 
-static TypeInfo xilinx_uartlite_info = {
+static const TypeInfo xilinx_uartlite_info = {
     .name          = "xlnx.xps-uartlite",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof (struct xlx_uartlite),
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 2dcd46b..7f00bc8 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -193,7 +193,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
     dc->props = xio3130_downstream_properties;
 }
 
-static TypeInfo xio3130_downstream_info = {
+static const TypeInfo xio3130_downstream_info = {
     .name          = "xio3130-downstream",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIESlot),
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 713caf2..70b15d3 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -167,7 +167,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
     dc->props = xio3130_upstream_properties;
 }
 
-static TypeInfo xio3130_upstream_info = {
+static const TypeInfo xio3130_upstream_info = {
     .name          = "x3130-upstream",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIEPort),
diff --git a/hw/z2.c b/hw/z2.c
index 09b0368..496e47d 100644
--- a/hw/z2.c
+++ b/hw/z2.c
@@ -185,7 +185,7 @@ static void zipit_lcd_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_zipit_lcd_state;
 }
 
-static TypeInfo zipit_lcd_info = {
+static const TypeInfo zipit_lcd_info = {
     .name          = "zipit-lcd",
     .parent        = TYPE_SSI_SLAVE,
     .instance_size = sizeof(ZipitLCD),
@@ -288,7 +288,7 @@ static void aer915_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_aer915_state;
 }
 
-static TypeInfo aer915_info = {
+static const TypeInfo aer915_info = {
     .name          = "aer915",
     .parent        = TYPE_I2C_SLAVE,
     .instance_size = sizeof(AER915State),
diff --git a/hw/zaurus.c b/hw/zaurus.c
index d77b34e..2defe3b 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -236,7 +236,7 @@ static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
     dc->props = scoop_sysbus_properties;
 }
 
-static TypeInfo scoop_sysbus_info = {
+static const TypeInfo scoop_sysbus_info = {
     .name          = "scoop",
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ScoopInfo),
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 143a7cf..4d6f8d9 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -521,7 +521,7 @@ static void zynq_slcr_class_init(ObjectClass *klass, void *data)
     dc->reset = zynq_slcr_reset;
 }
 
-static TypeInfo zynq_slcr_info = {
+static const TypeInfo zynq_slcr_info = {
     .class_init = zynq_slcr_class_init,
     .name  = "xilinx,zynq_slcr",
     .parent = TYPE_SYS_BUS_DEVICE,
diff --git a/include/qom/object.h b/include/qom/object.h
index abe9691..d43b289 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -65,7 +65,7 @@ typedef struct InterfaceInfo InterfaceInfo;
  *     int reg0, reg1, reg2;
  * } MyDevice;
  *
- * static TypeInfo my_device_info = {
+ * static const TypeInfo my_device_info = {
  *     .name = TYPE_MY_DEVICE,
  *     .parent = TYPE_DEVICE,
  *     .instance_size = sizeof(MyDevice),
@@ -138,7 +138,7 @@ typedef struct InterfaceInfo InterfaceInfo;
  *     dc->reset = my_device_reset;
  * }
  *
- * static TypeInfo my_device_info = {
+ * static const TypeInfo my_device_info = {
  *     .name = TYPE_MY_DEVICE,
  *     .parent = TYPE_DEVICE,
  *     .instance_size = sizeof(MyDevice),
@@ -163,7 +163,7 @@ typedef struct InterfaceInfo InterfaceInfo;
  *     void (*frobnicate) (MyDevice *obj);
  * } MyDeviceClass;
  *
- * static TypeInfo my_device_info = {
+ * static const TypeInfo my_device_info = {
  *     .name = TYPE_MY_DEVICE,
  *     .parent = TYPE_DEVICE,
  *     .instance_size = sizeof(MyDevice),
diff --git a/qom/container.c b/qom/container.c
index 5270a5e..62b1648 100644
--- a/qom/container.c
+++ b/qom/container.c
@@ -14,7 +14,7 @@
 #include "qemu/module.h"
 #include <assert.h>
 
-static TypeInfo container_info = {
+static const TypeInfo container_info = {
     .name          = "container",
     .instance_size = sizeof(Object),
     .parent        = TYPE_OBJECT,
commit 63e3555e80c31776285accbb4d0c14ae91c457dc
Merge: 52a71bf a6308bc
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Thu Jan 10 21:52:28 2013 +0100

    Merge branch 'master' of git://git.qemu.org/qemu into prep-up
    
    Conflicts:
    	hw/Makefile.objs
    	hw/ppc_prep.c
    
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>

diff --cc MAINTAINERS
index 950270f,cf39e5a..2991e1d
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@@ -373,8 -396,20 +396,21 @@@ L: qemu-ppc at nongnu.or
  S: Odd Fixes
  F: hw/ppc_prep.c
  F: hw/prep_pci.[hc]
 +F: hw/pc87312.[hc]
  
+ sPAPR
+ M: David Gibson <david at gibson.dropbear.id.au>
+ M: Alexander Graf <agraf at suse.de>
+ L: qemu-ppc at nongnu.org
+ S: Supported
+ F: hw/spapr*
+ 
+ virtex_ml507
+ M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
+ L: qemu-ppc at nongnu.org
+ S: Odd Fixes
+ F: hw/virtex_ml507.c
+ 
  SH4 Machines
  ------------
  R2D
diff --cc hw/Makefile.objs
index aab0a46,6b8a68c..d867184
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@@ -1,139 -1,147 +1,148 @@@
- hw-obj-y = usb/ ide/
- hw-obj-y += loader.o
- hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
- hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
- hw-obj-y += fw_cfg.o
- hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
- hw-obj-$(CONFIG_PCI) += msix.o msi.o
- hw-obj-$(CONFIG_PCI) += shpc.o
- hw-obj-$(CONFIG_PCI) += slotid_cap.o
- hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
- hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
- hw-obj-y += watchdog.o
- hw-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
- hw-obj-$(CONFIG_ECC) += ecc.o
- hw-obj-$(CONFIG_NAND) += nand.o
- hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
- hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
- 
- hw-obj-$(CONFIG_M48T59) += m48t59.o
- hw-obj-$(CONFIG_ESCC) += escc.o
- hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
- 
- hw-obj-$(CONFIG_SERIAL) += serial.o
- hw-obj-$(CONFIG_PARALLEL) += parallel.o
- hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
- hw-obj-$(CONFIG_PCSPK) += pcspk.o
- hw-obj-$(CONFIG_PCKBD) += pckbd.o
- hw-obj-$(CONFIG_FDC) += fdc.o
- hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
- hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
- hw-obj-$(CONFIG_DMA) += dma.o
- hw-obj-$(CONFIG_I82374) += i82374.o
- hw-obj-$(CONFIG_HPET) += hpet.o
- hw-obj-$(CONFIG_APPLESMC) += applesmc.o
- hw-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
- hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
- hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+ # core qdev-related obj files, also used by *-user:
+ hw-core-obj-y += qdev.o qdev-properties.o
+ # irq.o needed for qdev GPIO handling:
+ hw-core-obj-y += irq.o
+ 
+ 
+ common-obj-y = usb/ ide/ pci/
+ common-obj-y += loader.o
+ common-obj-$(CONFIG_VIRTIO) += virtio-console.o
+ common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
+ common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+ common-obj-y += fw_cfg.o
+ common-obj-$(CONFIG_PCI) += pci_bridge_dev.o
+ common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
+ common-obj-$(CONFIG_PCI) += i82801b11.o
+ common-obj-y += watchdog.o
+ common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
+ common-obj-$(CONFIG_ECC) += ecc.o
+ common-obj-$(CONFIG_NAND) += nand.o
+ common-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
+ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+ 
+ common-obj-$(CONFIG_M48T59) += m48t59.o
+ common-obj-$(CONFIG_ESCC) += escc.o
+ common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
+ 
+ common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o
+ common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o
+ common-obj-$(CONFIG_PARALLEL) += parallel.o
+ common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
+ common-obj-$(CONFIG_PCSPK) += pcspk.o
+ common-obj-$(CONFIG_PCKBD) += pckbd.o
+ common-obj-$(CONFIG_FDC) += fdc.o
+ common-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o acpi_ich9.o smbus_ich9.o
+ common-obj-$(CONFIG_APM) += pm_smbus.o apm.o
+ common-obj-$(CONFIG_DMA) += dma.o
+ common-obj-$(CONFIG_I82374) += i82374.o
+ common-obj-$(CONFIG_HPET) += hpet.o
+ common-obj-$(CONFIG_APPLESMC) += applesmc.o
+ common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
+ common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
+ common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
+ common-obj-y += fifo.o
+ common-obj-y += pam.o
+ 
+ extra-obj-y += pci/
  
  # PPC devices
- hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
- hw-obj-$(CONFIG_I82378) += i82378.o
- hw-obj-$(CONFIG_PC87312) += pc87312.o
+ common-obj-$(CONFIG_PREP_PCI) += prep_pci.o
+ common-obj-$(CONFIG_I82378) += i82378.o
++common-obj-$(CONFIG_PC87312) += pc87312.o
  # Mac shared devices
- hw-obj-$(CONFIG_MACIO) += macio.o
- hw-obj-$(CONFIG_CUDA) += cuda.o
- hw-obj-$(CONFIG_ADB) += adb.o
- hw-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
- hw-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
+ common-obj-$(CONFIG_MACIO) += macio.o
+ common-obj-$(CONFIG_CUDA) += cuda.o
+ common-obj-$(CONFIG_ADB) += adb.o
+ common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
+ common-obj-$(CONFIG_MAC_DBDMA) += mac_dbdma.o
  # OldWorld PowerMac
- hw-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
- hw-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
+ common-obj-$(CONFIG_HEATHROW_PIC) += heathrow_pic.o
+ common-obj-$(CONFIG_GRACKLE_PCI) += grackle_pci.o
  # NewWorld PowerMac
- hw-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
- hw-obj-$(CONFIG_DEC_PCI) += dec_pci.o
+ common-obj-$(CONFIG_UNIN_PCI) += unin_pci.o
+ common-obj-$(CONFIG_DEC_PCI) += dec_pci.o
  # PowerPC E500 boards
- hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
+ common-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
  
  # MIPS devices
- hw-obj-$(CONFIG_PIIX4) += piix4.o
- hw-obj-$(CONFIG_G364FB) += g364fb.o
- hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
+ common-obj-$(CONFIG_PIIX4) += piix4.o
+ common-obj-$(CONFIG_G364FB) += g364fb.o
+ common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
  
  # Xilinx devices
- hw-obj-$(CONFIG_XILINX) += xilinx_intc.o
- hw-obj-$(CONFIG_XILINX) += xilinx_timer.o
- hw-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
- hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
- hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
- hw-obj-$(CONFIG_XILINX_AXI) += stream.o
+ common-obj-$(CONFIG_XILINX) += xilinx_intc.o
+ common-obj-$(CONFIG_XILINX) += xilinx_timer.o
+ common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
+ common-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
+ common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
+ common-obj-$(CONFIG_XILINX_AXI) += stream.o
  
  # PKUnity SoC devices
- hw-obj-$(CONFIG_PUV3) += puv3_intc.o
- hw-obj-$(CONFIG_PUV3) += puv3_ost.o
- hw-obj-$(CONFIG_PUV3) += puv3_gpio.o
- hw-obj-$(CONFIG_PUV3) += puv3_pm.o
- hw-obj-$(CONFIG_PUV3) += puv3_dma.o
+ common-obj-$(CONFIG_PUV3) += puv3_intc.o
+ common-obj-$(CONFIG_PUV3) += puv3_ost.o
+ common-obj-$(CONFIG_PUV3) += puv3_gpio.o
+ common-obj-$(CONFIG_PUV3) += puv3_pm.o
+ common-obj-$(CONFIG_PUV3) += puv3_dma.o
  
  # ARM devices
- hw-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
- hw-obj-$(CONFIG_PL011) += pl011.o
- hw-obj-$(CONFIG_PL022) += pl022.o
- hw-obj-$(CONFIG_PL031) += pl031.o
- hw-obj-$(CONFIG_PL041) += pl041.o lm4549.o
- hw-obj-$(CONFIG_PL050) += pl050.o
- hw-obj-$(CONFIG_PL061) += pl061.o
- hw-obj-$(CONFIG_PL080) += pl080.o
- hw-obj-$(CONFIG_PL110) += pl110.o
- hw-obj-$(CONFIG_PL181) += pl181.o
- hw-obj-$(CONFIG_PL190) += pl190.o
- hw-obj-$(CONFIG_PL310) += arm_l2x0.o
- hw-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o
- hw-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
- hw-obj-$(CONFIG_CADENCE) += cadence_uart.o
- hw-obj-$(CONFIG_CADENCE) += cadence_ttc.o
- hw-obj-$(CONFIG_CADENCE) += cadence_gem.o
- hw-obj-$(CONFIG_XGMAC) += xgmac.o
+ common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
+ common-obj-$(CONFIG_PL011) += pl011.o
+ common-obj-$(CONFIG_PL022) += pl022.o
+ common-obj-$(CONFIG_PL031) += pl031.o
+ common-obj-$(CONFIG_PL041) += pl041.o lm4549.o
+ common-obj-$(CONFIG_PL050) += pl050.o
+ common-obj-$(CONFIG_PL061) += pl061.o
+ common-obj-$(CONFIG_PL080) += pl080.o
+ common-obj-$(CONFIG_PL110) += pl110.o
+ common-obj-$(CONFIG_PL181) += pl181.o
+ common-obj-$(CONFIG_PL190) += pl190.o
+ common-obj-$(CONFIG_PL310) += arm_l2x0.o
+ common-obj-$(CONFIG_VERSATILE_PCI) += versatile_pci.o
+ common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
+ common-obj-$(CONFIG_CADENCE) += cadence_uart.o
+ common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
+ common-obj-$(CONFIG_CADENCE) += cadence_gem.o
+ common-obj-$(CONFIG_XGMAC) += xgmac.o
  
  # PCI watchdog devices
- hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
- 
- hw-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
+ common-obj-$(CONFIG_PCI) += wdt_i6300esb.o
  
  # PCI network cards
- hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
- hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
- hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
- hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
- hw-obj-$(CONFIG_E1000_PCI) += e1000.o
- hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
- 
- hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
- hw-obj-$(CONFIG_LAN9118) += lan9118.o
- hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
- hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
+ common-obj-$(CONFIG_NE2000_PCI) += ne2000.o
+ common-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
+ common-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
+ common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
+ common-obj-$(CONFIG_E1000_PCI) += e1000.o
+ common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
+ 
+ common-obj-$(CONFIG_SMC91C111) += smc91c111.o
+ common-obj-$(CONFIG_LAN9118) += lan9118.o
+ common-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
+ common-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o
  
  # SCSI layer
- hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
- hw-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o
- hw-obj-$(CONFIG_ESP) += esp.o
- hw-obj-$(CONFIG_ESP_PCI) += esp-pci.o
+ common-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
+ common-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o
+ common-obj-$(CONFIG_ESP) += esp.o
+ common-obj-$(CONFIG_ESP_PCI) += esp-pci.o
  
- hw-obj-y += sysbus.o isa-bus.o
- hw-obj-y += qdev-addr.o
+ common-obj-y += sysbus.o isa-bus.o
+ common-obj-y += qdev-addr.o
  
  # VGA
- hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
- hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
- hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
- hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
- hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
- hw-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
- 
- hw-obj-$(CONFIG_RC4030) += rc4030.o
- hw-obj-$(CONFIG_DP8393X) += dp8393x.o
- hw-obj-$(CONFIG_DS1225Y) += ds1225y.o
- hw-obj-$(CONFIG_MIPSNET) += mipsnet.o
+ common-obj-$(CONFIG_VGA_PCI) += vga-pci.o
+ common-obj-$(CONFIG_VGA_ISA) += vga-isa.o
+ common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
+ common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
+ common-obj-$(CONFIG_VMMOUSE) += vmmouse.o
+ common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
+ 
+ common-obj-$(CONFIG_RC4030) += rc4030.o
+ common-obj-$(CONFIG_DP8393X) += dp8393x.o
+ common-obj-$(CONFIG_DS1225Y) += ds1225y.o
+ common-obj-$(CONFIG_MIPSNET) += mipsnet.o
+ 
+ common-obj-y += null-machine.o
  
  # Sound
  sound-obj-y =
diff --cc hw/pc87312.c
index b5fa016,0000000..6a17afd
mode 100644,000000..100644
--- a/hw/pc87312.c
+++ b/hw/pc87312.c
@@@ -1,386 -1,0 +1,387 @@@
 +/*
 + * QEMU National Semiconductor PC87312 (Super I/O)
 + *
 + * Copyright (c) 2010-2012 Herve Poussineau
 + * Copyright (c) 2011-2012 Andreas Färber
 + *
 + * 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 "pc87312.h"
- #include "blockdev.h"
- #include "sysemu.h"
++#include "sysemu/blockdev.h"
++#include "sysemu/sysemu.h"
++#include "char/char.h"
 +#include "trace.h"
 +
 +
 +#define REG_FER 0
 +#define REG_FAR 1
 +#define REG_PTR 2
 +
 +#define FER regs[REG_FER]
 +#define FAR regs[REG_FAR]
 +#define PTR regs[REG_PTR]
 +
 +#define FER_PARALLEL_EN   0x01
 +#define FER_UART1_EN      0x02
 +#define FER_UART2_EN      0x04
 +#define FER_FDC_EN        0x08
 +#define FER_FDC_4         0x10
 +#define FER_FDC_ADDR      0x20
 +#define FER_IDE_EN        0x40
 +#define FER_IDE_ADDR      0x80
 +
 +#define FAR_PARALLEL_ADDR 0x03
 +#define FAR_UART1_ADDR    0x0C
 +#define FAR_UART2_ADDR    0x30
 +#define FAR_UART_3_4      0xC0
 +
 +#define PTR_POWER_DOWN    0x01
 +#define PTR_CLOCK_DOWN    0x02
 +#define PTR_PWDN          0x04
 +#define PTR_IRQ_5_7       0x08
 +#define PTR_UART1_TEST    0x10
 +#define PTR_UART2_TEST    0x20
 +#define PTR_LOCK_CONF     0x40
 +#define PTR_EPP_MODE      0x80
 +
 +
 +/* Parallel port */
 +
 +static inline bool is_parallel_enabled(PC87312State *s)
 +{
 +    return s->FER & FER_PARALLEL_EN;
 +}
 +
 +static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 };
 +
 +static inline uint32_t get_parallel_iobase(PC87312State *s)
 +{
 +    return parallel_base[s->FAR & FAR_PARALLEL_ADDR];
 +}
 +
 +static const uint32_t parallel_irq[] = { 5, 7, 5, 0 };
 +
 +static inline uint32_t get_parallel_irq(PC87312State *s)
 +{
 +    int idx;
 +    idx = (s->FAR & FAR_PARALLEL_ADDR);
 +    if (idx == 0) {
 +        return (s->PTR & PTR_IRQ_5_7) ? 7 : 5;
 +    } else {
 +        return parallel_irq[idx];
 +    }
 +}
 +
 +static inline bool is_parallel_epp(PC87312State *s)
 +{
 +    return s->PTR & PTR_EPP_MODE;
 +}
 +
 +
 +/* UARTs */
 +
 +static const uint32_t uart_base[2][4] = {
 +    { 0x3e8, 0x338, 0x2e8, 0x220 },
 +    { 0x2e8, 0x238, 0x2e0, 0x228 }
 +};
 +
 +static inline uint32_t get_uart_iobase(PC87312State *s, int i)
 +{
 +    int idx;
 +    idx = (s->FAR >> (2 * i + 2)) & 0x3;
 +    if (idx == 0) {
 +        return 0x3f8;
 +    } else if (idx == 1) {
 +        return 0x2f8;
 +    } else {
 +        return uart_base[idx & 1][(s->FAR & FAR_UART_3_4) >> 6];
 +    }
 +}
 +
 +static inline uint32_t get_uart_irq(PC87312State *s, int i)
 +{
 +    int idx;
 +    idx = (s->FAR >> (2 * i + 2)) & 0x3;
 +    return (idx & 1) ? 3 : 4;
 +}
 +
 +static inline bool is_uart_enabled(PC87312State *s, int i)
 +{
 +    return s->FER & (FER_UART1_EN << i);
 +}
 +
 +
 +/* Floppy controller */
 +
 +static inline bool is_fdc_enabled(PC87312State *s)
 +{
 +    return s->FER & FER_FDC_EN;
 +}
 +
 +static inline uint32_t get_fdc_iobase(PC87312State *s)
 +{
 +    return (s->FER & FER_FDC_ADDR) ? 0x370 : 0x3f0;
 +}
 +
 +
 +/* IDE controller */
 +
 +static inline bool is_ide_enabled(PC87312State *s)
 +{
 +    return s->FER & FER_IDE_EN;
 +}
 +
 +static inline uint32_t get_ide_iobase(PC87312State *s)
 +{
 +    return (s->FER & FER_IDE_ADDR) ? 0x170 : 0x1f0;
 +}
 +
 +
 +static void reconfigure_devices(PC87312State *s)
 +{
 +    error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)",
 +                 s->FER, s->FAR, s->PTR);
 +}
 +
 +static void pc87312_soft_reset(PC87312State *s)
 +{
 +    static const uint8_t fer_init[] = {
 +        0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4b, 0x4b,
 +        0x4b, 0x4b, 0x4b, 0x4b, 0x0f, 0x0f, 0x0f, 0x0f,
 +        0x49, 0x49, 0x49, 0x49, 0x07, 0x07, 0x07, 0x07,
 +        0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x08, 0x00,
 +    };
 +    static const uint8_t far_init[] = {
 +        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x00, 0x01,
 +        0x01, 0x09, 0x08, 0x08, 0x10, 0x11, 0x39, 0x24,
 +        0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x39, 0x24,
 +        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x10, 0x10,
 +    };
 +    static const uint8_t ptr_init[] = {
 +        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
 +    };
 +
 +    s->read_id_step = 0;
 +    s->selected_index = REG_FER;
 +
 +    s->FER = fer_init[s->config & 0x1f];
 +    s->FAR = far_init[s->config & 0x1f];
 +    s->PTR = ptr_init[s->config & 0x1f];
 +}
 +
 +static void pc87312_hard_reset(PC87312State *s)
 +{
 +    pc87312_soft_reset(s);
 +}
 +
 +static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 +{
 +    PC87312State *s = opaque;
 +
 +    trace_pc87312_io_write(addr, val);
 +
 +    if ((addr & 1) == 0) {
 +        /* Index register */
 +        s->read_id_step = 2;
 +        s->selected_index = val;
 +    } else {
 +        /* Data register */
 +        if (s->selected_index < 3) {
 +            s->regs[s->selected_index] = val;
 +            reconfigure_devices(s);
 +        }
 +    }
 +}
 +
 +static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr)
 +{
 +    PC87312State *s = opaque;
 +    uint32_t val;
 +
 +    if ((addr & 1) == 0) {
 +        /* Index register */
 +        if (s->read_id_step++ == 0) {
 +            val = 0x88;
 +        } else if (s->read_id_step++ == 1) {
 +            val = 0;
 +        } else {
 +            val = s->selected_index;
 +        }
 +    } else {
 +        /* Data register */
 +        if (s->selected_index < 3) {
 +            val = s->regs[s->selected_index];
 +        } else {
 +            /* Invalid selected index */
 +            val = 0;
 +        }
 +    }
 +
 +    trace_pc87312_io_read(addr, val);
 +    return val;
 +}
 +
 +static int pc87312_post_load(void *opaque, int version_id)
 +{
 +    PC87312State *s = opaque;
 +
 +    reconfigure_devices(s);
 +    return 0;
 +}
 +
 +static void pc87312_reset(DeviceState *d)
 +{
 +    PC87312State *s = PC87312(d);
 +
 +    pc87312_soft_reset(s);
 +}
 +
 +static int pc87312_init(ISADevice *dev)
 +{
 +    PC87312State *s;
 +    DeviceState *d;
 +    ISADevice *isa;
 +    ISABus *bus;
 +    CharDriverState *chr;
 +    DriveInfo *drive;
 +    char name[5];
 +    int i;
 +
 +    s = PC87312(dev);
 +    bus = isa_bus_from_device(dev);
 +    pc87312_hard_reset(s);
 +
 +    if (is_parallel_enabled(s)) {
 +        chr = parallel_hds[0];
 +        if (chr == NULL) {
 +            chr = qemu_chr_new("par0", "null", NULL);
 +        }
 +        isa = isa_create(bus, "isa-parallel");
 +        d = DEVICE(isa);
 +        qdev_prop_set_uint32(d, "index", 0);
 +        qdev_prop_set_uint32(d, "iobase", get_parallel_iobase(s));
 +        qdev_prop_set_uint32(d, "irq", get_parallel_irq(s));
 +        qdev_prop_set_chr(d, "chardev", chr);
 +        qdev_init_nofail(d);
 +        s->parallel.dev = isa;
 +        trace_pc87312_info_parallel(get_parallel_iobase(s),
 +                                    get_parallel_irq(s));
 +    }
 +
 +    for (i = 0; i < 2; i++) {
 +        if (is_uart_enabled(s, i)) {
 +            chr = serial_hds[i];
 +            if (chr == NULL) {
 +                snprintf(name, sizeof(name), "ser%d", i);
 +                chr = qemu_chr_new(name, "null", NULL);
 +            }
 +            isa = isa_create(bus, "isa-serial");
 +            d = DEVICE(isa);
 +            qdev_prop_set_uint32(d, "index", i);
 +            qdev_prop_set_uint32(d, "iobase", get_uart_iobase(s, i));
 +            qdev_prop_set_uint32(d, "irq", get_uart_irq(s, i));
 +            qdev_prop_set_chr(d, "chardev", chr);
 +            qdev_init_nofail(d);
 +            s->uart[i].dev = isa;
 +            trace_pc87312_info_serial(i, get_uart_iobase(s, i),
 +                                      get_uart_irq(s, i));
 +        }
 +    }
 +
 +    if (is_fdc_enabled(s)) {
 +        isa = isa_create(bus, "isa-fdc");
 +        d = DEVICE(isa);
 +        qdev_prop_set_uint32(d, "iobase", get_fdc_iobase(s));
 +        qdev_prop_set_uint32(d, "irq", 6);
 +        drive = drive_get(IF_FLOPPY, 0, 0);
 +        if (drive != NULL) {
 +            qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
 +        }
 +        drive = drive_get(IF_FLOPPY, 0, 1);
 +        if (drive != NULL) {
 +            qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
 +        }
 +        qdev_init_nofail(d);
 +        s->fdc.dev = isa;
 +        trace_pc87312_info_floppy(get_fdc_iobase(s));
 +    }
 +
 +    if (is_ide_enabled(s)) {
 +        isa = isa_create(bus, "isa-ide");
 +        d = DEVICE(isa);
 +        qdev_prop_set_uint32(d, "iobase", get_ide_iobase(s));
 +        qdev_prop_set_uint32(d, "iobase2", get_ide_iobase(s) + 0x206);
 +        qdev_prop_set_uint32(d, "irq", 14);
 +        qdev_init_nofail(d);
 +        s->ide.dev = isa;
 +        trace_pc87312_info_ide(get_ide_iobase(s));
 +    }
 +
 +    register_ioport_write(s->iobase, 2, 1, pc87312_ioport_write, s);
 +    register_ioport_read(s->iobase, 2, 1, pc87312_ioport_read, s);
 +    return 0;
 +}
 +
 +static const VMStateDescription vmstate_pc87312 = {
 +    .name = "pc87312",
 +    .version_id = 1,
 +    .minimum_version_id = 1,
 +    .post_load = pc87312_post_load,
 +    .fields = (VMStateField[]) {
 +        VMSTATE_UINT8(read_id_step, PC87312State),
 +        VMSTATE_UINT8(selected_index, PC87312State),
 +        VMSTATE_UINT8_ARRAY(regs, PC87312State, 3),
 +        VMSTATE_END_OF_LIST()
 +    }
 +};
 +
 +static Property pc87312_properties[] = {
 +    DEFINE_PROP_HEX32("iobase", PC87312State, iobase, 0x398),
 +    DEFINE_PROP_UINT8("config", PC87312State, config, 1),
 +    DEFINE_PROP_END_OF_LIST()
 +};
 +
 +static void pc87312_class_init(ObjectClass *klass, void *data)
 +{
 +    DeviceClass *dc = DEVICE_CLASS(klass);
 +    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
 +
 +    ic->init = pc87312_init;
 +    dc->reset = pc87312_reset;
 +    dc->vmsd = &vmstate_pc87312;
 +    dc->props = pc87312_properties;
 +}
 +
 +static const TypeInfo pc87312_type_info = {
 +    .name          = TYPE_PC87312,
 +    .parent        = TYPE_ISA_DEVICE,
 +    .instance_size = sizeof(PC87312State),
 +    .class_init    = pc87312_class_init,
 +};
 +
 +static void pc87312_register_types(void)
 +{
 +    type_register_static(&pc87312_type_info);
 +}
 +
 +type_init(pc87312_register_types)
diff --cc hw/ppc_prep.c
index 59def90,9c78c86..417583a
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@@ -36,10 -37,9 +37,10 @@@
  #include "ide.h"
  #include "loader.h"
  #include "mc146818rtc.h"
 +#include "pc87312.h"
- #include "blockdev.h"
- #include "arch_init.h"
- #include "exec-memory.h"
+ #include "sysemu/blockdev.h"
+ #include "sysemu/arch_init.h"
+ #include "exec/address-spaces.h"
  
  //#define HARD_DEBUG_PPC_IO
  //#define DEBUG_PPC_IO
commit 7682e8580722f951559f372ba3d2b6170fdbe734
Author: Nickolai Zeldovich <nickolai at csail.mit.edu>
Date:   Mon Jan 7 15:38:39 2013 -0500

    readline: avoid memcpy() of overlapping regions
    
    memcpy() for overlapping regions is undefined behavior; use memmove()
    instead in readline_hist_add().
    
    [Keep tab characters since surrounding code still uses them -- Stefan]
    
    Signed-off-by: Nickolai Zeldovich <nickolai at csail.mit.edu>
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/readline.c b/readline.c
index 5fc9643..a0c9638 100644
--- a/readline.c
+++ b/readline.c
@@ -248,8 +248,8 @@ static void readline_hist_add(ReadLineState *rs, const char *cmdline)
     if (idx == READLINE_MAX_CMDS) {
 	/* Need to get one free slot */
 	free(rs->history[0]);
-	memcpy(rs->history, &rs->history[1],
-	       (READLINE_MAX_CMDS - 1) * sizeof(char *));
+	memmove(rs->history, &rs->history[1],
+	        (READLINE_MAX_CMDS - 1) * sizeof(char *));
 	rs->history[READLINE_MAX_CMDS - 1] = NULL;
 	idx = READLINE_MAX_CMDS - 1;
     }
commit 61993a67128095946ed5df51c3c20748182d8efc
Author: Samuel Seay <lightningth at gmail.com>
Date:   Fri Jan 4 14:35:48 2013 +0000

    PPC: linux-user: Calculate context pointer explicitly
    
    Peter Maydell recommended the change to be more proper. The result was tested
    and shows coming up with the same proper value.
    
    Signed-off-by: Samuel Seay <LightningTH at GMail.com>
    [agraf: change subject]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index c43b8ac..bb08a93 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4614,7 +4614,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     /* Set up registers for signal handler.  */
     env->gpr[1] = newsp;
     env->gpr[3] = signal;
-    env->gpr[4] = (target_ulong) h2g(sc);
+    env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx);
     env->nip = (target_ulong) ka->_sa_handler;
     /* Signal handlers are entered in big-endian mode.  */
     env->msr &= ~MSR_LE;
commit 1b7ce68fb45b97a9eaf71eeb81d2b4f4ea6bf4b2
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 6 08:31:31 2013 +0000

    target-ppc: Error out for -cpu host on unknown PVR
    
    Previously we silently exited, with subclasses we got an opcode warning.
    Instead, explicitly tell the user what's wrong.
    
    An indication for this is -cpu ? showing "host" with an all-zero PVR.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index ce7d69b..4846acf 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1232,7 +1232,15 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
 
 static void kvmppc_host_cpu_initfn(Object *obj)
 {
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(obj);
+
     assert(kvm_enabled());
+
+    if (pcc->info->pvr != mfpvr()) {
+        fprintf(stderr, "Your host CPU is unsupported.\n"
+                "Please choose a supported model instead, see -cpu ?.\n");
+        exit(1);
+    }
 }
 
 static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
commit 2985b86b5c9c068af203bd912309af033112039a
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 6 08:31:30 2013 +0000

    target-ppc: Slim conversion of model definitions to QOM subclasses
    
    Since the model list is highly macrofied, keep ppc_def_t for now and
    save a pointer to it in PowerPCCPUClass. This results in a flat list of
    subclasses including aliases, to be refined later.
    
    Move cpu_ppc_init() to translate_init.c and drop helper.c.
    Long-term the idea is to turn translate_init.c into a standalone cpu.c.
    
    Inline cpu_ppc_usable() into type registration.
    
    Split cpu_ppc_register() in two by code movement into the initfn and
    by turning the remaining part into a realizefn.
    Move qemu_init_vcpu() call into the new realizefn and adapt
    create_ppc_opcodes() to return an Error.
    
    Change ppc_find_by_pvr() -> ppc_cpu_class_by_pvr().
    Change ppc_find_by_name() -> ppc_cpu_class_by_name().
    
    Turn -cpu host into its own subclass. This requires to move the
    kvm_enabled() check in ppc_cpu_class_by_name() to avoid the class being
    found via the normal name lookup in the !kvm_enabled() case.
    Turn kvmppc_host_cpu_def() into the class_init and add an initfn that
    asserts KVM is in fact enabled.
    
    Implement -cpu ? and the QMP equivalent in terms of subclasses.
    This newly exposes -cpu host to the user, ordered last for -cpu ?.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 6c11ef8..a028dcd 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -1,7 +1,6 @@
-obj-y += translate.o helper.o
+obj-y += translate.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
-obj-y += helper.o
 obj-y += excp_helper.o
 obj-y += fpu_helper.o
 obj-y += int_helper.o
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index fb6b5a4..b338f8f 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -50,6 +50,9 @@ typedef struct PowerPCCPUClass {
     /*< public >*/
 
     void (*parent_reset)(CPUState *cpu);
+
+    /* TODO inline fields here */
+    ppc_def_t *info;
 } PowerPCCPUClass;
 
 /**
@@ -73,5 +76,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
 
 #define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
 
+PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr);
+
 
 #endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index dc5145b..953146e 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1158,10 +1158,6 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
 
 void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
 
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr);
-const ppc_def_t *cpu_ppc_find_by_name (const char *name);
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def);
-
 /* Time-base and decrementer management */
 #ifndef NO_CPU_IO_DEFS
 uint64_t cpu_ppc_load_tbl (CPUPPCState *env);
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
deleted file mode 100644
index 103855a..0000000
--- a/target-ppc/helper.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  PowerPC emulation helpers for QEMU.
- *
- *  Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "cpu.h"
-#include "helper_regs.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
-#include "sysemu/cpus.h"
-
-PowerPCCPU *cpu_ppc_init(const char *cpu_model)
-{
-    PowerPCCPU *cpu;
-    CPUPPCState *env;
-    const ppc_def_t *def;
-
-    def = cpu_ppc_find_by_name(cpu_model);
-    if (!def) {
-        return NULL;
-    }
-
-    cpu = POWERPC_CPU(object_new(TYPE_POWERPC_CPU));
-    env = &cpu->env;
-
-    if (tcg_enabled()) {
-        ppc_translate_init();
-    }
-
-    env->cpu_model_str = cpu_model;
-    cpu_ppc_register_internal(env, def);
-
-    qemu_init_vcpu(env);
-
-    return cpu;
-}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 9fe949f..ce7d69b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1230,18 +1230,29 @@ static void alter_insns(uint64_t *word, uint64_t flags, bool on)
     }
 }
 
-const ppc_def_t *kvmppc_host_cpu_def(void)
+static void kvmppc_host_cpu_initfn(Object *obj)
 {
+    assert(kvm_enabled());
+}
+
+static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
     uint32_t host_pvr = mfpvr();
-    const ppc_def_t *base_spec;
+    PowerPCCPUClass *pvr_pcc;
     ppc_def_t *spec;
     uint32_t vmx = kvmppc_get_vmx();
     uint32_t dfp = kvmppc_get_dfp();
 
-    base_spec = ppc_find_by_pvr(host_pvr);
-
     spec = g_malloc0(sizeof(*spec));
-    memcpy(spec, base_spec, sizeof(*spec));
+
+    pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
+    if (pvr_pcc != NULL) {
+        memcpy(spec, pvr_pcc->info, sizeof(*spec));
+    }
+    pcc->info = spec;
+    /* Override the display name for -cpu ? and QMP */
+    pcc->info->name = "host";
 
     /* Now fix up the spec with information we can query from the host */
 
@@ -1254,8 +1265,6 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
         /* Only override when we know what the host supports */
         alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
     }
-
-    return spec;
 }
 
 int kvmppc_fixup_cpu(CPUPPCState *env)
@@ -1285,3 +1294,17 @@ int kvm_arch_on_sigbus(int code, void *addr)
 {
     return 1;
 }
+
+static const TypeInfo kvm_host_cpu_type_info = {
+    .name = TYPE_HOST_POWERPC_CPU,
+    .parent = TYPE_POWERPC_CPU,
+    .instance_init = kvmppc_host_cpu_initfn,
+    .class_init = kvmppc_host_cpu_class_init,
+};
+
+static void kvm_ppc_register_types(void)
+{
+    type_register_static(&kvm_host_cpu_type_info);
+}
+
+type_init(kvm_ppc_register_types)
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 9b0d500..4b21723 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -11,6 +11,8 @@
 
 #include "exec/memory.h"
 
+#define TYPE_HOST_POWERPC_CPU "host-" TYPE_POWERPC_CPU
+
 void kvmppc_init(void);
 
 #ifdef CONFIG_KVM
@@ -31,7 +33,6 @@ int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
 int kvmppc_reset_htab(int shift_hint);
 uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
 #endif /* !CONFIG_USER_ONLY */
-const ppc_def_t *kvmppc_host_cpu_def(void);
 int kvmppc_fixup_cpu(CPUPPCState *env);
 
 #else
@@ -121,11 +122,6 @@ static inline int kvmppc_update_sdr1(CPUPPCState *env)
 
 #endif /* !CONFIG_USER_ONLY */
 
-static inline const ppc_def_t *kvmppc_host_cpu_def(void)
-{
-    return NULL;
-}
-
 static inline int kvmppc_fixup_cpu(CPUPPCState *env)
 {
     return -1;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e2eeb87..2b03756 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9792,8 +9792,11 @@ static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
 }
 
 /*****************************************************************************/
-static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
+static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
 {
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    CPUPPCState *env = &cpu->env;
+    const ppc_def_t *def = pcc->info;
     opcode_t *opc;
 
     fill_new_table(env->opcodes, 0x40);
@@ -9801,18 +9804,16 @@ static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
         if (((opc->handler.type & def->insns_flags) != 0) ||
             ((opc->handler.type2 & def->insns_flags2) != 0)) {
             if (register_insn(env->opcodes, opc) < 0) {
-                printf("*** ERROR initializing PowerPC instruction "
-                       "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
-                       opc->opc3);
-                return -1;
+                error_setg(errp, "ERROR initializing PowerPC instruction "
+                           "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
+                           opc->opc3);
+                return;
             }
         }
     }
     fix_opcode_tables(env->opcodes);
     fflush(stdout);
     fflush(stderr);
-
-    return 0;
 }
 
 #if defined(PPC_DUMP_CPU)
@@ -10026,53 +10027,31 @@ static int ppc_fixup_cpu(CPUPPCState *env)
     return 0;
 }
 
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
+static void ppc_cpu_realize(Object *obj, Error **errp)
 {
-    env->msr_mask = def->msr_mask;
-    env->mmu_model = def->mmu_model;
-    env->excp_model = def->excp_model;
-    env->bus_model = def->bus_model;
-    env->insns_flags = def->insns_flags;
-    env->insns_flags2 = def->insns_flags2;
-    env->flags = def->flags;
-    env->bfd_mach = def->bfd_mach;
-    env->check_pow = def->check_pow;
-
-#if defined(TARGET_PPC64)
-    if (def->sps)
-        env->sps = *def->sps;
-    else if (env->mmu_model & POWERPC_MMU_64) {
-        /* Use default sets of page sizes */
-        static const struct ppc_segment_page_sizes defsps = {
-            .sps = {
-                { .page_shift = 12, /* 4K */
-                  .slb_enc = 0,
-                  .enc = { { .page_shift = 12, .pte_enc = 0 } }
-                },
-                { .page_shift = 24, /* 16M */
-                  .slb_enc = 0x100,
-                  .enc = { { .page_shift = 24, .pte_enc = 0 } }
-                },
-            },
-        };
-        env->sps = defsps;
-    }
-#endif /* defined(TARGET_PPC64) */
+    PowerPCCPU *cpu = POWERPC_CPU(obj);
+    CPUPPCState *env = &cpu->env;
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    ppc_def_t *def = pcc->info;
+    Error *local_err = NULL;
 
     if (kvm_enabled()) {
         if (kvmppc_fixup_cpu(env) != 0) {
-            fprintf(stderr, "Unable to virtualize selected CPU with KVM\n");
-            exit(1);
+            error_setg(errp, "Unable to virtualize selected CPU with KVM");
+            return;
         }
     } else {
         if (ppc_fixup_cpu(env) != 0) {
-            fprintf(stderr, "Unable to emulate selected CPU with TCG\n");
-            exit(1);
+            error_setg(errp, "Unable to emulate selected CPU with TCG");
+            return;
         }
     }
 
-    if (create_ppc_opcodes(env, def) < 0)
-        return -1;
+    create_ppc_opcodes(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
     init_ppc_proc(env, def);
 
     if (def->insns_flags & PPC_FLOAT) {
@@ -10088,6 +10067,8 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
                                  34, "power-spe.xml", 0);
     }
 
+    qemu_init_vcpu(env);
+
 #if defined(PPC_DUMP_CPU)
     {
         const char *mmu_model, *excp_model, *bus_model;
@@ -10249,50 +10230,65 @@ int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
     dump_ppc_sprs(env);
     fflush(stdout);
 #endif
-
-    return 0;
 }
 
-static bool ppc_cpu_usable(const ppc_def_t *def)
+static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
 {
-#if defined(TARGET_PPCEMB)
-    /* When using the ppcemb target, we only support 440 style cores */
-    if (def->mmu_model != POWERPC_MMU_BOOKE) {
-        return false;
+    ObjectClass *oc = (ObjectClass *)a;
+    uint32_t pvr = *(uint32_t *)b;
+    PowerPCCPUClass *pcc = (PowerPCCPUClass *)a;
+
+    /* -cpu host does a PVR lookup during construction */
+    if (unlikely(strcmp(object_class_get_name(oc),
+                        TYPE_HOST_POWERPC_CPU) == 0)) {
+        return -1;
     }
-#endif
 
-    return true;
+    return pcc->info->pvr == pvr ? 0 : -1;
 }
 
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
+PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr)
 {
-    int i;
+    GSList *list, *item;
+    PowerPCCPUClass *pcc = NULL;
 
-    for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
-        if (!ppc_cpu_usable(&ppc_defs[i])) {
-            continue;
-        }
-
-        /* If we have an exact match, we're done */
-        if (pvr == ppc_defs[i].pvr) {
-            return &ppc_defs[i];
-        }
+    list = object_class_get_list(TYPE_POWERPC_CPU, false);
+    item = g_slist_find_custom(list, &pvr, ppc_cpu_compare_class_pvr);
+    if (item != NULL) {
+        pcc = POWERPC_CPU_CLASS(item->data);
     }
+    g_slist_free(list);
+
+    return pcc;
+}
+
+static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *oc = (ObjectClass *)a;
+    const char *name = b;
 
-    return NULL;
+    if (strncasecmp(name, object_class_get_name(oc), strlen(name)) == 0 &&
+        strcmp(object_class_get_name(oc) + strlen(name),
+               "-" TYPE_POWERPC_CPU) == 0) {
+        return 0;
+    }
+    return -1;
 }
 
 #include <ctype.h>
 
-const ppc_def_t *cpu_ppc_find_by_name (const char *name)
+static ObjectClass *ppc_cpu_class_by_name(const char *name)
 {
-    const ppc_def_t *ret;
+    GSList *list, *item;
+    ObjectClass *ret = NULL;
     const char *p;
-    int i, max, len;
+    int i, len;
 
-    if (kvm_enabled() && (strcasecmp(name, "host") == 0)) {
-        return kvmppc_host_cpu_def();
+    if (strcasecmp(name, "host") == 0) {
+        if (kvm_enabled()) {
+            ret = object_class_by_name(TYPE_HOST_POWERPC_CPU);
+        }
+        return ret;
     }
 
     /* Check if the given name is a PVR */
@@ -10307,63 +10303,152 @@ const ppc_def_t *cpu_ppc_find_by_name (const char *name)
             if (!qemu_isxdigit(*p++))
                 break;
         }
-        if (i == 8)
-            return ppc_find_by_pvr(strtoul(name, NULL, 16));
-    }
-    ret = NULL;
-    max = ARRAY_SIZE(ppc_defs);
-    for (i = 0; i < max; i++) {
-        if (!ppc_cpu_usable(&ppc_defs[i])) {
-            continue;
+        if (i == 8) {
+            ret = OBJECT_CLASS(ppc_cpu_class_by_pvr(strtoul(name, NULL, 16)));
+            return ret;
         }
+    }
 
-        if (strcasecmp(name, ppc_defs[i].name) == 0) {
-            ret = &ppc_defs[i];
-            break;
-        }
+    list = object_class_get_list(TYPE_POWERPC_CPU, false);
+    item = g_slist_find_custom(list, name, ppc_cpu_compare_class_name);
+    if (item != NULL) {
+        ret = OBJECT_CLASS(item->data);
     }
+    g_slist_free(list);
 
     return ret;
 }
 
-void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
+PowerPCCPU *cpu_ppc_init(const char *cpu_model)
 {
-    int i, max;
+    PowerPCCPU *cpu;
+    CPUPPCState *env;
+    ObjectClass *oc;
+    Error *err = NULL;
 
-    max = ARRAY_SIZE(ppc_defs);
-    for (i = 0; i < max; i++) {
-        if (!ppc_cpu_usable(&ppc_defs[i])) {
-            continue;
-        }
+    oc = ppc_cpu_class_by_name(cpu_model);
+    if (oc == NULL) {
+        return NULL;
+    }
 
-        (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
-                       ppc_defs[i].name, ppc_defs[i].pvr);
+    cpu = POWERPC_CPU(object_new(object_class_get_name(oc)));
+    env = &cpu->env;
+
+    if (tcg_enabled()) {
+        ppc_translate_init();
     }
+
+    env->cpu_model_str = cpu_model;
+
+    ppc_cpu_realize(OBJECT(cpu), &err);
+    if (err != NULL) {
+        fprintf(stderr, "%s\n", error_get_pretty(err));
+        error_free(err);
+        object_delete(OBJECT(cpu));
+        return NULL;
+    }
+
+    return cpu;
+}
+
+/* Sort by PVR, ordering special case "host" last. */
+static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *oc_a = (ObjectClass *)a;
+    ObjectClass *oc_b = (ObjectClass *)b;
+    PowerPCCPUClass *pcc_a = POWERPC_CPU_CLASS(oc_a);
+    PowerPCCPUClass *pcc_b = POWERPC_CPU_CLASS(oc_b);
+    const char *name_a = object_class_get_name(oc_a);
+    const char *name_b = object_class_get_name(oc_b);
+
+    if (strcmp(name_a, TYPE_HOST_POWERPC_CPU) == 0) {
+        return 1;
+    } else if (strcmp(name_b, TYPE_HOST_POWERPC_CPU) == 0) {
+        return -1;
+    } else {
+        /* Avoid an integer overflow during subtraction */
+        if (pcc_a->info->pvr < pcc_b->info->pvr) {
+            return -1;
+        } else if (pcc_a->info->pvr > pcc_b->info->pvr) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
+
+static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    CPUListState *s = user_data;
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+    (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
+                      pcc->info->name, pcc->info->pvr);
+}
+
+void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    CPUListState s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_POWERPC_CPU, false);
+    list = g_slist_sort(list, ppc_cpu_list_compare);
+    g_slist_foreach(list, ppc_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
+static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    CpuDefinitionInfoList **first = user_data;
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+    CpuDefinitionInfoList *entry;
+    CpuDefinitionInfo *info;
+
+    info = g_malloc0(sizeof(*info));
+    info->name = g_strdup(pcc->info->name);
+
+    entry = g_malloc0(sizeof(*entry));
+    entry->value = info;
+    entry->next = *first;
+    *first = entry;
 }
 
 CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
-    int i;
+    GSList *list;
 
-    for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
-        CpuDefinitionInfoList *entry;
-        CpuDefinitionInfo *info;
+    list = object_class_get_list(TYPE_POWERPC_CPU, false);
+    g_slist_foreach(list, ppc_cpu_defs_entry, &cpu_list);
+    g_slist_free(list);
 
-        if (!ppc_cpu_usable(&ppc_defs[i])) {
-            continue;
-        }
+    return cpu_list;
+}
 
-        info = g_malloc0(sizeof(*info));
-        info->name = g_strdup(ppc_defs[i].name);
+static void ppc_cpu_def_class_init(ObjectClass *oc, void *data)
+{
+    PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+    ppc_def_t *info = data;
 
-        entry = g_malloc0(sizeof(*entry));
-        entry->value = info;
-        entry->next = cpu_list;
-        cpu_list = entry;
-    }
+    pcc->info = info;
+}
 
-    return cpu_list;
+static void ppc_cpu_register_model(const ppc_def_t *def)
+{
+    TypeInfo type_info = {
+        .parent = TYPE_POWERPC_CPU,
+        .class_init = ppc_cpu_def_class_init,
+        .class_data = (void *)def,
+    };
+
+    type_info.name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, def->name),
+    type_register(&type_info);
+    g_free((gpointer)type_info.name);
 }
 
 /* CPUClass::reset() */
@@ -10434,9 +10519,42 @@ static void ppc_cpu_reset(CPUState *s)
 static void ppc_cpu_initfn(Object *obj)
 {
     PowerPCCPU *cpu = POWERPC_CPU(obj);
+    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
     CPUPPCState *env = &cpu->env;
+    ppc_def_t *def = pcc->info;
 
     cpu_exec_init(env);
+
+    env->msr_mask = def->msr_mask;
+    env->mmu_model = def->mmu_model;
+    env->excp_model = def->excp_model;
+    env->bus_model = def->bus_model;
+    env->insns_flags = def->insns_flags;
+    env->insns_flags2 = def->insns_flags2;
+    env->flags = def->flags;
+    env->bfd_mach = def->bfd_mach;
+    env->check_pow = def->check_pow;
+
+#if defined(TARGET_PPC64)
+    if (def->sps) {
+        env->sps = *def->sps;
+    } else if (env->mmu_model & POWERPC_MMU_64) {
+        /* Use default sets of page sizes */
+        static const struct ppc_segment_page_sizes defsps = {
+            .sps = {
+                { .page_shift = 12, /* 4K */
+                  .slb_enc = 0,
+                  .enc = { { .page_shift = 12, .pte_enc = 0 } }
+                },
+                { .page_shift = 24, /* 16M */
+                  .slb_enc = 0x100,
+                  .enc = { { .page_shift = 24, .pte_enc = 0 } }
+                },
+            },
+        };
+        env->sps = defsps;
+    }
+#endif /* defined(TARGET_PPC64) */
 }
 
 static void ppc_cpu_class_init(ObjectClass *oc, void *data)
@@ -10453,14 +10571,27 @@ static const TypeInfo ppc_cpu_type_info = {
     .parent = TYPE_CPU,
     .instance_size = sizeof(PowerPCCPU),
     .instance_init = ppc_cpu_initfn,
-    .abstract = false,
+    .abstract = true,
     .class_size = sizeof(PowerPCCPUClass),
     .class_init = ppc_cpu_class_init,
 };
 
 static void ppc_cpu_register_types(void)
 {
+    int i;
+
     type_register_static(&ppc_cpu_type_info);
+
+    for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
+        const ppc_def_t *def = &ppc_defs[i];
+#if defined(TARGET_PPCEMB)
+        /* When using the ppcemb target, we only support 440 style cores */
+        if (def->mmu_model != POWERPC_MMU_BOOKE) {
+            continue;
+        }
+#endif
+        ppc_cpu_register_model(def);
+    }
 }
 
 type_init(ppc_cpu_register_types)
commit 68c2dd70068fe82a1989d0d5b70a1ab400bde19a
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Jan 4 11:21:04 2013 +0100

    PPC: Bring EPR support closer to reality
    
    We already used to support the external proxy facility of FSL MPICs,
    but only implemented it halfway correctly.
    
    This patch adds support for
    
      * dynamic enablement of the EPR facility
      * interrupt acknowledgement only when the interrupt is delivered
    
    This way the implementation now is closer to real hardware.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index e773d68..3b20a39 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -131,6 +131,9 @@ static const int debug_openpic = 0;
 #define VIR_GENERIC      0x00000000 /* Generic Vendor ID */
 
 #define GCR_RESET        0x80000000
+#define GCR_MODE_PASS    0x00000000
+#define GCR_MODE_MIXED   0x20000000
+#define GCR_MODE_PROXY   0x60000000
 
 #define TBCR_CI           0x80000000 /* count inhibit */
 #define TCCR_TOG          0x80000000 /* toggles when decrement to zero */
@@ -233,6 +236,7 @@ typedef struct OpenPICState {
     uint32_t ivpr_reset;
     uint32_t idr_reset;
     uint32_t brr1;
+    uint32_t mpic_mode_mask;
 
     /* Sub-regions */
     MemoryRegion sub_io_mem[5];
@@ -667,6 +671,20 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x1020: /* GCR */
         if (val & GCR_RESET) {
             openpic_reset(&opp->busdev.qdev);
+        } else if (opp->mpic_mode_mask) {
+            CPUArchState *env;
+            int mpic_proxy = 0;
+
+            opp->gcr &= ~opp->mpic_mode_mask;
+            opp->gcr |= val & opp->mpic_mode_mask;
+
+            /* Set external proxy mode */
+            if ((val & opp->mpic_mode_mask) == GCR_MODE_PROXY) {
+                mpic_proxy = 1;
+            }
+            for (env = first_cpu; env != NULL; env = env->next_cpu) {
+                env->mpic_proxy = mpic_proxy;
+            }
         }
         break;
     case 0x1080: /* VIR */
@@ -1407,6 +1425,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
         opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
         opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
+        /* XXX really only available as of MPIC 4.0 */
+        opp->mpic_mode_mask = GCR_MODE_PROXY;
+
         msi_supported = true;
         list = list_be;
 
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 5d70618..3a9e1c7 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -497,8 +497,8 @@ void ppce500_init(PPCE500Params *params)
         irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
         irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
         env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
-        env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
-                              MPC8544_MPIC_REGS_OFFSET + 0x20000;
+        env->mpic_iack = MPC8544_CCSRBAR_BASE +
+                         MPC8544_MPIC_REGS_OFFSET + 0x200A0;
 
         ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
 
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 237a0ed..6c11ef8 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -9,4 +9,3 @@ obj-y += mmu_helper.o
 obj-y += timebase_helper.o
 obj-y += misc_helper.o
 obj-y += mem_helper.o
-obj-y += mpic_helper.o
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index e88ebe0..dc5145b 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1067,7 +1067,9 @@ struct CPUPPCState {
     target_ulong ivor_mask;
     target_ulong ivpr_mask;
     target_ulong hreset_vector;
-    hwaddr mpic_cpu_base;
+    hwaddr mpic_iack;
+    /* true when the external proxy facility mode is enabled */
+    bool mpic_proxy;
 #endif
 
     /* Those resources are used only during code translation */
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 41037a7..0a1ac86 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -178,6 +178,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
         if (lpes0 == 1) {
             new_msr |= (target_ulong)MSR_HVB;
         }
+        if (env->mpic_proxy) {
+            /* IACK the IRQ on delivery */
+            env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
+        }
         goto store_next;
     case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
         if (lpes1 == 0) {
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index d2e9a55..83139d5 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -405,7 +405,6 @@ DEF_HELPER_2(store_40x_dbcr0, void, env, tl)
 DEF_HELPER_2(store_40x_sler, void, env, tl)
 DEF_HELPER_2(store_booke_tcr, void, env, tl)
 DEF_HELPER_2(store_booke_tsr, void, env, tl)
-DEF_HELPER_1(load_epr, tl, env)
 DEF_HELPER_3(store_ibatl, void, env, i32, tl)
 DEF_HELPER_3(store_ibatu, void, env, i32, tl)
 DEF_HELPER_3(store_dbatl, void, env, i32, tl)
diff --git a/target-ppc/mpic_helper.c b/target-ppc/mpic_helper.c
deleted file mode 100644
index 2c6a4d3..0000000
--- a/target-ppc/mpic_helper.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  PowerPC emulation helpers for QEMU.
- *
- *  Copyright (c) 2003-2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-#include "cpu.h"
-#include "helper.h"
-
-/*****************************************************************************/
-/* SPR accesses */
-
-#if !defined(CONFIG_USER_ONLY)
-/*
- * This is an ugly helper for EPR, which is basically the same as accessing
- * the IACK (PIAC) register on the MPIC. Because we model the MPIC as a device
- * that can only talk to the CPU through MMIO, let's access it that way!
- */
-target_ulong helper_load_epr(CPUPPCState *env)
-{
-    return ldl_phys(env->mpic_cpu_base + 0xA0);
-}
-#endif
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 42ed748..e2eeb87 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -4493,11 +4493,6 @@ static void spr_read_mas73(void *opaque, int gprn, int sprn)
     tcg_temp_free(mas7);
 }
 
-static void spr_load_epr(void *opaque, int gprn, int sprn)
-{
-    gen_helper_load_epr(cpu_gpr[gprn], cpu_env);
-}
-
 #endif
 
 enum fsl_e500_version {
@@ -4656,7 +4651,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
                  0x00000000);
     spr_register(env, SPR_BOOKE_EPR, "EPR",
                  SPR_NOACCESS, SPR_NOACCESS,
-                 &spr_load_epr, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
                  0x00000000);
     /* XXX better abstract into Emb.xxx features */
     if (version == fsl_e5500) {
commit 1a61a9ae61cdf7b7d24c3eb711fe772c196c235e
Author: Stuart Yoder <stuart.yoder at freescale.com>
Date:   Thu Jan 3 12:37:02 2013 +0000

    PPC: KVM: set has-idle in guest device tree
    
    On e500mc, the platform doesn't provide a way for the CPU to go idle.
    
    To still not uselessly burn CPU time, expose an idle hypercall to the guest
    if kvm supports it.
    
    Signed-off-by: Stuart Yoder <stuart.yoder at freescale.com>
    [agraf: adjust for current code base, add patch description, fix non-kvm case]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index b262f31..5d70618 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -225,6 +225,10 @@ static int ppce500_load_device_tree(CPUPPCState *env,
         kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
         qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
                              hypercall, sizeof(hypercall));
+        /* if KVM supports the idle hcall, set property indicating this */
+        if (kvmppc_get_hasidle(env)) {
+            qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
+        }
     }
 
     /* Create CPU nodes */
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 436ca47..9fe949f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -989,18 +989,38 @@ uint32_t kvmppc_get_dfp(void)
     return kvmppc_read_int_cpu_dt("ibm,dfp");
 }
 
+static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
+ {
+     PowerPCCPU *cpu = ppc_env_get_cpu(env);
+     CPUState *cs = CPU(cpu);
+
+    if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
+        !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) {
+        return 0;
+    }
+
+    return 1;
+}
+
+int kvmppc_get_hasidle(CPUPPCState *env)
+{
+    struct kvm_ppc_pvinfo pvinfo;
+
+    if (!kvmppc_get_pvinfo(env, &pvinfo) &&
+        (pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) {
+        return 1;
+    }
+
+    return 0;
+}
+
 int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     uint32_t *hc = (uint32_t*)buf;
-
     struct kvm_ppc_pvinfo pvinfo;
 
-    if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
-        !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
+    if (!kvmppc_get_pvinfo(env, &pvinfo)) {
         memcpy(buf, pvinfo.hcall, buf_len);
-
         return 0;
     }
 
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 31eb9e6..9b0d500 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -19,6 +19,7 @@ uint32_t kvmppc_get_tbfreq(void);
 uint64_t kvmppc_get_clockfreq(void);
 uint32_t kvmppc_get_vmx(void);
 uint32_t kvmppc_get_dfp(void);
+int kvmppc_get_hasidle(CPUPPCState *env);
 int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
 int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
 void kvmppc_set_papr(PowerPCCPU *cpu);
@@ -55,6 +56,11 @@ static inline uint32_t kvmppc_get_dfp(void)
     return 0;
 }
 
+static inline int kvmppc_get_hasidle(CPUPPCState *env)
+{
+    return 0;
+}
+
 static inline int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
 {
     return -1;
commit d4834ff9b72d7b89181e88b1a481564cb750c1b5
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Jan 4 10:04:19 2013 +0100

    kvm: Update kernel headers
    
    Corresponding kvm.git hash: 18eb54cf4a
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/linux-headers/asm-powerpc/epapr_hcalls.h b/linux-headers/asm-powerpc/epapr_hcalls.h
new file mode 100644
index 0000000..06f7247
--- /dev/null
+++ b/linux-headers/asm-powerpc/epapr_hcalls.h
@@ -0,0 +1,98 @@
+/*
+ * ePAPR hcall interface
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur at freescale.com>
+ *
+ * This file is provided under a dual BSD/GPL license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_POWERPC_EPAPR_HCALLS_H
+#define _ASM_POWERPC_EPAPR_HCALLS_H
+
+#define EV_BYTE_CHANNEL_SEND		1
+#define EV_BYTE_CHANNEL_RECEIVE		2
+#define EV_BYTE_CHANNEL_POLL		3
+#define EV_INT_SET_CONFIG		4
+#define EV_INT_GET_CONFIG		5
+#define EV_INT_SET_MASK			6
+#define EV_INT_GET_MASK			7
+#define EV_INT_IACK			9
+#define EV_INT_EOI			10
+#define EV_INT_SEND_IPI			11
+#define EV_INT_SET_TASK_PRIORITY	12
+#define EV_INT_GET_TASK_PRIORITY	13
+#define EV_DOORBELL_SEND		14
+#define EV_MSGSND			15
+#define EV_IDLE				16
+
+/* vendor ID: epapr */
+#define EV_LOCAL_VENDOR_ID		0	/* for private use */
+#define EV_EPAPR_VENDOR_ID		1
+#define EV_FSL_VENDOR_ID		2	/* Freescale Semiconductor */
+#define EV_IBM_VENDOR_ID		3	/* IBM */
+#define EV_GHS_VENDOR_ID		4	/* Green Hills Software */
+#define EV_ENEA_VENDOR_ID		5	/* Enea */
+#define EV_WR_VENDOR_ID			6	/* Wind River Systems */
+#define EV_AMCC_VENDOR_ID		7	/* Applied Micro Circuits */
+#define EV_KVM_VENDOR_ID		42	/* KVM */
+
+/* The max number of bytes that a byte channel can send or receive per call */
+#define EV_BYTE_CHANNEL_MAX_BYTES	16
+
+
+#define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
+#define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
+
+/* epapr return codes */
+#define EV_SUCCESS		0
+#define EV_EPERM		1	/* Operation not permitted */
+#define EV_ENOENT		2	/*  Entry Not Found */
+#define EV_EIO			3	/* I/O error occured */
+#define EV_EAGAIN		4	/* The operation had insufficient
+					 * resources to complete and should be
+					 * retried
+					 */
+#define EV_ENOMEM		5	/* There was insufficient memory to
+					 * complete the operation */
+#define EV_EFAULT		6	/* Bad guest address */
+#define EV_ENODEV		7	/* No such device */
+#define EV_EINVAL		8	/* An argument supplied to the hcall
+					   was out of range or invalid */
+#define EV_INTERNAL		9	/* An internal error occured */
+#define EV_CONFIG		10	/* A configuration error was detected */
+#define EV_INVALID_STATE	11	/* The object is in an invalid state */
+#define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
+#define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
+
+#endif /* _ASM_POWERPC_EPAPR_HCALLS_H */
diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1bea4d8..2fba8a6 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
 
 			__u32 dbsr;	/* KVM_SREGS_E_UPDATE_DBSR */
 			__u32 dbcr[3];
+			/*
+			 * iac/dac registers are 64bit wide, while this API
+			 * interface provides only lower 32 bits on 64 bit
+			 * processors. ONE_REG interface is added for 64bit
+			 * iac/dac registers.
+			 */
 			__u32 iac[4];
 			__u32 dac[2];
 			__u32 dvc[2];
@@ -325,6 +331,86 @@ struct kvm_book3e_206_tlb_params {
 	__u32 reserved[8];
 };
 
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+	__u64	flags;
+	__u64	start_index;
+	__u64	reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY	((__u64)0x1)
+#define KVM_GET_HTAB_WRITE		((__u64)0x2)
+
+/*
+ * Data read on the file descriptor is formatted as a series of
+ * records, each consisting of a header followed by a series of
+ * `n_valid' HPTEs (16 bytes each), which are all valid.  Following
+ * those valid HPTEs there are `n_invalid' invalid HPTEs, which
+ * are not represented explicitly in the stream.  The same format
+ * is used for writing.
+ */
+struct kvm_get_htab_header {
+	__u32	index;
+	__u16	n_valid;
+	__u16	n_invalid;
+};
+
 #define KVM_REG_PPC_HIOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n)	(KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0		(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n)	(KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n)	(KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL	(KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
+
+#define KVM_REG_PPC_EPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
 
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index 5e04383..7e64f57 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -17,8 +17,8 @@
  * Authors: Hollis Blanchard <hollisb at us.ibm.com>
  */
 
-#ifndef _UAPI__POWERPC_KVM_PARA_H__
-#define _UAPI__POWERPC_KVM_PARA_H__
+#ifndef __POWERPC_KVM_PARA_H__
+#define __POWERPC_KVM_PARA_H__
 
 #include <linux/types.h>
 
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0		0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM		(42 << 16)
-#define HC_EV_SUCCESS		0
-#define HC_EV_UNIMPLEMENTED	12
+
+#define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE	1
 
@@ -87,4 +88,4 @@ struct kvm_vcpu_arch_shared {
 #define KVM_MAGIC_FEAT_MAS0_TO_SPRG7	(1 << 1)
 
 
-#endif /* _UAPI__POWERPC_KVM_PARA_H__ */
+#endif /* __POWERPC_KVM_PARA_H__ */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 81d2feb..bfdbf4d 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -167,10 +167,15 @@ struct kvm_pit_config {
 #define KVM_EXIT_OSI              18
 #define KVM_EXIT_PAPR_HCALL	  19
 #define KVM_EXIT_S390_UCONTROL	  20
+#define KVM_EXIT_WATCHDOG         21
 
 /* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION	1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX	2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV	3
 
 /* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 struct kvm_run {
@@ -477,6 +482,8 @@ struct kvm_ppc_smmu_info {
 	struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
 };
 
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
 #define KVMIO 0xAE
 
 /* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +633,8 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_READONLY_MEM 81
 #endif
 #define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_PPC_HTAB_FD 84
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -848,6 +857,11 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_SMMU_INFO	  _IOR(KVMIO,  0xa6, struct kvm_ppc_smmu_info)
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB	  _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_PPC_HTAB_FD */
+#define KVM_PPC_GET_HTAB_FD	  _IOW(KVMIO,  0xaa, struct kvm_get_htab_fd)
 
 /*
  * ioctls for vcpu fds
@@ -911,9 +925,6 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_XCRS */
 #define KVM_GET_XCRS		  _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 #define KVM_SET_XCRS		  _IOW(KVMIO,  0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE	  _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA	  _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_SW_TLB */
 #define KVM_DIRTY_TLB		  _IOW(KVMIO,  0xaa, struct kvm_dirty_tlb)
 /* Available with KVM_CAP_ONE_REG */
diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h
index cea2c5c..7bdcf93 100644
--- a/linux-headers/linux/kvm_para.h
+++ b/linux-headers/linux/kvm_para.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI__LINUX_KVM_PARA_H
-#define _UAPI__LINUX_KVM_PARA_H
+#ifndef __LINUX_KVM_PARA_H
+#define __LINUX_KVM_PARA_H
 
 /*
  * This header file provides a method for making a hypercall to the host
@@ -25,4 +25,4 @@
  */
 #include <asm/kvm_para.h>
 
-#endif /* _UAPI__LINUX_KVM_PARA_H */
+#endif /* __LINUX_KVM_PARA_H */
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4758d1b..f787b72 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -8,8 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef _UAPIVFIO_H
-#define _UAPIVFIO_H
+#ifndef VFIO_H
+#define VFIO_H
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
@@ -365,4 +365,4 @@ struct vfio_iommu_type1_dma_unmap {
 
 #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
 
-#endif /* _UAPIVFIO_H */
+#endif /* VFIO_H */
diff --git a/linux-headers/linux/virtio_config.h b/linux-headers/linux/virtio_config.h
index b7cda39..4f51d8f 100644
--- a/linux-headers/linux/virtio_config.h
+++ b/linux-headers/linux/virtio_config.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_CONFIG_H
-#define _UAPI_LINUX_VIRTIO_CONFIG_H
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
 /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
  * anyone can use the definitions to implement compatible drivers/servers.
  *
@@ -51,4 +51,4 @@
  * suppressed them? */
 #define VIRTIO_F_NOTIFY_ON_EMPTY	24
 
-#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
+#endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/linux-headers/linux/virtio_ring.h b/linux-headers/linux/virtio_ring.h
index 921694a..1b333e2 100644
--- a/linux-headers/linux/virtio_ring.h
+++ b/linux-headers/linux/virtio_ring.h
@@ -1,5 +1,5 @@
-#ifndef _UAPI_LINUX_VIRTIO_RING_H
-#define _UAPI_LINUX_VIRTIO_RING_H
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
 /* An interface for efficient virtio implementation, currently for use by KVM
  * and lguest, but hopefully others soon.  Do NOT change this since it will
  * break existing servers and clients.
@@ -160,4 +160,4 @@ static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old
 	return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
 }
 
-#endif /* _UAPI_LINUX_VIRTIO_RING_H */
+#endif /* _LINUX_VIRTIO_RING_H */
commit 9f1d4b1d6939d39fe570d886f6a651f4764bcbcb
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Jan 3 13:25:40 2013 +0000

    openpic: fix CTPR and de-assertion of interrupts
    
    Properly implement level-triggered interrupts by withdrawing an
    interrupt from the raised queue if the interrupt source de-asserts.
    Also withdraw from the raised queue if the interrupt becomes masked.
    
    When CTPR is written, check whether we need to raise or lower the
    interrupt output.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 374f80e..e773d68 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -213,6 +213,9 @@ typedef struct IRQDest {
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
+
+    /* Count of IRQ sources asserting on non-INT outputs */
+    uint32_t outputs_active[OPENPIC_OUTPUT_NB];
 } IRQDest;
 
 typedef struct OpenPICState {
@@ -308,7 +311,8 @@ static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
     return q->next;
 }
 
-static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
+static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ,
+                           bool active, bool was_active)
 {
     IRQDest *dst;
     IRQSource *src;
@@ -317,79 +321,113 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
 
+    DPRINTF("%s: IRQ %d active %d was %d\n",
+            __func__, n_IRQ, active, was_active);
+
     if (src->output != OPENPIC_OUTPUT_INT) {
+        DPRINTF("%s: output %d irq %d active %d was %d count %d\n",
+                __func__, src->output, n_IRQ, active, was_active,
+                dst->outputs_active[src->output]);
+
         /* On Freescale MPIC, critical interrupts ignore priority,
          * IACK, EOI, etc.  Before MPIC v4.1 they also ignore
          * masking.
          */
-        src->ivpr |= IVPR_ACTIVITY_MASK;
-        DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
-                __func__, src->output, n_CPU, n_IRQ);
-        qemu_irq_raise(opp->dst[n_CPU].irqs[src->output]);
+        if (active) {
+            if (!was_active && dst->outputs_active[src->output]++ == 0) {
+                DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
+                        __func__, src->output, n_CPU, n_IRQ);
+                qemu_irq_raise(dst->irqs[src->output]);
+            }
+        } else {
+            if (was_active && --dst->outputs_active[src->output] == 0) {
+                DPRINTF("%s: Lower OpenPIC output %d cpu %d irq %d\n",
+                        __func__, src->output, n_CPU, n_IRQ);
+                qemu_irq_lower(dst->irqs[src->output]);
+            }
+        }
+
         return;
     }
 
     priority = IVPR_PRIORITY(src->ivpr);
-    if (priority <= dst->ctpr) {
-        /* Too low priority */
-        DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
-                __func__, n_IRQ, n_CPU);
-        return;
-    }
-    if (IRQ_testbit(&dst->raised, n_IRQ)) {
-        /* Interrupt miss */
-        DPRINTF("%s: IRQ %d was missed on CPU %d\n",
-                __func__, n_IRQ, n_CPU);
-        return;
-    }
-    src->ivpr |= IVPR_ACTIVITY_MASK;
-    IRQ_setbit(&dst->raised, n_IRQ);
-    if (priority < dst->raised.priority) {
-        /* An higher priority IRQ is already raised */
-        DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
-                __func__, n_IRQ, dst->raised.next, n_CPU);
-        return;
+
+    /* Even if the interrupt doesn't have enough priority,
+     * it is still raised, in case ctpr is lowered later.
+     */
+    if (active) {
+        IRQ_setbit(&dst->raised, n_IRQ);
+    } else {
+        IRQ_resetbit(&dst->raised, n_IRQ);
     }
+
     IRQ_check(opp, &dst->raised);
-    if (IRQ_get_next(opp, &dst->servicing) != -1 &&
-        priority <= dst->servicing.priority) {
-        DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
-                __func__, n_IRQ, dst->servicing.next, n_CPU);
-        /* Already servicing a higher priority IRQ */
-        return;
+
+    if (active && priority <= dst->ctpr) {
+        DPRINTF("%s: IRQ %d priority %d too low for ctpr %d on CPU %d\n",
+                __func__, n_IRQ, priority, dst->ctpr, n_CPU);
+        active = 0;
+    }
+
+    if (active) {
+        if (IRQ_get_next(opp, &dst->servicing) >= 0 &&
+                priority <= dst->servicing.priority) {
+            DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
+                    __func__, n_IRQ, dst->servicing.next, n_CPU);
+        } else {
+            DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d/%d\n",
+                    __func__, n_CPU, n_IRQ, dst->raised.next);
+            qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        }
+    } else {
+        IRQ_get_next(opp, &dst->servicing);
+        if (dst->raised.priority > dst->ctpr &&
+                dst->raised.priority > dst->servicing.priority) {
+            DPRINTF("%s: IRQ %d inactive, IRQ %d prio %d above %d/%d, CPU %d\n",
+                    __func__, n_IRQ, dst->raised.next, dst->raised.priority,
+                    dst->ctpr, dst->servicing.priority, n_CPU);
+            /* IRQ line stays asserted */
+        } else {
+            DPRINTF("%s: IRQ %d inactive, current prio %d/%d, CPU %d\n",
+                    __func__, n_IRQ, dst->ctpr, dst->servicing.priority, n_CPU);
+            qemu_irq_lower(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        }
     }
-    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
-    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 {
     IRQSource *src;
+    bool active, was_active;
     int i;
 
     src = &opp->src[n_IRQ];
+    active = src->pending;
 
-    if (!src->pending) {
-        /* no irq pending */
-        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
-        return;
-    }
     if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
-        return;
+        active = false;
     }
-    if (IVPR_PRIORITY(src->ivpr) == 0) {
-        /* Priority set to zero */
-        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
+
+    was_active = !!(src->ivpr & IVPR_ACTIVITY_MASK);
+
+    /*
+     * We don't have a similar check for already-active because
+     * ctpr may have changed and we need to withdraw the interrupt.
+     */
+    if (!active && !was_active) {
+        DPRINTF("%s: IRQ %d is already inactive\n", __func__, n_IRQ);
         return;
     }
-    if (src->ivpr & IVPR_ACTIVITY_MASK) {
-        /* IRQ already active */
-        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
-        return;
+
+    if (active) {
+        src->ivpr |= IVPR_ACTIVITY_MASK;
+    } else {
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
     }
+
     if (src->idr == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
@@ -398,12 +436,12 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 
     if (src->idr == (1 << src->last_cpu)) {
         /* Only one CPU is allowed to receive this IRQ */
-        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
+        IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
     } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
             if (src->destmask & (1 << i)) {
-                IRQ_local_pipe(opp, i, n_IRQ);
+                IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
             }
         }
     } else {
@@ -413,7 +451,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
                 i = 0;
             }
             if (src->destmask & (1 << i)) {
-                IRQ_local_pipe(opp, i, n_IRQ);
+                IRQ_local_pipe(opp, i, n_IRQ, active, was_active);
                 src->last_cpu = i;
                 break;
             }
@@ -437,16 +475,25 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     if (src->level) {
         /* level-sensitive irq */
         src->pending = level;
-        if (!level) {
-            src->ivpr &= ~IVPR_ACTIVITY_MASK;
-        }
+        openpic_update_irq(opp, n_IRQ);
     } else {
         /* edge-sensitive irq */
         if (level) {
             src->pending = 1;
+            openpic_update_irq(opp, n_IRQ);
+        }
+
+        if (src->output != OPENPIC_OUTPUT_INT) {
+            /* Edge-triggered interrupts shouldn't be used
+             * with non-INT delivery, but just in case,
+             * try to make it do something sane rather than
+             * cause an interrupt storm.  This is close to
+             * what you'd probably see happen in real hardware.
+             */
+            src->pending = 0;
+            openpic_update_irq(opp, n_IRQ);
         }
     }
-    openpic_update_irq(opp, n_IRQ);
 }
 
 static void openpic_reset(DeviceState *d)
@@ -934,6 +981,21 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         break;
     case 0x80: /* CTPR */
         dst->ctpr = val & 0x0000000F;
+
+        DPRINTF("%s: set CPU %d ctpr to %d, raised %d servicing %d\n",
+                __func__, idx, dst->ctpr, dst->raised.priority,
+                dst->servicing.priority);
+
+        if (dst->raised.priority <= dst->ctpr) {
+            DPRINTF("%s: Lower OpenPIC INT output cpu %d due to ctpr\n",
+                    __func__, idx);
+            qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
+        } else if (dst->raised.priority > dst->servicing.priority) {
+            DPRINTF("%s: Raise OpenPIC INT output cpu %d irq %d\n",
+                    __func__, idx, dst->raised.next);
+            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+        }
+
         break;
     case 0x90: /* WHOAMI */
         /* Read-only register */
@@ -995,22 +1057,21 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
     src = &opp->src[irq];
     if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
             !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
-        /* - Spurious level-sensitive IRQ
-         * - Priorities has been changed
-         *   and the pending IRQ isn't allowed anymore
-         */
-        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        fprintf(stderr, "%s: bad raised IRQ %d ctpr %d ivpr 0x%08x\n",
+                __func__, irq, dst->ctpr, src->ivpr);
+        openpic_update_irq(opp, irq);
         retval = opp->spve;
     } else {
         /* IRQ enter servicing state */
         IRQ_setbit(&dst->servicing, irq);
         retval = IVPR_VECTOR(opp, src->ivpr);
     }
-    IRQ_resetbit(&dst->raised, irq);
+
     if (!src->level) {
         /* edge-sensitive IRQ */
         src->ivpr &= ~IVPR_ACTIVITY_MASK;
         src->pending = 0;
+        IRQ_resetbit(&dst->raised, irq);
     }
 
     if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + MAX_IPI))) {
@@ -1208,6 +1269,8 @@ static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_sbe32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
+        qemu_put_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
+                        sizeof(opp->dst[i].outputs_active));
     }
 
     for (i = 0; i < MAX_TMR; i++) {
@@ -1264,6 +1327,8 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_sbe32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
+        qemu_get_buffer(f, (uint8_t *)&opp->dst[i].outputs_active,
+                        sizeof(opp->dst[i].outputs_active));
     }
 
     for (i = 0; i < MAX_TMR; i++) {
commit a898a8fc96a071189206218b39b5db99531f5c8b
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Jan 3 13:25:39 2013 +0000

    openpic: move IACK to its own function
    
    Besides making the code cleaner, we will need a separate way to access
    IACK in order to implement EPR (external proxy) interrupt delivery.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 7645d67..374f80e 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -975,14 +975,64 @@ static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
     openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
 }
 
+
+static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
+{
+    IRQSource *src;
+    int retval, irq;
+
+    DPRINTF("Lower OpenPIC INT output\n");
+    qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
+
+    irq = IRQ_get_next(opp, &dst->raised);
+    DPRINTF("IACK: irq=%d\n", irq);
+
+    if (irq == -1) {
+        /* No more interrupt pending */
+        return opp->spve;
+    }
+
+    src = &opp->src[irq];
+    if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
+            !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
+        /* - Spurious level-sensitive IRQ
+         * - Priorities has been changed
+         *   and the pending IRQ isn't allowed anymore
+         */
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        retval = opp->spve;
+    } else {
+        /* IRQ enter servicing state */
+        IRQ_setbit(&dst->servicing, irq);
+        retval = IVPR_VECTOR(opp, src->ivpr);
+    }
+    IRQ_resetbit(&dst->raised, irq);
+    if (!src->level) {
+        /* edge-sensitive IRQ */
+        src->ivpr &= ~IVPR_ACTIVITY_MASK;
+        src->pending = 0;
+    }
+
+    if ((irq >= opp->irq_ipi0) &&  (irq < (opp->irq_ipi0 + MAX_IPI))) {
+        src->idr &= ~(1 << cpu);
+        if (src->idr && !src->level) {
+            /* trigger on CPUs that didn't know about it yet */
+            openpic_set_irq(opp, irq, 1);
+            openpic_set_irq(opp, irq, 0);
+            /* if all CPUs knew about it, set active bit again */
+            src->ivpr |= IVPR_ACTIVITY_MASK;
+        }
+    }
+
+    return retval;
+}
+
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                                           int idx)
 {
     OpenPICState *opp = opaque;
-    IRQSource *src;
     IRQDest *dst;
     uint32_t retval;
-    int n_IRQ;
 
     DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
@@ -1004,46 +1054,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         retval = idx;
         break;
     case 0xA0: /* IACK */
-        DPRINTF("Lower OpenPIC INT output\n");
-        qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
-        n_IRQ = IRQ_get_next(opp, &dst->raised);
-        DPRINTF("IACK: irq=%d\n", n_IRQ);
-        if (n_IRQ == -1) {
-            /* No more interrupt pending */
-            retval = opp->spve;
-        } else {
-            src = &opp->src[n_IRQ];
-            if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
-                !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
-                /* - Spurious level-sensitive IRQ
-                 * - Priorities has been changed
-                 *   and the pending IRQ isn't allowed anymore
-                 */
-                src->ivpr &= ~IVPR_ACTIVITY_MASK;
-                retval = opp->spve;
-            } else {
-                /* IRQ enter servicing state */
-                IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IVPR_VECTOR(opp, src->ivpr);
-            }
-            IRQ_resetbit(&dst->raised, n_IRQ);
-            if (!src->level) {
-                /* edge-sensitive IRQ */
-                src->ivpr &= ~IVPR_ACTIVITY_MASK;
-                src->pending = 0;
-            }
-
-            if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
-                src->idr &= ~(1 << idx);
-                if (src->idr && !src->level) {
-                    /* trigger on CPUs that didn't know about it yet */
-                    openpic_set_irq(opp, n_IRQ, 1);
-                    openpic_set_irq(opp, n_IRQ, 0);
-                    /* if all CPUs knew about it, set active bit again */
-                    src->ivpr |= IVPR_ACTIVITY_MASK;
-                }
-            }
-        }
+        retval = openpic_iack(opp, dst, idx);
         break;
     case 0xB0: /* EOI */
         retval = 0;
commit 4417c73305f60e46a2370bcaf3635981f5dbc050
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Jan 3 13:25:38 2013 +0000

    openpic: IRQ_check: search the queue a word at a time
    
    Search the queue more efficiently by first looking for a non-zero word,
    and then using the common bit-searching function to find the bit within
    the word.  It would be even nicer if bitops_ffsl() could be hooked up
    to the compiler intrinsic so that bit-searching instructions could be
    used, but that's another matter.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 66179c2..7645d67 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -277,21 +277,25 @@ static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 
 static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 {
-    int next, i;
-    int priority;
+    int irq = -1;
+    int next = -1;
+    int priority = -1;
 
-    next = -1;
-    priority = -1;
-    for (i = 0; i < opp->max_irq; i++) {
-        if (IRQ_testbit(q, i)) {
-            DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
-                    i, IVPR_PRIORITY(opp->src[i].ivpr), priority);
-            if (IVPR_PRIORITY(opp->src[i].ivpr) > priority) {
-                next = i;
-                priority = IVPR_PRIORITY(opp->src[i].ivpr);
-            }
+    for (;;) {
+        irq = find_next_bit(q->queue, opp->max_irq, irq + 1);
+        if (irq == opp->max_irq) {
+            break;
+        }
+
+        DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
+                irq, IVPR_PRIORITY(opp->src[irq].ivpr), priority);
+
+        if (IVPR_PRIORITY(opp->src[irq].ivpr) > priority) {
+            next = irq;
+            priority = IVPR_PRIORITY(opp->src[irq].ivpr);
         }
     }
+
     q->next = next;
     q->priority = priority;
 }
commit 6c5e84c25fc70717c410150b23c765bedf0af52d
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Jan 3 13:25:37 2013 +0000

    openpic: fix sense and priority bits
    
    Previously, the sense and priority bits were masked off when writing
    to IVPR, and all interrupts were treated as edge-triggered (despite
    the existence of code for handling level-triggered interrupts).
    
    Polarity is implemented only as storage.  We don't simulate the
    bad effects that you'd get on real hardware if you set this incorrectly,
    but at least the guest sees the right thing when it reads back the register.
    
    Sense now controls level/edge on FSL external interrupts (and all
    interrupts on non-FSL MPIC).  FSL internal interrupts do not have a sense
    bit (reads as zero), but are level.  FSL timers and IPIs do not have
    sense or polarity bits (read as zero), and are edge-triggered.  To
    accommodate FSL internal interrupts, QEMU's internal notion of whether an
    interrupt is level-triggered is separated from the IVPR bit.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 35a7fe3..66179c2 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -162,6 +162,12 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
+typedef enum IRQType {
+    IRQ_TYPE_NORMAL = 0,
+    IRQ_TYPE_FSLINT,        /* FSL internal interrupt -- level only */
+    IRQ_TYPE_FSLSPECIAL,    /* FSL timer/IPI interrupt, edge, no polarity */
+} IRQType;
+
 typedef struct IRQQueue {
     /* Round up to the nearest 64 IRQs so that the queue length
      * won't change when moving between 32 and 64 bit hosts.
@@ -178,6 +184,8 @@ typedef struct IRQSource {
     int last_cpu;
     int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
+    IRQType type;
+    bool level:1;   /* level-triggered */
     bool nomask:1;  /* critical interrupts ignore mask on some FSL MPICs */
 } IRQSource;
 
@@ -422,7 +430,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
             n_IRQ, level, src->ivpr);
-    if (src->ivpr & IVPR_SENSE_MASK) {
+    if (src->level) {
         /* level-sensitive irq */
         src->pending = level;
         if (!level) {
@@ -455,6 +463,19 @@ static void openpic_reset(DeviceState *d)
     for (i = 0; i < opp->max_irq; i++) {
         opp->src[i].ivpr = opp->ivpr_reset;
         opp->src[i].idr  = opp->idr_reset;
+
+        switch (opp->src[i].type) {
+        case IRQ_TYPE_NORMAL:
+            opp->src[i].level = !!(opp->ivpr_reset & IVPR_SENSE_MASK);
+            break;
+
+        case IRQ_TYPE_FSLINT:
+            opp->src[i].ivpr |= IVPR_POLARITY_MASK;
+            break;
+
+        case IRQ_TYPE_FSLSPECIAL:
+            break;
+        }
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
@@ -530,10 +551,36 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 
 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
-    /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
+    uint32_t mask;
+
+    /* NOTE when implementing newer FSL MPIC models: starting with v4.0,
+     * the polarity bit is read-only on internal interrupts.
+     */
+    mask = IVPR_MASK_MASK | IVPR_PRIORITY_MASK | IVPR_SENSE_MASK |
+           IVPR_POLARITY_MASK | opp->vector_mask;
+
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ivpr = (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) |
-        (val & (IVPR_MASK_MASK | IVPR_PRIORITY_MASK | opp->vector_mask));
+    opp->src[n_IRQ].ivpr =
+        (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) | (val & mask);
+
+    /* For FSL internal interrupts, The sense bit is reserved and zero,
+     * and the interrupt is always level-triggered.  Timers and IPIs
+     * have no sense or polarity bits, and are edge-triggered.
+     */
+    switch (opp->src[n_IRQ].type) {
+    case IRQ_TYPE_NORMAL:
+        opp->src[n_IRQ].level = !!(opp->src[n_IRQ].ivpr & IVPR_SENSE_MASK);
+        break;
+
+    case IRQ_TYPE_FSLINT:
+        opp->src[n_IRQ].ivpr &= ~IVPR_SENSE_MASK;
+        break;
+
+    case IRQ_TYPE_FSLSPECIAL:
+        opp->src[n_IRQ].ivpr &= ~(IVPR_POLARITY_MASK | IVPR_SENSE_MASK);
+        break;
+    }
+
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ivpr);
@@ -976,7 +1023,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                 retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
-            if (!(src->ivpr & IVPR_SENSE_MASK)) {
+            if (!src->level) {
                 /* edge-sensitive IRQ */
                 src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 src->pending = 0;
@@ -984,7 +1031,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 
             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
                 src->idr &= ~(1 << idx);
-                if (src->idr && !(src->ivpr & IVPR_SENSE_MASK)) {
+                if (src->idr && !src->level) {
                     /* trigger on CPUs that didn't know about it yet */
                     openpic_set_irq(opp, n_IRQ, 1);
                     openpic_set_irq(opp, n_IRQ, 0);
@@ -1282,7 +1329,25 @@ static int openpic_init(SysBusDevice *dev)
         opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
         msi_supported = true;
         list = list_be;
+
+        for (i = 0; i < FSL_MPIC_20_MAX_EXT; i++) {
+            opp->src[i].level = false;
+        }
+
+        /* Internal interrupts, including message and MSI */
+        for (i = 16; i < MAX_SRC; i++) {
+            opp->src[i].type = IRQ_TYPE_FSLINT;
+            opp->src[i].level = true;
+        }
+
+        /* timers and IPIs */
+        for (i = MAX_SRC; i < MAX_IRQ; i++) {
+            opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
+            opp->src[i].level = false;
+        }
+
         break;
+
     case OPENPIC_MODEL_RAVEN:
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
commit 65b9d0d5659687ebb85b1305ac70b3a84df16e5a
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:50 2012 +0000

    openpic: add some bounds checking for IRQ numbers
    
    The two checks with abort() guard against potential QEMU-internal
    problems, but the EOI check stops the guest from causing updates to queue
    position -1 and other havoc if it writes EOI with no interrupt in
    service.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    [agraf: remove hunk in code that didn't get applied yet]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index b54308d..35a7fe3 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -414,6 +414,11 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     OpenPICState *opp = opaque;
     IRQSource *src;
 
+    if (n_IRQ >= MAX_IRQ) {
+        fprintf(stderr, "%s: IRQ %d out of range\n", __func__, n_IRQ);
+        abort();
+    }
+
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
             n_IRQ, level, src->ivpr);
@@ -888,6 +893,12 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     case 0xB0: /* EOI */
         DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
+
+        if (s_IRQ < 0) {
+            DPRINTF("%s: EOI with no interrupt in service\n", __func__);
+            break;
+        }
+
         IRQ_resetbit(&dst->servicing, s_IRQ);
         /* Set up next servicing IRQ */
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
commit e69a17f65e9f12f33c48b04a789e49d40a8993f5
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:48 2012 +0000

    openpic: use standard bitmap operations
    
    Besides the private implementation being redundant, namespace collisions
    prevented the use of other things in bitops.h.
    
    Serialization does get a bit more awkward, unfortunately, since the
    standard bitmap operations are "unsigned long" rather than "uint32_t",
    though in exchange we will get faster queue lookups on 64-bit hosts once
    we search a word at a time.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 2c238fb..b54308d 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -39,6 +39,7 @@
 #include "openpic.h"
 #include "sysbus.h"
 #include "pci/msi.h"
+#include "qemu/bitops.h"
 
 //#define DEBUG_OPENPIC
 
@@ -147,24 +148,6 @@ static const int debug_openpic = 0;
 #define MSIIR_IBS_SHIFT    24
 #define MSIIR_IBS_MASK     (0x1f << MSIIR_IBS_SHIFT)
 
-#define BF_WIDTH(_bits_) \
-(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
-
-static inline void set_bit(uint32_t *field, int bit)
-{
-    field[bit >> 5] |= 1 << (bit & 0x1F);
-}
-
-static inline void reset_bit(uint32_t *field, int bit)
-{
-    field[bit >> 5] &= ~(1 << (bit & 0x1F));
-}
-
-static inline int test_bit(uint32_t *field, int bit)
-{
-    return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
-}
-
 static int get_current_cpu(void)
 {
     if (!cpu_single_env) {
@@ -180,7 +163,10 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
 typedef struct IRQQueue {
-    uint32_t queue[BF_WIDTH(MAX_IRQ)];
+    /* Round up to the nearest 64 IRQs so that the queue length
+     * won't change when moving between 32 and 64 bit hosts.
+     */
+    unsigned long queue[BITS_TO_LONGS((MAX_IRQ + 63) & ~63)];
     int next;
     int priority;
 } IRQQueue;
@@ -268,17 +254,17 @@ typedef struct OpenPICState {
 
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
-    set_bit(q->queue, n_IRQ);
+    set_bit(n_IRQ, q->queue);
 }
 
 static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
-    reset_bit(q->queue, n_IRQ);
+    clear_bit(n_IRQ, q->queue);
 }
 
 static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 {
-    return test_bit(q->queue, n_IRQ);
+    return test_bit(n_IRQ, q->queue);
 }
 
 static void IRQ_check(OpenPICState *opp, IRQQueue *q)
@@ -1117,8 +1103,16 @@ static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
-    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
-        qemu_put_be32s(f, &q->queue[i]);
+    for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+        /* Always put the lower half of a 64-bit long first, in case we
+         * restore on a 32-bit host.  The least significant bits correspond
+         * to lower IRQ numbers in the bitmap.
+         */
+        qemu_put_be32(f, (uint32_t)q->queue[i]);
+#if LONG_MAX > 0x7FFFFFFF
+        qemu_put_be32(f, (uint32_t)(q->queue[i] >> 32));
+#endif
+    }
 
     qemu_put_sbe32s(f, &q->next);
     qemu_put_sbe32s(f, &q->priority);
@@ -1160,8 +1154,17 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
-    for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
-        qemu_get_be32s(f, &q->queue[i]);
+    for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+        unsigned long val;
+
+        val = qemu_get_be32(f);
+#if LONG_MAX > 0x7FFFFFFF
+        val <<= 32;
+        val |= qemu_get_be32(f);
+#endif
+
+        q->queue[i] = val;
+    }
 
     qemu_get_sbe32s(f, &q->next);
     qemu_get_sbe32s(f, &q->priority);
commit 47f73749c61765f7a898ac88f11995368740da10
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:47 2012 +0000

    Revert "openpic: Accelerate pending irq search"
    
    This reverts commit a9bd83f4c65de0058659ede009fa1a241f379edd.
    
    This counting approach is not robust against setting a bit that
    was already set, or clearing a bit that was already clear.  Perhaps
    that is considered a bug, but besides the lack of any documentation
    for that restriction, it's a pretty unpleasant way for the problem
    to manifest itself.
    
    It could be made more robust by testing the current value of the
    bit before changing the count, but a later patch speeds up IRQ_check
    in all cases, not just when there's nothing pending.  Hopefully that
    should be adequate to address performance concerns.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 19e6280..2c238fb 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -183,7 +183,6 @@ typedef struct IRQQueue {
     uint32_t queue[BF_WIDTH(MAX_IRQ)];
     int next;
     int priority;
-    int pending;    /* nr of pending bits in queue */
 } IRQQueue;
 
 typedef struct IRQSource {
@@ -269,13 +268,11 @@ typedef struct OpenPICState {
 
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
-    q->pending++;
     set_bit(q->queue, n_IRQ);
 }
 
 static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
-    q->pending--;
     reset_bit(q->queue, n_IRQ);
 }
 
@@ -291,12 +288,6 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 
     next = -1;
     priority = -1;
-
-    if (!q->pending) {
-        /* IRQ bitmap is empty */
-        goto out;
-    }
-
     for (i = 0; i < opp->max_irq; i++) {
         if (IRQ_testbit(q, i)) {
             DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
@@ -307,8 +298,6 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
             }
         }
     }
-
-out:
     q->next = next;
     q->priority = priority;
 }
commit 3c94378e2c500b6211e95d7457f4a9959955c3d1
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:46 2012 +0000

    openpic: always call IRQ_check from IRQ_get_next
    
    Previously the code relied on the queue's "next" field getting
    set to -1 sometime between an update to the bitmap, and the next
    call to IRQ_get_next.  Sometimes this happened after the update.
    Sometimes it happened before the check.  Sometimes it didn't happen
    at all.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index ac5027a..19e6280 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -315,10 +315,8 @@ out:
 
 static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
 {
-    if (q->next == -1) {
-        /* XXX: optimize */
-        IRQ_check(opp, q);
-    }
+    /* XXX: optimize */
+    IRQ_check(opp, q);
 
     return q->next;
 }
@@ -365,7 +363,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
                 __func__, n_IRQ, dst->raised.next, n_CPU);
         return;
     }
-    IRQ_get_next(opp, &dst->raised);
+    IRQ_check(opp, &dst->raised);
     if (IRQ_get_next(opp, &dst->servicing) != -1 &&
         priority <= dst->servicing.priority) {
         DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
@@ -916,7 +914,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         IRQ_resetbit(&dst->servicing, s_IRQ);
-        dst->servicing.next = -1;
         /* Set up next servicing IRQ */
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         /* Check queued interrupts. */
@@ -993,7 +990,6 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                 retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
-            dst->raised.next = -1;
             if (!(src->ivpr & IVPR_SENSE_MASK)) {
                 /* edge-sensitive IRQ */
                 src->ivpr &= ~IVPR_ACTIVITY_MASK;
commit 72c1da2ca72af50e6536d0cd9c6db758f66cd7c2
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:45 2012 +0000

    openpic/fsl: critical interrupts ignore mask before v4.1
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    [agraf: make bool :1]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 824b8fd..ac5027a 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -193,6 +193,7 @@ typedef struct IRQSource {
     int last_cpu;
     int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
+    bool nomask:1;  /* critical interrupts ignore mask on some FSL MPICs */
 } IRQSource;
 
 #define IVPR_MASK_SHIFT       31
@@ -389,7 +390,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
-    if (src->ivpr & IVPR_MASK_MASK) {
+    if ((src->ivpr & IVPR_MASK_MASK) && !src->nomask) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
         return;
@@ -529,6 +530,7 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
             }
 
             src->output = OPENPIC_OUTPUT_CINT;
+            src->nomask = true;
             src->destmask = 0;
 
             for (i = 0; i < opp->nb_cpus; i++) {
@@ -540,6 +542,7 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
             }
         } else {
             src->output = OPENPIC_OUTPUT_INT;
+            src->nomask = false;
             src->destmask = src->idr & normal_mask;
         }
     } else {
commit eb4384278417297661663c54e01c0f0ffec0a9e3
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:44 2012 +0000

    openpic: make ctpr signed
    
    Other priorities are signed, so avoid comparisons between
    signed and unsigned.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index fe6cf67..824b8fd 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -215,7 +215,7 @@ typedef struct IRQSource {
 #define IDR_CI      0x40000000  /* critical interrupt */
 
 typedef struct IRQDest {
-    uint32_t ctpr; /* CPU current task priority */
+    int32_t ctpr; /* CPU current task priority */
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
@@ -1150,7 +1150,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_put_be32s(f, &opp->dst[i].ctpr);
+        qemu_put_sbe32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
@@ -1197,7 +1197,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_get_be32s(f, &opp->dst[i].ctpr);
+        qemu_get_sbe32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
commit 5e22c276de982dd26ebc4424c8d4592cce1baab9
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:43 2012 +0000

    openpic: rework critical interrupt support
    
    Critical interrupts on FSL MPIC are not supposed to pay
    attention to priority, IACK, EOI, etc.  On the currently modeled
    version it's not supposed to pay attention to the mask bit either.
    
    Also reorganize to make it easier to implement newer FSL MPIC models,
    which encode interrupt level information differently and support
    mcheck as well as crit, and to reduce problems for later patches
    in this set.
    
    Still missing is the ability to lower the CINT signal to the core,
    as IACK/EOI is not used.  This will come with general IRQ-source-driven
    lowering in the next patch.
    
    New state is added which is not serialized, but instead is recomputed
    in openpic_load() by calling the appropriate write_IRQreg function.
    This should have the side effect of causing the IRQ outputs to be
    raised appropriately on load, which was missing.
    
    The serialization format is altered by swapping ivpr and idr (we'd like
    IDR to be restored before we run the IVPR logic), and moving interrupts
    to the end (so that other state has been restored by the time we run the
    IDR/IVPR logic.  Serialization for this driver is not yet in a state
    where backwards compatibility is reasonable (assuming it works at all),
    and the current serialization format was not built for extensibility.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    [agraf: fix for current code state]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 6362497..fe6cf67 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -189,7 +189,9 @@ typedef struct IRQQueue {
 typedef struct IRQSource {
     uint32_t ivpr;  /* IRQ vector/priority register */
     uint32_t idr;   /* IRQ destination register */
+    uint32_t destmask; /* bitmap of CPU destinations */
     int last_cpu;
+    int output;     /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
     int pending;    /* TRUE if IRQ is pending */
 } IRQSource;
 
@@ -264,8 +266,6 @@ typedef struct OpenPICState {
     uint32_t irq_msi;
 } OpenPICState;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src);
-
 static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
     q->pending++;
@@ -330,6 +330,19 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
+
+    if (src->output != OPENPIC_OUTPUT_INT) {
+        /* On Freescale MPIC, critical interrupts ignore priority,
+         * IACK, EOI, etc.  Before MPIC v4.1 they also ignore
+         * masking.
+         */
+        src->ivpr |= IVPR_ACTIVITY_MASK;
+        DPRINTF("%s: Raise OpenPIC output %d cpu %d irq %d\n",
+                __func__, src->output, n_CPU, n_IRQ);
+        qemu_irq_raise(opp->dst[n_CPU].irqs[src->output]);
+        return;
+    }
+
     priority = IVPR_PRIORITY(src->ivpr);
     if (priority <= dst->ctpr) {
         /* Too low priority */
@@ -360,7 +373,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
         return;
     }
     DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
-    openpic_irq_raise(opp, n_CPU, src);
+    qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
@@ -403,7 +416,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
     } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
-            if (src->idr & (1 << i)) {
+            if (src->destmask & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
             }
         }
@@ -413,7 +426,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
             if (i == opp->nb_cpus) {
                 i = 0;
             }
-            if (src->idr & (1 << i)) {
+            if (src->destmask & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
                 break;
@@ -493,12 +506,45 @@ static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
 
 static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
-    uint32_t tmp;
+    IRQSource *src = &opp->src[n_IRQ];
+    uint32_t normal_mask = (1UL << opp->nb_cpus) - 1;
+    uint32_t crit_mask = 0;
+    uint32_t mask = normal_mask;
+    int crit_shift = IDR_EP_SHIFT - opp->nb_cpus;
+    int i;
+
+    if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
+        crit_mask = mask << crit_shift;
+        mask |= crit_mask | IDR_EP;
+    }
+
+    src->idr = val & mask;
+    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, src->idr);
+
+    if (opp->flags & OPENPIC_FLAG_IDR_CRIT) {
+        if (src->idr & crit_mask) {
+            if (src->idr & normal_mask) {
+                DPRINTF("%s: IRQ configured for multiple output types, using "
+                        "critical\n", __func__);
+            }
+
+            src->output = OPENPIC_OUTPUT_CINT;
+            src->destmask = 0;
+
+            for (i = 0; i < opp->nb_cpus; i++) {
+                int n_ci = IDR_CI0_SHIFT - i;
 
-    tmp = val & (IDR_EP | IDR_CI);
-    tmp |= val & ((1ULL << MAX_CPU) - 1);
-    opp->src[n_IRQ].idr = tmp;
-    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].idr);
+                if (src->idr & (1UL << n_ci)) {
+                    src->destmask |= 1UL << i;
+                }
+            }
+        } else {
+            src->output = OPENPIC_OUTPUT_INT;
+            src->destmask = src->idr & normal_mask;
+        }
+    } else {
+        src->destmask = src->idr;
+    }
 }
 
 static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
@@ -878,7 +924,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
              IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
                     idx, n_IRQ);
-            openpic_irq_raise(opp, idx, src);
+            qemu_irq_raise(opp->dst[idx].irqs[OPENPIC_OUTPUT_INT]);
         }
         break;
     default:
@@ -1101,13 +1147,6 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->spve);
     qemu_put_be32s(f, &opp->tfrr);
 
-    for (i = 0; i < opp->max_irq; i++) {
-        qemu_put_be32s(f, &opp->src[i].ivpr);
-        qemu_put_be32s(f, &opp->src[i].idr);
-        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
-        qemu_put_sbe32s(f, &opp->src[i].pending);
-    }
-
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
@@ -1120,6 +1159,13 @@ static void openpic_save(QEMUFile* f, void *opaque)
         qemu_put_be32s(f, &opp->timers[i].tccr);
         qemu_put_be32s(f, &opp->timers[i].tbcr);
     }
+
+    for (i = 0; i < opp->max_irq; i++) {
+        qemu_put_be32s(f, &opp->src[i].ivpr);
+        qemu_put_be32s(f, &opp->src[i].idr);
+        qemu_put_sbe32s(f, &opp->src[i].last_cpu);
+        qemu_put_sbe32s(f, &opp->src[i].pending);
+    }
 }
 
 static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
@@ -1148,13 +1194,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->spve);
     qemu_get_be32s(f, &opp->tfrr);
 
-    for (i = 0; i < opp->max_irq; i++) {
-        qemu_get_be32s(f, &opp->src[i].ivpr);
-        qemu_get_be32s(f, &opp->src[i].idr);
-        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
-        qemu_get_sbe32s(f, &opp->src[i].pending);
-    }
-
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
@@ -1168,18 +1207,21 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         qemu_get_be32s(f, &opp->timers[i].tbcr);
     }
 
-    return 0;
-}
+    for (i = 0; i < opp->max_irq; i++) {
+        uint32_t val;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
-{
-    int n_ci = IDR_CI0_SHIFT - n_CPU;
+        val = qemu_get_be32(f);
+        write_IRQreg_idr(opp, i, val);
+        val = qemu_get_be32(f);
+        write_IRQreg_ivpr(opp, i, val);
 
-    if ((opp->flags & OPENPIC_FLAG_IDR_CRIT) && (src->idr & (1 << n_ci))) {
-        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
-    } else {
-        qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
+        qemu_get_be32s(f, &opp->src[i].ivpr);
+        qemu_get_be32s(f, &opp->src[i].idr);
+        qemu_get_sbe32s(f, &opp->src[i].last_cpu);
+        qemu_get_sbe32s(f, &opp->src[i].pending);
     }
+
+    return 0;
 }
 
 typedef struct MemReg {
commit be7c236fa2e59090d7cd0193ca3f225c331d5f81
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:42 2012 +0000

    openpic: make register names correspond better with hw docs
    
    The base openpic specification doesn't provide abbreviated register
    names, so it's somewhat understandable that the QEMU code made up
    its own, except that most of the names that QEMU used didn't correspond
    to the terminology used by any implementation I could find.
    
    In some cases, like PCTP, the phrase "processor current task priority"
    could be found in the openpic spec when describing the concept, but
    the register itself was labelled "current task priority register"
    and every implementation seems to use either CTPR or the full phrase.
    
    In other cases, individual implementations disagree on what to call
    the register.  The implementations I have documentation for are
    Freescale, Raven (MCP750), and IBM.  The Raven docs tend to not use
    abbreviations at all.  The IBM MPIC isn't implemented in QEMU.  Thus,
    where there's disagreement I chose to use the Freescale abbreviations.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    [agraf: rebase on current state of the code]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index f4df66d..6362497 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -63,7 +63,7 @@ static const int debug_openpic = 0;
 #define VID         0x03 /* MPIC version ID */
 
 /* OpenPIC capability flags */
-#define OPENPIC_FLAG_IDE_CRIT     (1 << 0)
+#define OPENPIC_FLAG_IDR_CRIT     (1 << 0)
 
 /* OpenPIC address map */
 #define OPENPIC_GLB_REG_START        0x0
@@ -120,19 +120,19 @@ static const int debug_openpic = 0;
 #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
 #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
 
-#define FREP_NIRQ_SHIFT   16
-#define FREP_NCPU_SHIFT    8
-#define FREP_VID_SHIFT     0
+#define FRR_NIRQ_SHIFT    16
+#define FRR_NCPU_SHIFT     8
+#define FRR_VID_SHIFT      0
 
 #define VID_REVISION_1_2   2
 #define VID_REVISION_1_3   3
 
-#define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
+#define VIR_GENERIC      0x00000000 /* Generic Vendor ID */
 
-#define GLBC_RESET        0x80000000
+#define GCR_RESET        0x80000000
 
-#define TIBC_CI           0x80000000 /* count inhibit */
-#define TICC_TOG          0x80000000 /* toggles when decrement to zero */
+#define TBCR_CI           0x80000000 /* count inhibit */
+#define TCCR_TOG          0x80000000 /* toggles when decrement to zero */
 
 #define IDR_EP_SHIFT      31
 #define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
@@ -187,33 +187,33 @@ typedef struct IRQQueue {
 } IRQQueue;
 
 typedef struct IRQSource {
-    uint32_t ipvp;  /* IRQ vector/priority register */
-    uint32_t ide;   /* IRQ destination register */
+    uint32_t ivpr;  /* IRQ vector/priority register */
+    uint32_t idr;   /* IRQ destination register */
     int last_cpu;
     int pending;    /* TRUE if IRQ is pending */
 } IRQSource;
 
-#define IPVP_MASK_SHIFT       31
-#define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
-#define IPVP_ACTIVITY_SHIFT   30
-#define IPVP_ACTIVITY_MASK    (1 << IPVP_ACTIVITY_SHIFT)
-#define IPVP_MODE_SHIFT       29
-#define IPVP_MODE_MASK        (1 << IPVP_MODE_SHIFT)
-#define IPVP_POLARITY_SHIFT   23
-#define IPVP_POLARITY_MASK    (1 << IPVP_POLARITY_SHIFT)
-#define IPVP_SENSE_SHIFT      22
-#define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
-
-#define IPVP_PRIORITY_MASK     (0xF << 16)
-#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
-#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
-
-/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
-#define IDE_EP      0x80000000  /* external pin */
-#define IDE_CI      0x40000000  /* critical interrupt */
+#define IVPR_MASK_SHIFT       31
+#define IVPR_MASK_MASK        (1 << IVPR_MASK_SHIFT)
+#define IVPR_ACTIVITY_SHIFT   30
+#define IVPR_ACTIVITY_MASK    (1 << IVPR_ACTIVITY_SHIFT)
+#define IVPR_MODE_SHIFT       29
+#define IVPR_MODE_MASK        (1 << IVPR_MODE_SHIFT)
+#define IVPR_POLARITY_SHIFT   23
+#define IVPR_POLARITY_MASK    (1 << IVPR_POLARITY_SHIFT)
+#define IVPR_SENSE_SHIFT      22
+#define IVPR_SENSE_MASK       (1 << IVPR_SENSE_SHIFT)
+
+#define IVPR_PRIORITY_MASK     (0xF << 16)
+#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
+#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
+
+/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
+#define IDR_EP      0x80000000  /* external pin */
+#define IDR_CI      0x40000000  /* critical interrupt */
 
 typedef struct IRQDest {
-    uint32_t pctp; /* CPU current task priority */
+    uint32_t ctpr; /* CPU current task priority */
     IRQQueue raised;
     IRQQueue servicing;
     qemu_irq *irqs;
@@ -228,22 +228,22 @@ typedef struct OpenPICState {
     uint32_t flags;
     uint32_t nb_irqs;
     uint32_t vid;
-    uint32_t veni; /* Vendor identification register */
+    uint32_t vir; /* Vendor identification register */
     uint32_t vector_mask;
-    uint32_t tifr_reset;
-    uint32_t ipvp_reset;
-    uint32_t ide_reset;
+    uint32_t tfrr_reset;
+    uint32_t ivpr_reset;
+    uint32_t idr_reset;
     uint32_t brr1;
 
     /* Sub-regions */
     MemoryRegion sub_io_mem[5];
 
     /* Global registers */
-    uint32_t frep; /* Feature reporting register */
-    uint32_t glbc; /* Global configuration register  */
-    uint32_t pint; /* Processor initialization register */
+    uint32_t frr; /* Feature reporting register */
+    uint32_t gcr; /* Global configuration register  */
+    uint32_t pir; /* Processor initialization register */
     uint32_t spve; /* Spurious vector register */
-    uint32_t tifr; /* Timer frequency reporting register */
+    uint32_t tfrr; /* Timer frequency reporting register */
     /* Source registers */
     IRQSource src[MAX_IRQ];
     /* Local registers per output pin */
@@ -251,8 +251,8 @@ typedef struct OpenPICState {
     uint32_t nb_cpus;
     /* Timer registers */
     struct {
-        uint32_t ticc;  /* Global timer current count register */
-        uint32_t tibc;  /* Global timer base count register */
+        uint32_t tccr;  /* Global timer current count register */
+        uint32_t tbcr;  /* Global timer base count register */
     } timers[MAX_TMR];
     /* Shared MSI registers */
     struct {
@@ -298,11 +298,11 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 
     for (i = 0; i < opp->max_irq; i++) {
         if (IRQ_testbit(q, i)) {
-            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
-                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
-            if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
+            DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
+                    i, IVPR_PRIORITY(opp->src[i].ivpr), priority);
+            if (IVPR_PRIORITY(opp->src[i].ivpr) > priority) {
                 next = i;
-                priority = IPVP_PRIORITY(opp->src[i].ipvp);
+                priority = IVPR_PRIORITY(opp->src[i].ivpr);
             }
         }
     }
@@ -330,8 +330,8 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 
     dst = &opp->dst[n_CPU];
     src = &opp->src[n_IRQ];
-    priority = IPVP_PRIORITY(src->ipvp);
-    if (priority <= dst->pctp) {
+    priority = IVPR_PRIORITY(src->ivpr);
+    if (priority <= dst->ctpr) {
         /* Too low priority */
         DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
                 __func__, n_IRQ, n_CPU);
@@ -343,7 +343,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
                 __func__, n_IRQ, n_CPU);
         return;
     }
-    src->ipvp |= IPVP_ACTIVITY_MASK;
+    src->ivpr |= IVPR_ACTIVITY_MASK;
     IRQ_setbit(&dst->raised, n_IRQ);
     if (priority < dst->raised.priority) {
         /* An higher priority IRQ is already raised */
@@ -376,34 +376,34 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
-    if (src->ipvp & IPVP_MASK_MASK) {
+    if (src->ivpr & IVPR_MASK_MASK) {
         /* Interrupt source is disabled */
         DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
         return;
     }
-    if (IPVP_PRIORITY(src->ipvp) == 0) {
+    if (IVPR_PRIORITY(src->ivpr) == 0) {
         /* Priority set to zero */
         DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
         return;
     }
-    if (src->ipvp & IPVP_ACTIVITY_MASK) {
+    if (src->ivpr & IVPR_ACTIVITY_MASK) {
         /* IRQ already active */
         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
-    if (src->ide == 0) {
+    if (src->idr == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
         return;
     }
 
-    if (src->ide == (1 << src->last_cpu)) {
+    if (src->idr == (1 << src->last_cpu)) {
         /* Only one CPU is allowed to receive this IRQ */
         IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
-    } else if (!(src->ipvp & IPVP_MODE_MASK)) {
+    } else if (!(src->ivpr & IVPR_MODE_MASK)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
-            if (src->ide & (1 << i)) {
+            if (src->idr & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
             }
         }
@@ -413,7 +413,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
             if (i == opp->nb_cpus) {
                 i = 0;
             }
-            if (src->ide & (1 << i)) {
+            if (src->idr & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
                 break;
@@ -428,13 +428,13 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     IRQSource *src;
 
     src = &opp->src[n_IRQ];
-    DPRINTF("openpic: set irq %d = %d ipvp=0x%08x\n",
-            n_IRQ, level, src->ipvp);
-    if (src->ipvp & IPVP_SENSE_MASK) {
+    DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
+            n_IRQ, level, src->ivpr);
+    if (src->ivpr & IVPR_SENSE_MASK) {
         /* level-sensitive irq */
         src->pending = level;
         if (!level) {
-            src->ipvp &= ~IPVP_ACTIVITY_MASK;
+            src->ivpr &= ~IVPR_ACTIVITY_MASK;
         }
     } else {
         /* edge-sensitive irq */
@@ -450,23 +450,23 @@ static void openpic_reset(DeviceState *d)
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
     int i;
 
-    opp->glbc = GLBC_RESET;
+    opp->gcr = GCR_RESET;
     /* Initialise controller registers */
-    opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
-                ((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
-                (opp->vid << FREP_VID_SHIFT);
+    opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
+               ((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
+               (opp->vid << FRR_VID_SHIFT);
 
-    opp->pint = 0;
+    opp->pir = 0;
     opp->spve = -1 & opp->vector_mask;
-    opp->tifr = opp->tifr_reset;
+    opp->tfrr = opp->tfrr_reset;
     /* Initialise IRQ sources */
     for (i = 0; i < opp->max_irq; i++) {
-        opp->src[i].ipvp = opp->ipvp_reset;
-        opp->src[i].ide  = opp->ide_reset;
+        opp->src[i].ivpr = opp->ivpr_reset;
+        opp->src[i].idr  = opp->idr_reset;
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
-        opp->dst[i].pctp      = 15;
+        opp->dst[i].ctpr      = 15;
         memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
         opp->dst[i].raised.next = -1;
         memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
@@ -474,42 +474,42 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise timers */
     for (i = 0; i < MAX_TMR; i++) {
-        opp->timers[i].ticc = 0;
-        opp->timers[i].tibc = TIBC_CI;
+        opp->timers[i].tccr = 0;
+        opp->timers[i].tbcr = TBCR_CI;
     }
     /* Go out of RESET state */
-    opp->glbc = 0;
+    opp->gcr = 0;
 }
 
-static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
 {
-    return opp->src[n_IRQ].ide;
+    return opp->src[n_IRQ].idr;
 }
 
-static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
 {
-    return opp->src[n_IRQ].ipvp;
+    return opp->src[n_IRQ].ivpr;
 }
 
-static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     uint32_t tmp;
 
-    tmp = val & (IDE_EP | IDE_CI);
+    tmp = val & (IDR_EP | IDR_CI);
     tmp |= val & ((1ULL << MAX_CPU) - 1);
-    opp->src[n_IRQ].ide = tmp;
-    DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
+    opp->src[n_IRQ].idr = tmp;
+    DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].idr);
 }
 
-static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
-        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
+    opp->src[n_IRQ].ivpr = (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) |
+        (val & (IVPR_MASK_MASK | IVPR_PRIORITY_MASK | opp->vector_mask));
     openpic_update_irq(opp, n_IRQ);
-    DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
-            opp->src[n_IRQ].ipvp);
+    DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
+            opp->src[n_IRQ].ivpr);
 }
 
 static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
@@ -537,37 +537,37 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0xB0:
         openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
         break;
-    case 0x1000: /* FREP */
+    case 0x1000: /* FRR */
         break;
-    case 0x1020: /* GLBC */
-        if (val & GLBC_RESET) {
+    case 0x1020: /* GCR */
+        if (val & GCR_RESET) {
             openpic_reset(&opp->busdev.qdev);
         }
         break;
-    case 0x1080: /* VENI */
+    case 0x1080: /* VIR */
         break;
-    case 0x1090: /* PINT */
+    case 0x1090: /* PIR */
         for (idx = 0; idx < opp->nb_cpus; idx++) {
-            if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
+            if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
                 DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
                 dst = &opp->dst[idx];
                 qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
-            } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
+            } else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) {
                 DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
                 dst = &opp->dst[idx];
                 qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
             }
         }
-        opp->pint = val;
+        opp->pir = val;
         break;
-    case 0x10A0: /* IPI_IPVP */
+    case 0x10A0: /* IPI_IVPR */
     case 0x10B0:
     case 0x10C0:
     case 0x10D0:
         {
             int idx;
             idx = (addr - 0x10A0) >> 4;
-            write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
+            write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
         }
         break;
     case 0x10E0: /* SPVE */
@@ -589,16 +589,16 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
         return retval;
     }
     switch (addr) {
-    case 0x1000: /* FREP */
-        retval = opp->frep;
+    case 0x1000: /* FRR */
+        retval = opp->frr;
         break;
-    case 0x1020: /* GLBC */
-        retval = opp->glbc;
+    case 0x1020: /* GCR */
+        retval = opp->gcr;
         break;
-    case 0x1080: /* VENI */
-        retval = opp->veni;
+    case 0x1080: /* VIR */
+        retval = opp->vir;
         break;
-    case 0x1090: /* PINT */
+    case 0x1090: /* PIR */
         retval = 0x00000000;
         break;
     case 0x00: /* Block Revision Register1 (BRR1) */
@@ -614,14 +614,14 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     case 0xB0:
         retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
         break;
-    case 0x10A0: /* IPI_IPVP */
+    case 0x10A0: /* IPI_IVPR */
     case 0x10B0:
     case 0x10C0:
     case 0x10D0:
         {
             int idx;
             idx = (addr - 0x10A0) >> 4;
-            retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
+            retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
         }
         break;
     case 0x10E0: /* SPVE */
@@ -650,26 +650,26 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     addr = addr & 0x30;
 
     if (addr == 0x0) {
-        /* TIFR (TFRR) */
-        opp->tifr = val;
+        /* TFRR */
+        opp->tfrr = val;
         return;
     }
     switch (addr & 0x30) {
-    case 0x00: /* TICC (GTCCR) */
+    case 0x00: /* TCCR */
         break;
-    case 0x10: /* TIBC (GTBCR) */
-        if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
-            (val & TIBC_CI) == 0 &&
-            (opp->timers[idx].tibc & TIBC_CI) != 0) {
-            opp->timers[idx].ticc &= ~TICC_TOG;
+    case 0x10: /* TBCR */
+        if ((opp->timers[idx].tccr & TCCR_TOG) != 0 &&
+            (val & TBCR_CI) == 0 &&
+            (opp->timers[idx].tbcr & TBCR_CI) != 0) {
+            opp->timers[idx].tccr &= ~TCCR_TOG;
         }
-        opp->timers[idx].tibc = val;
+        opp->timers[idx].tbcr = val;
         break;
-    case 0x20: /* TIVP (GTIVPR) */
-        write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
+    case 0x20: /* TVPR */
+        write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
         break;
-    case 0x30: /* TIDE (GTIDR) */
-        write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
+    case 0x30: /* TDR */
+        write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
         break;
     }
 }
@@ -686,22 +686,22 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     }
     idx = (addr >> 6) & 0x3;
     if (addr == 0x0) {
-        /* TIFR (TFRR) */
-        retval = opp->tifr;
+        /* TFRR */
+        retval = opp->tfrr;
         goto out;
     }
     switch (addr & 0x30) {
-    case 0x00: /* TICC (GTCCR) */
-        retval = opp->timers[idx].ticc;
+    case 0x00: /* TCCR */
+        retval = opp->timers[idx].tccr;
         break;
-    case 0x10: /* TIBC (GTBCR) */
-        retval = opp->timers[idx].tibc;
+    case 0x10: /* TBCR */
+        retval = opp->timers[idx].tbcr;
         break;
-    case 0x20: /* TIPV (TIPV) */
-        retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
+    case 0x20: /* TIPV */
+        retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
         break;
     case 0x30: /* TIDE (TIDR) */
-        retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
+        retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
         break;
     }
 
@@ -726,10 +726,10 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        write_IRQreg_ide(opp, idx, val);
+        write_IRQreg_idr(opp, idx, val);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        write_IRQreg_ipvp(opp, idx, val);
+        write_IRQreg_ivpr(opp, idx, val);
     }
 }
 
@@ -748,10 +748,10 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
     idx = addr >> 5;
     if (addr & 0x10) {
         /* EXDE / IFEDE / IEEDE */
-        retval = read_IRQreg_ide(opp, idx);
+        retval = read_IRQreg_idr(opp, idx);
     } else {
         /* EXVP / IFEVP / IEEVP */
-        retval = read_IRQreg_ipvp(opp, idx);
+        retval = read_IRQreg_ivpr(opp, idx);
     }
     DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
@@ -849,22 +849,22 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     case 0x70:
         idx = (addr - 0x40) >> 4;
         /* we use IDE as mask which CPUs to deliver the IPI to still. */
-        write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
-                         opp->src[opp->irq_ipi0 + idx].ide | val);
+        write_IRQreg_idr(opp, opp->irq_ipi0 + idx,
+                         opp->src[opp->irq_ipi0 + idx].idr | val);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
         openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
         break;
-    case 0x80: /* PCTP */
-        dst->pctp = val & 0x0000000F;
+    case 0x80: /* CTPR */
+        dst->ctpr = val & 0x0000000F;
         break;
     case 0x90: /* WHOAMI */
         /* Read-only register */
         break;
-    case 0xA0: /* PIAC */
+    case 0xA0: /* IACK */
         /* Read-only register */
         break;
-    case 0xB0: /* PEOI */
-        DPRINTF("PEOI\n");
+    case 0xB0: /* EOI */
+        DPRINTF("EOI\n");
         s_IRQ = IRQ_get_next(opp, &dst->servicing);
         IRQ_resetbit(&dst->servicing, s_IRQ);
         dst->servicing.next = -1;
@@ -875,7 +875,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         src = &opp->src[n_IRQ];
         if (n_IRQ != -1 &&
             (s_IRQ == -1 ||
-             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
+             IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
             DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
                     idx, n_IRQ);
             openpic_irq_raise(opp, idx, src);
@@ -914,56 +914,56 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
-    case 0x80: /* PCTP */
-        retval = dst->pctp;
+    case 0x80: /* CTPR */
+        retval = dst->ctpr;
         break;
     case 0x90: /* WHOAMI */
         retval = idx;
         break;
-    case 0xA0: /* PIAC */
+    case 0xA0: /* IACK */
         DPRINTF("Lower OpenPIC INT output\n");
         qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
         n_IRQ = IRQ_get_next(opp, &dst->raised);
-        DPRINTF("PIAC: irq=%d\n", n_IRQ);
+        DPRINTF("IACK: irq=%d\n", n_IRQ);
         if (n_IRQ == -1) {
             /* No more interrupt pending */
             retval = opp->spve;
         } else {
             src = &opp->src[n_IRQ];
-            if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
-                !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
+            if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
+                !(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
                 /* - Spurious level-sensitive IRQ
                  * - Priorities has been changed
                  *   and the pending IRQ isn't allowed anymore
                  */
-                src->ipvp &= ~IPVP_ACTIVITY_MASK;
+                src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 retval = opp->spve;
             } else {
                 /* IRQ enter servicing state */
                 IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IPVP_VECTOR(opp, src->ipvp);
+                retval = IVPR_VECTOR(opp, src->ivpr);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
             dst->raised.next = -1;
-            if (!(src->ipvp & IPVP_SENSE_MASK)) {
+            if (!(src->ivpr & IVPR_SENSE_MASK)) {
                 /* edge-sensitive IRQ */
-                src->ipvp &= ~IPVP_ACTIVITY_MASK;
+                src->ivpr &= ~IVPR_ACTIVITY_MASK;
                 src->pending = 0;
             }
 
             if ((n_IRQ >= opp->irq_ipi0) &&  (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
-                src->ide &= ~(1 << idx);
-                if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
+                src->idr &= ~(1 << idx);
+                if (src->idr && !(src->ivpr & IVPR_SENSE_MASK)) {
                     /* trigger on CPUs that didn't know about it yet */
                     openpic_set_irq(opp, n_IRQ, 1);
                     openpic_set_irq(opp, n_IRQ, 0);
                     /* if all CPUs knew about it, set active bit again */
-                    src->ipvp |= IPVP_ACTIVITY_MASK;
+                    src->ivpr |= IVPR_ACTIVITY_MASK;
                 }
             }
         }
         break;
-    case 0xB0: /* PEOI */
+    case 0xB0: /* EOI */
         retval = 0;
         break;
     default:
@@ -1095,15 +1095,15 @@ static void openpic_save(QEMUFile* f, void *opaque)
     OpenPICState *opp = (OpenPICState *)opaque;
     unsigned int i;
 
-    qemu_put_be32s(f, &opp->glbc);
-    qemu_put_be32s(f, &opp->veni);
-    qemu_put_be32s(f, &opp->pint);
+    qemu_put_be32s(f, &opp->gcr);
+    qemu_put_be32s(f, &opp->vir);
+    qemu_put_be32s(f, &opp->pir);
     qemu_put_be32s(f, &opp->spve);
-    qemu_put_be32s(f, &opp->tifr);
+    qemu_put_be32s(f, &opp->tfrr);
 
     for (i = 0; i < opp->max_irq; i++) {
-        qemu_put_be32s(f, &opp->src[i].ipvp);
-        qemu_put_be32s(f, &opp->src[i].ide);
+        qemu_put_be32s(f, &opp->src[i].ivpr);
+        qemu_put_be32s(f, &opp->src[i].idr);
         qemu_put_sbe32s(f, &opp->src[i].last_cpu);
         qemu_put_sbe32s(f, &opp->src[i].pending);
     }
@@ -1111,14 +1111,14 @@ static void openpic_save(QEMUFile* f, void *opaque)
     qemu_put_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_put_be32s(f, &opp->dst[i].pctp);
+        qemu_put_be32s(f, &opp->dst[i].ctpr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
 
     for (i = 0; i < MAX_TMR; i++) {
-        qemu_put_be32s(f, &opp->timers[i].ticc);
-        qemu_put_be32s(f, &opp->timers[i].tibc);
+        qemu_put_be32s(f, &opp->timers[i].tccr);
+        qemu_put_be32s(f, &opp->timers[i].tbcr);
     }
 }
 
@@ -1142,15 +1142,15 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
         return -EINVAL;
     }
 
-    qemu_get_be32s(f, &opp->glbc);
-    qemu_get_be32s(f, &opp->veni);
-    qemu_get_be32s(f, &opp->pint);
+    qemu_get_be32s(f, &opp->gcr);
+    qemu_get_be32s(f, &opp->vir);
+    qemu_get_be32s(f, &opp->pir);
     qemu_get_be32s(f, &opp->spve);
-    qemu_get_be32s(f, &opp->tifr);
+    qemu_get_be32s(f, &opp->tfrr);
 
     for (i = 0; i < opp->max_irq; i++) {
-        qemu_get_be32s(f, &opp->src[i].ipvp);
-        qemu_get_be32s(f, &opp->src[i].ide);
+        qemu_get_be32s(f, &opp->src[i].ivpr);
+        qemu_get_be32s(f, &opp->src[i].idr);
         qemu_get_sbe32s(f, &opp->src[i].last_cpu);
         qemu_get_sbe32s(f, &opp->src[i].pending);
     }
@@ -1158,14 +1158,14 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     qemu_get_be32s(f, &opp->nb_cpus);
 
     for (i = 0; i < opp->nb_cpus; i++) {
-        qemu_get_be32s(f, &opp->dst[i].pctp);
+        qemu_get_be32s(f, &opp->dst[i].ctpr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
 
     for (i = 0; i < MAX_TMR; i++) {
-        qemu_get_be32s(f, &opp->timers[i].ticc);
-        qemu_get_be32s(f, &opp->timers[i].tibc);
+        qemu_get_be32s(f, &opp->timers[i].tccr);
+        qemu_get_be32s(f, &opp->timers[i].tbcr);
     }
 
     return 0;
@@ -1175,7 +1175,7 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
 {
     int n_ci = IDR_CI0_SHIFT - n_CPU;
 
-    if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
+    if ((opp->flags & OPENPIC_FLAG_IDR_CRIT) && (src->idr & (1 << n_ci))) {
         qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
     } else {
         qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
@@ -1223,14 +1223,14 @@ static int openpic_init(SysBusDevice *dev)
     switch (opp->model) {
     case OPENPIC_MODEL_FSL_MPIC_20:
     default:
-        opp->flags |= OPENPIC_FLAG_IDE_CRIT;
+        opp->flags |= OPENPIC_FLAG_IDR_CRIT;
         opp->nb_irqs = 80;
         opp->vid = VID_REVISION_1_2;
-        opp->veni = VENI_GENERIC;
+        opp->vir = VIR_GENERIC;
         opp->vector_mask = 0xFFFF;
-        opp->tifr_reset = 0;
-        opp->ipvp_reset = IPVP_MASK_MASK;
-        opp->ide_reset = 1 << 0;
+        opp->tfrr_reset = 0;
+        opp->ivpr_reset = IVPR_MASK_MASK;
+        opp->idr_reset = 1 << 0;
         opp->max_irq = FSL_MPIC_20_MAX_IRQ;
         opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
@@ -1242,11 +1242,11 @@ static int openpic_init(SysBusDevice *dev)
     case OPENPIC_MODEL_RAVEN:
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
-        opp->veni = VENI_GENERIC;
+        opp->vir = VIR_GENERIC;
         opp->vector_mask = 0xFF;
-        opp->tifr_reset = 4160000;
-        opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
-        opp->ide_reset = 0;
+        opp->tfrr_reset = 4160000;
+        opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
+        opp->idr_reset = 0;
         opp->max_irq = RAVEN_MAX_IRQ;
         opp->irq_ipi0 = RAVEN_IPI_IRQ;
         opp->irq_tim0 = RAVEN_TMR_IRQ;
commit a1bb73849fbd7d992b6ac2cf30c034244fb2299d
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:41 2012 +0000

    ppc/booke: fix crit/mcheck/debug exceptions
    
    Book E does not play games with certain bits of xSRR1 being MSR save
    bits and others being error status.  xSRR1 is the old MSR, period.
    This was causing things like MSR[CE] to be lost, even in the saved
    version, as soon as you take an exception.
    
    rfci/rfdi/rfmci are fixed to pass the actual xSRR1 register contents,
    rather than the register number.
    
    Put FIXME comments on the hack that is "asrr0/1".  The whole point of
    separate exception levels is so that you can, for example, take a machine
    check or debug interrupt without corrupting critical-level operations.
    The right xSRR0/1 set needs to be chosen based on CPU type flags.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index 5e34ad0..41037a7 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -84,7 +84,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
                   " => %08x (%02x)\n", env->nip, excp, env->error_code);
 
     /* new srr1 value excluding must-be-zero bits */
-    msr = env->msr & ~0x783f0000ULL;
+    if (excp_model == POWERPC_EXCP_BOOKE) {
+        msr = env->msr;
+    } else {
+        msr = env->msr & ~0x783f0000ULL;
+    }
 
     /* new interrupt handler msr */
     new_msr = env->msr & ((target_ulong)1 << MSR_ME);
@@ -145,6 +149,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
             srr1 = SPR_40x_SRR3;
             break;
         case POWERPC_EXCP_BOOKE:
+            /* FIXME: choose one or the other based on CPU type */
             srr0 = SPR_BOOKE_MCSRR0;
             srr1 = SPR_BOOKE_MCSRR1;
             asrr0 = SPR_BOOKE_CSRR0;
@@ -275,6 +280,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
         switch (excp_model) {
         case POWERPC_EXCP_BOOKE:
+            /* FIXME: choose one or the other based on CPU type */
             srr0 = SPR_BOOKE_DSRR0;
             srr1 = SPR_BOOKE_DSRR1;
             asrr0 = SPR_BOOKE_CSRR0;
@@ -836,8 +842,13 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
 
 void helper_rfi(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0x783F0000), 1);
+    if (env->excp_model == POWERPC_EXCP_BOOKE) {
+        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+               ~((target_ulong)0), 0);
+    } else {
+        do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+               ~((target_ulong)0x783F0000), 1);
+    }
 }
 
 #if defined(TARGET_PPC64)
@@ -864,20 +875,22 @@ void helper_40x_rfci(CPUPPCState *env)
 
 void helper_rfci(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
+           ~((target_ulong)0), 0);
 }
 
 void helper_rfdi(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
+    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
+           ~((target_ulong)0), 0);
 }
 
 void helper_rfmci(CPUPPCState *env)
 {
-    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
+    /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
+    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
+           ~((target_ulong)0), 0);
 }
 #endif
 
commit e99fd8af63a1692a1159cba8fa4943f2589adf97
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:39 2012 +0000

    openpic: lower interrupt when reading the MSI register
    
    This will stop things from breaking once it's properly treated as a
    level-triggered interrupt.  Note that it's the MPIC's MSI cascade
    interrupts that are level-triggered; the individual MSIs are
    edge-triggered.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 9243e70..f4df66d 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -810,6 +810,7 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
         r = opp->msi[srs].msir;
         /* Clear on read */
         opp->msi[srs].msir = 0;
+        openpic_set_irq(opp, opp->irq_msi + srs, 0);
         break;
     case 0x120: /* MSISR */
         for (i = 0; i < MAX_MSI; i++) {
commit 4c4f0e4801ac79632d03867c88aafc90b4ce503c
Author: Scott Wood <scottwood at freescale.com>
Date:   Fri Dec 21 16:15:38 2012 +0000

    openpic: fix debug prints
    
    Fix various format errors when debug prints are enabled.  Also
    cause error checking to happen even when debug prints are not
    enabled, and consistently use 0x for hex output.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    [agraf: adjust for more recent code base, prettify DPRINTF macro]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 55e96d1..9243e70 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -43,11 +43,17 @@
 //#define DEBUG_OPENPIC
 
 #ifdef DEBUG_OPENPIC
-#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
+static const int debug_openpic = 1;
 #else
-#define DPRINTF(fmt, ...) do { } while (0)
+static const int debug_openpic = 0;
 #endif
 
+#define DPRINTF(fmt, ...) do { \
+        if (debug_openpic) { \
+            printf(fmt , ## __VA_ARGS__); \
+        } \
+    } while (0)
+
 #define MAX_CPU     15
 #define MAX_SRC     256
 #define MAX_TMR     4
@@ -422,7 +428,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
     IRQSource *src;
 
     src = &opp->src[n_IRQ];
-    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
+    DPRINTF("openpic: set irq %d = %d ipvp=0x%08x\n",
             n_IRQ, level, src->ipvp);
     if (src->ipvp & IPVP_SENSE_MASK) {
         /* level-sensitive irq */
@@ -513,7 +519,8 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     IRQDest *dst;
     int idx;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -576,7 +583,7 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     OpenPICState *opp = opaque;
     uint32_t retval;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
     if (addr & 0xF) {
         return retval;
@@ -623,7 +630,7 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
     default:
         break;
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -634,7 +641,8 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     OpenPICState *opp = opaque;
     int idx;
 
-    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -672,7 +680,7 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     uint32_t retval = -1;
     int idx;
 
-    DPRINTF("%s: addr %08x\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     if (addr & 0xF) {
         goto out;
     }
@@ -698,7 +706,7 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
     }
 
 out:
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -709,7 +717,8 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     OpenPICState *opp = opaque;
     int idx;
 
-    DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -730,7 +739,7 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
     uint32_t retval;
     int idx;
 
-    DPRINTF("%s: addr %08x\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
     if (addr & 0xF) {
         return retval;
@@ -744,7 +753,7 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
         /* EXVP / IFEVP / IEEVP */
         retval = read_IRQreg_ipvp(opp, idx);
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
@@ -756,7 +765,8 @@ static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
     int idx = opp->irq_msi;
     int srs, ibs;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+    DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
+            __func__, addr, val);
     if (addr & 0xF) {
         return;
     }
@@ -781,7 +791,7 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
     uint64_t r = 0;
     int i, srs;
 
-    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
     if (addr & 0xF) {
         return -1;
     }
@@ -819,7 +829,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
     IRQDest *dst;
     int s_IRQ, n_IRQ;
 
-    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
+    DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx " <= 0x%08x\n", __func__, idx,
             addr, val);
 
     if (idx < 0) {
@@ -890,7 +900,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     uint32_t retval;
     int n_IRQ;
 
-    DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
+    DPRINTF("%s: cpu %d addr %#" HWADDR_PRIx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
 
     if (idx < 0) {
@@ -958,7 +968,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     default:
         break;
     }
-    DPRINTF("%s: => %08x\n", __func__, retval);
+    DPRINTF("%s: => 0x%08x\n", __func__, retval);
 
     return retval;
 }
commit beb526b12134a6b6744125deec5a7fe24a8f92e3
Author: Samuel Seay <lightningth at gmail.com>
Date:   Wed Jan 2 10:53:46 2013 +0000

    PPC: fix segfault in signal handling code
    
    Removed h2g() macro around the ka->_sa_handler due to the _sa_handler being a
    guest memory address.
    
    Changed the __put_user to put_user as it was attempting to put a value at the
    stack address but the new address is a guest memory address, __put_user is
    for host memory addresses.
    
    Signed-off-by: Samuel Seay <LightningTH at GMail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    [agraf: change subject line, reformat commit message]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 95e2ffa..c43b8ac 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4584,7 +4584,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
     signal = current_exec_domain_sig(sig);
 
-    err |= __put_user(h2g(ka->_sa_handler), &sc->handler);
+    err |= __put_user(ka->_sa_handler, &sc->handler);
     err |= __put_user(set->sig[0], &sc->oldmask);
 #if defined(TARGET_PPC64)
     err |= __put_user(set->sig[0] >> 32, &sc->_unused[3]);
@@ -4606,7 +4606,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
     /* Create a stack frame for the caller of the handler.  */
     newsp = frame_addr - SIGNAL_FRAMESIZE;
-    err |= __put_user(env->gpr[1], (target_ulong *)(uintptr_t) newsp);
+    err |= put_user(env->gpr[1], newsp, target_ulong);
 
     if (err)
         goto sigsegv;
commit 88a78d9093917096feffeba66802be27d0e64ead
Author: Bharat Bhushan <r65777 at freescale.com>
Date:   Thu Dec 27 19:16:51 2012 +0000

    PPC: Reset qemu timers when guest reset
    
    This patch install the timer reset handler. This will be called when
    the guest is reset.
    
    Signed-off-by: Bharat Bhushan <bharat.bhushan at freescale.com>
    [agraf: adjust for QOM'ification]
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_booke.c b/hw/ppc_booke.c
index 4483b8d..25a4e91 100644
--- a/hw/ppc_booke.c
+++ b/hw/ppc_booke.c
@@ -237,6 +237,17 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
 
 }
 
+static void ppc_booke_timer_reset_handle(void *opaque)
+{
+    PowerPCCPU *cpu = opaque;
+    CPUPPCState *env = &cpu->env;
+
+    env->spr[SPR_BOOKE_TSR] = 0;
+    env->spr[SPR_BOOKE_TCR] = 0;
+
+    booke_update_irq(cpu);
+}
+
 void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
 {
     ppc_tb_t *tb_env;
@@ -257,4 +268,6 @@ void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
         qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
     booke_timer->wdt_timer =
         qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
+
+    qemu_register_reset(ppc_booke_timer_reset_handle, cpu);
 }
commit af7e9e74c6a62a5bcd911726a9e88d28b61490e0
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Dec 20 17:30:58 2012 +0100

    openpic: fix coding style issues
    
    This patch fixes the following coding style violations:
    
      - structs have to be typedef and be CamelCase
      - if()s are always surrounded by curly braces
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 93e8208..55e96d1 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -173,19 +173,19 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx);
 
-typedef struct IRQ_queue_t {
+typedef struct IRQQueue {
     uint32_t queue[BF_WIDTH(MAX_IRQ)];
     int next;
     int priority;
     int pending;    /* nr of pending bits in queue */
-} IRQ_queue_t;
+} IRQQueue;
 
-typedef struct IRQ_src_t {
+typedef struct IRQSource {
     uint32_t ipvp;  /* IRQ vector/priority register */
     uint32_t ide;   /* IRQ destination register */
     int last_cpu;
     int pending;    /* TRUE if IRQ is pending */
-} IRQ_src_t;
+} IRQSource;
 
 #define IPVP_MASK_SHIFT       31
 #define IPVP_MASK_MASK        (1 << IPVP_MASK_SHIFT)
@@ -206,12 +206,12 @@ typedef struct IRQ_src_t {
 #define IDE_EP      0x80000000  /* external pin */
 #define IDE_CI      0x40000000  /* critical interrupt */
 
-typedef struct IRQ_dst_t {
+typedef struct IRQDest {
     uint32_t pctp; /* CPU current task priority */
-    IRQ_queue_t raised;
-    IRQ_queue_t servicing;
+    IRQQueue raised;
+    IRQQueue servicing;
     qemu_irq *irqs;
-} IRQ_dst_t;
+} IRQDest;
 
 typedef struct OpenPICState {
     SysBusDevice busdev;
@@ -239,9 +239,9 @@ typedef struct OpenPICState {
     uint32_t spve; /* Spurious vector register */
     uint32_t tifr; /* Timer frequency reporting register */
     /* Source registers */
-    IRQ_src_t src[MAX_IRQ];
+    IRQSource src[MAX_IRQ];
     /* Local registers per output pin */
-    IRQ_dst_t dst[MAX_CPU];
+    IRQDest dst[MAX_CPU];
     uint32_t nb_cpus;
     /* Timer registers */
     struct {
@@ -258,26 +258,26 @@ typedef struct OpenPICState {
     uint32_t irq_msi;
 } OpenPICState;
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src);
 
-static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ)
+static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
 {
     q->pending++;
     set_bit(q->queue, n_IRQ);
 }
 
-static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ)
+static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
 {
     q->pending--;
     reset_bit(q->queue, n_IRQ);
 }
 
-static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ)
+static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
 {
     return test_bit(q->queue, n_IRQ);
 }
 
-static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
+static void IRQ_check(OpenPICState *opp, IRQQueue *q)
 {
     int next, i;
     int priority;
@@ -306,7 +306,7 @@ out:
     q->priority = priority;
 }
 
-static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
+static int IRQ_get_next(OpenPICState *opp, IRQQueue *q)
 {
     if (q->next == -1) {
         /* XXX: optimize */
@@ -318,8 +318,8 @@ static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
 
 static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 {
-    IRQ_dst_t *dst;
-    IRQ_src_t *src;
+    IRQDest *dst;
+    IRQSource *src;
     int priority;
 
     dst = &opp->dst[n_CPU];
@@ -360,7 +360,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
 /* update pic state because registers for n_IRQ have changed value */
 static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 {
-    IRQ_src_t *src;
+    IRQSource *src;
     int i;
 
     src = &opp->src[n_IRQ];
@@ -404,8 +404,9 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
     } else {
         /* Distributed delivery mode */
         for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
-            if (i == opp->nb_cpus)
+            if (i == opp->nb_cpus) {
                 i = 0;
+            }
             if (src->ide & (1 << i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
                 src->last_cpu = i;
@@ -418,7 +419,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
 static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
+    IRQSource *src;
 
     src = &opp->src[n_IRQ];
     DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
@@ -431,8 +432,9 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
         }
     } else {
         /* edge-sensitive irq */
-        if (level)
+        if (level) {
             src->pending = 1;
+        }
     }
     openpic_update_irq(opp, n_IRQ);
 }
@@ -459,9 +461,9 @@ static void openpic_reset(DeviceState *d)
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
         opp->dst[i].pctp      = 15;
-        memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
+        memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
         opp->dst[i].raised.next = -1;
-        memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
+        memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
         opp->dst[i].servicing.next = -1;
     }
     /* Initialise timers */
@@ -508,12 +510,13 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
                               unsigned len)
 {
     OpenPICState *opp = opaque;
-    IRQ_dst_t *dst;
+    IRQDest *dst;
     int idx;
 
     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     switch (addr) {
     case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
         break;
@@ -575,8 +578,9 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
 
     DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
     retval = 0xFFFFFFFF;
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     switch (addr) {
     case 0x1000: /* FREP */
         retval = opp->frep;
@@ -631,8 +635,9 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     idx = (addr >> 6) & 0x3;
     addr = addr & 0x30;
 
@@ -705,8 +710,9 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
     int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     addr = addr & 0xFFF0;
     idx = addr >> 5;
     if (addr & 0x10) {
@@ -726,8 +732,9 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
 
     DPRINTF("%s: addr %08x\n", __func__, addr);
     retval = 0xFFFFFFFF;
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     addr = addr & 0xFFF0;
     idx = addr >> 5;
     if (addr & 0x10) {
@@ -808,8 +815,8 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
                                        uint32_t val, int idx)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
-    IRQ_dst_t *dst;
+    IRQSource *src;
+    IRQDest *dst;
     int s_IRQ, n_IRQ;
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
@@ -819,8 +826,9 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
         return;
     }
 
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return;
+    }
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
@@ -877,8 +885,8 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                                           int idx)
 {
     OpenPICState *opp = opaque;
-    IRQ_src_t *src;
-    IRQ_dst_t *dst;
+    IRQSource *src;
+    IRQDest *dst;
     uint32_t retval;
     int n_IRQ;
 
@@ -889,8 +897,9 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         return retval;
     }
 
-    if (addr & 0xF)
+    if (addr & 0xF) {
         return retval;
+    }
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
@@ -1059,7 +1068,7 @@ static const MemoryRegionOps openpic_msi_ops_be = {
     },
 };
 
-static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
+static void openpic_save_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
@@ -1102,7 +1111,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
     }
 }
 
-static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
+static void openpic_load_IRQ_queue(QEMUFile* f, IRQQueue *q)
 {
     unsigned int i;
 
@@ -1118,8 +1127,9 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     OpenPICState *opp = (OpenPICState *)opaque;
     unsigned int i;
 
-    if (version_id != 1)
+    if (version_id != 1) {
         return -EINVAL;
+    }
 
     qemu_get_be32s(f, &opp->glbc);
     qemu_get_be32s(f, &opp->veni);
@@ -1150,7 +1160,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
-static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
 {
     int n_ci = IDR_CI0_SHIFT - n_CPU;
 
@@ -1161,19 +1171,19 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
     }
 }
 
-struct memreg {
+typedef struct MemReg {
     const char             *name;
     MemoryRegionOps const  *ops;
     bool                   map;
     hwaddr      start_addr;
     ram_addr_t              size;
-};
+} MemReg;
 
 static int openpic_init(SysBusDevice *dev)
 {
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
     int i, j;
-    struct memreg list_le[] = {
+    MemReg list_le[] = {
         {"glb", &openpic_glb_ops_le, true,
                 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
         {"tmr", &openpic_tmr_ops_le, true,
@@ -1185,7 +1195,7 @@ static int openpic_init(SysBusDevice *dev)
         {"cpu", &openpic_cpu_ops_le, true,
                 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
     };
-    struct memreg list_be[] = {
+    MemReg list_be[] = {
         {"glb", &openpic_glb_ops_be, true,
                 OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
         {"tmr", &openpic_tmr_ops_be, true,
@@ -1197,7 +1207,7 @@ static int openpic_init(SysBusDevice *dev)
         {"cpu", &openpic_cpu_ops_be, true,
                 OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
     };
-    struct memreg *list;
+    MemReg *list;
 
     switch (opp->model) {
     case OPENPIC_MODEL_FSL_MPIC_20:
commit d56af005dc3d6354bd39411e8446b415bbcf86b8
Author: Bharat Bhushan <r65777 at freescale.com>
Date:   Tue Dec 18 01:13:58 2012 +0000

    powerpc: linux header sync script includes epapr_hcalls.h
    
    epapr_hcalls.h is now referenced by kvm_para.h. so this is needed for
    QEMU to get compiled on powerpc.
    
    Signed-off-by: Bharat Bhushan <bharat.bhushan at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index 4c7b566..120a694 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -54,6 +54,9 @@ for arch in $ARCHLIST; do
     if [ $arch = x86 ]; then
         cp "$tmpdir/include/asm/hyperv.h" "$output/linux-headers/asm-x86"
     fi
+    if [ $arch = powerpc ]; then
+        cp "$tmpdir/include/asm/epapr_hcalls.h" "$output/linux-headers/asm-powerpc/"
+    fi
 done
 
 rm -rf "$output/linux-headers/linux"
commit c3203fa5b2c17a1c446e44c87788fef21b4af5f4
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:12:02 2012 +0000

    openpic: don't crash on a register access without a CPU context
    
    If we access a register via the QEMU memory inspection commands (e.g.
    "xp") rather than from guest code, we won't have a CPU context.
    Gracefully fail to access the register in that case, rather than
    crashing.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 10dbdf7..93e8208 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -161,7 +161,11 @@ static inline int test_bit(uint32_t *field, int bit)
 
 static int get_current_cpu(void)
 {
-  return cpu_single_env->cpu_index;
+    if (!cpu_single_env) {
+        return -1;
+    }
+
+    return cpu_single_env->cpu_index;
 }
 
 static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
@@ -810,6 +814,11 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
             addr, val);
+
+    if (idx < 0) {
+        return;
+    }
+
     if (addr & 0xF)
         return;
     dst = &opp->dst[idx];
@@ -875,6 +884,11 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
 
     DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
     retval = 0xFFFFFFFF;
+
+    if (idx < 0) {
+        return retval;
+    }
+
     if (addr & 0xF)
         return retval;
     dst = &opp->dst[idx];
commit a26a7b38331dc14893a66fbe78f34afab153d6b2
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:12:04 2012 +0000

    openpic: s/opp->nb_irqs -1/opp->nb_cpus - 1/
    
    "opp->nb_irqs-1" would have been a minor coding style error,
    but putting in one space but not the other makes it look
    confusingly like a numeric literal "-1".
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 337dbf5..10dbdf7 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -440,8 +440,8 @@ static void openpic_reset(DeviceState *d)
 
     opp->glbc = GLBC_RESET;
     /* Initialise controller registers */
-    opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
-                ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
+    opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
+                ((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
                 (opp->vid << FREP_VID_SHIFT);
 
     opp->pint = 0;
commit 0d4046833ba44c5f29e5dcce2dde0a6202225e59
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:12:03 2012 +0000

    openpic: BRR1 is not a CPU-specific register.
    
    It's in the address range that normally contains a magic redirection
    to the CPU-specific region of the curretn CPU, but it isn't actually
    a per-CPU register.  On real hardware BRR1 shows up only at 0x40000,
    not at 0x60000 or other non-magic per-CPU areas.  Plus, this makes
    it possible to read the register on the QEMU command line with "xp".
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index f0877fa..337dbf5 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -587,6 +587,8 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
         retval = 0x00000000;
         break;
     case 0x00: /* Block Revision Register1 (BRR1) */
+        retval = opp->brr1;
+        break;
     case 0x40:
     case 0x50:
     case 0x60:
@@ -878,9 +880,6 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
     dst = &opp->dst[idx];
     addr &= 0xFF0;
     switch (addr) {
-    case 0x00: /* Block Revision Register1 (BRR1) */
-        retval = opp->brr1;
-        break;
     case 0x80: /* PCTP */
         retval = dst->pctp;
         break;
commit 0fe04622c11a4f131070196ad5cd97ce94d9c33b
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:12:01 2012 +0000

    openpic: support large vectors on FSL mpic
    
    Previously only the spurious vector was sized appropriately
    to the openpic model.
    
    Also, instances of "IPVP_VECTOR(opp->spve)" were replace with
    just "opp->spve", as opp->spve is already just a vector and not
    an IVPR.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 44f7cc4..f0877fa 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -51,7 +51,6 @@
 #define MAX_CPU     15
 #define MAX_SRC     256
 #define MAX_TMR     4
-#define VECTOR_BITS 8
 #define MAX_IPI     4
 #define MAX_MSI     8
 #define MAX_IRQ     (MAX_SRC + MAX_IPI + MAX_TMR)
@@ -197,8 +196,7 @@ typedef struct IRQ_src_t {
 
 #define IPVP_PRIORITY_MASK     (0xF << 16)
 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
-#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
-#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
+#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
 
 /* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
 #define IDE_EP      0x80000000  /* external pin */
@@ -221,7 +219,7 @@ typedef struct OpenPICState {
     uint32_t nb_irqs;
     uint32_t vid;
     uint32_t veni; /* Vendor identification register */
-    uint32_t spve_mask;
+    uint32_t vector_mask;
     uint32_t tifr_reset;
     uint32_t ipvp_reset;
     uint32_t ide_reset;
@@ -447,7 +445,7 @@ static void openpic_reset(DeviceState *d)
                 (opp->vid << FREP_VID_SHIFT);
 
     opp->pint = 0;
-    opp->spve = -1 & opp->spve_mask;
+    opp->spve = -1 & opp->vector_mask;
     opp->tifr = opp->tifr_reset;
     /* Initialise IRQ sources */
     for (i = 0; i < opp->max_irq; i++) {
@@ -496,7 +494,7 @@ static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
     opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
-        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | IPVP_VECTOR_MASK));
+        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ipvp);
@@ -559,7 +557,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
         }
         break;
     case 0x10E0: /* SPVE */
-        opp->spve = val & opp->spve_mask;
+        opp->spve = val & opp->vector_mask;
         break;
     default:
         break;
@@ -896,7 +894,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
         DPRINTF("PIAC: irq=%d\n", n_IRQ);
         if (n_IRQ == -1) {
             /* No more interrupt pending */
-            retval = IPVP_VECTOR(opp->spve);
+            retval = opp->spve;
         } else {
             src = &opp->src[n_IRQ];
             if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
@@ -906,11 +904,11 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
                  *   and the pending IRQ isn't allowed anymore
                  */
                 src->ipvp &= ~IPVP_ACTIVITY_MASK;
-                retval = IPVP_VECTOR(opp->spve);
+                retval = opp->spve;
             } else {
                 /* IRQ enter servicing state */
                 IRQ_setbit(&dst->servicing, n_IRQ);
-                retval = IPVP_VECTOR(src->ipvp);
+                retval = IPVP_VECTOR(opp, src->ipvp);
             }
             IRQ_resetbit(&dst->raised, n_IRQ);
             dst->raised.next = -1;
@@ -1195,7 +1193,7 @@ static int openpic_init(SysBusDevice *dev)
         opp->nb_irqs = 80;
         opp->vid = VID_REVISION_1_2;
         opp->veni = VENI_GENERIC;
-        opp->spve_mask = 0xFFFF;
+        opp->vector_mask = 0xFFFF;
         opp->tifr_reset = 0;
         opp->ipvp_reset = IPVP_MASK_MASK;
         opp->ide_reset = 1 << 0;
@@ -1211,7 +1209,7 @@ static int openpic_init(SysBusDevice *dev)
         opp->nb_irqs = RAVEN_MAX_EXT;
         opp->vid = VID_REVISION_1_3;
         opp->veni = VENI_GENERIC;
-        opp->spve_mask = 0xFF;
+        opp->vector_mask = 0xFF;
         opp->tifr_reset = 4160000;
         opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
         opp->ide_reset = 0;
commit c975330ec4f5674f2899331f914c04ecba6edf26
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:12:00 2012 +0000

    openpic: remove pcsr (CPU sensitivity register)
    
    I could not find this register in any spec (FSL, IBM, or OpenPIC)
    and the code doesn't do anything with it but initialize, save,
    or restore it.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index eff1eee..44f7cc4 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -206,7 +206,6 @@ typedef struct IRQ_src_t {
 
 typedef struct IRQ_dst_t {
     uint32_t pctp; /* CPU current task priority */
-    uint32_t pcsr; /* CPU sensitivity register */
     IRQ_queue_t raised;
     IRQ_queue_t servicing;
     qemu_irq *irqs;
@@ -458,7 +457,6 @@ static void openpic_reset(DeviceState *d)
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
         opp->dst[i].pctp      = 15;
-        opp->dst[i].pcsr      = 0x00000000;
         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
         opp->dst[i].raised.next = -1;
         memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
@@ -1083,7 +1081,6 @@ static void openpic_save(QEMUFile* f, void *opaque)
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_put_be32s(f, &opp->dst[i].pctp);
-        qemu_put_be32s(f, &opp->dst[i].pcsr);
         openpic_save_IRQ_queue(f, &opp->dst[i].raised);
         openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
     }
@@ -1130,7 +1127,6 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
 
     for (i = 0; i < opp->nb_cpus; i++) {
         qemu_get_be32s(f, &opp->dst[i].pctp);
-        qemu_get_be32s(f, &opp->dst[i].pcsr);
         openpic_load_IRQ_queue(f, &opp->dst[i].raised);
         openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
     }
commit 71c6cacb241689bbf99d54467dc2ae6912ffdab9
Author: Scott Wood <scottwood at freescale.com>
Date:   Thu Dec 13 16:11:59 2012 +0000

    openpic: symbolicize some magic numbers
    
    Deefine symbolic names for some register bits, and use some that
    have already been defined.
    
    Also convert some register values from hex to decimal when it improves
    readability.
    
    IPVP_PRIORITY_MASK is corrected from (0x1F << 16) to (0xF << 16), in
    conjunction with making wider use of the symbolic name.  I looked at
    Freescale and IBM MPIC docs and at the base OpenPIC spec, and all three
    had priority as 4 bits rather than 5.  Plus, the magic nubmer that is
    being replaced with symbolic values treated the field as 4 bits wide.
    
    Signed-off-by: Scott Wood <scottwood at freescale.com>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/openpic.c b/hw/openpic.c
index 9c956b9..eff1eee 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -124,6 +124,11 @@
 
 #define VENI_GENERIC      0x00000000 /* Generic Vendor ID */
 
+#define GLBC_RESET        0x80000000
+
+#define TIBC_CI           0x80000000 /* count inhibit */
+#define TICC_TOG          0x80000000 /* toggles when decrement to zero */
+
 #define IDR_EP_SHIFT      31
 #define IDR_EP_MASK       (1 << IDR_EP_SHIFT)
 #define IDR_CI0_SHIFT     30
@@ -190,11 +195,15 @@ typedef struct IRQ_src_t {
 #define IPVP_SENSE_SHIFT      22
 #define IPVP_SENSE_MASK       (1 << IPVP_SENSE_SHIFT)
 
-#define IPVP_PRIORITY_MASK     (0x1F << 16)
+#define IPVP_PRIORITY_MASK     (0xF << 16)
 #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
 #define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
 #define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
 
+/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
+#define IDE_EP      0x80000000  /* external pin */
+#define IDE_CI      0x40000000  /* critical interrupt */
+
 typedef struct IRQ_dst_t {
     uint32_t pctp; /* CPU current task priority */
     uint32_t pcsr; /* CPU sensitivity register */
@@ -375,7 +384,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
         DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
-    if (src->ide == 0x00000000) {
+    if (src->ide == 0) {
         /* No target */
         DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
         return;
@@ -432,13 +441,13 @@ static void openpic_reset(DeviceState *d)
     OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
     int i;
 
-    opp->glbc = 0x80000000;
+    opp->glbc = GLBC_RESET;
     /* Initialise controller registers */
     opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
                 ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
                 (opp->vid << FREP_VID_SHIFT);
 
-    opp->pint = 0x00000000;
+    opp->pint = 0;
     opp->spve = -1 & opp->spve_mask;
     opp->tifr = opp->tifr_reset;
     /* Initialise IRQ sources */
@@ -448,7 +457,7 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise IRQ destinations */
     for (i = 0; i < MAX_CPU; i++) {
-        opp->dst[i].pctp      = 0x0000000F;
+        opp->dst[i].pctp      = 15;
         opp->dst[i].pcsr      = 0x00000000;
         memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
         opp->dst[i].raised.next = -1;
@@ -457,11 +466,11 @@ static void openpic_reset(DeviceState *d)
     }
     /* Initialise timers */
     for (i = 0; i < MAX_TMR; i++) {
-        opp->timers[i].ticc = 0x00000000;
-        opp->timers[i].tibc = 0x80000000;
+        opp->timers[i].ticc = 0;
+        opp->timers[i].tibc = TIBC_CI;
     }
     /* Go out of RESET state */
-    opp->glbc = 0x00000000;
+    opp->glbc = 0;
 }
 
 static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
@@ -478,7 +487,7 @@ static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     uint32_t tmp;
 
-    tmp = val & 0xC0000000;
+    tmp = val & (IDE_EP | IDE_CI);
     tmp |= val & ((1ULL << MAX_CPU) - 1);
     opp->src[n_IRQ].ide = tmp;
     DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
@@ -488,8 +497,8 @@ static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
 {
     /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
     /* ACTIVITY bit is read-only */
-    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
-                         | (val & 0x800F00FF);
+    opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
+        (val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | IPVP_VECTOR_MASK));
     openpic_update_irq(opp, n_IRQ);
     DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
             opp->src[n_IRQ].ipvp);
@@ -521,7 +530,7 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x1000: /* FREP */
         break;
     case 0x1020: /* GLBC */
-        if (val & 0x80000000) {
+        if (val & GLBC_RESET) {
             openpic_reset(&opp->busdev.qdev);
         }
         break;
@@ -634,10 +643,11 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
     case 0x00: /* TICC (GTCCR) */
         break;
     case 0x10: /* TIBC (GTBCR) */
-        if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
-            (val & 0x80000000) == 0 &&
-            (opp->timers[idx].tibc & 0x80000000) != 0)
-            opp->timers[idx].ticc &= ~0x80000000;
+        if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
+            (val & TIBC_CI) == 0 &&
+            (opp->timers[idx].tibc & TIBC_CI) != 0) {
+            opp->timers[idx].ticc &= ~TICC_TOG;
+        }
         opp->timers[idx].tibc = val;
         break;
     case 0x20: /* TIVP (GTIVPR) */
@@ -1190,9 +1200,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->vid = VID_REVISION_1_2;
         opp->veni = VENI_GENERIC;
         opp->spve_mask = 0xFFFF;
-        opp->tifr_reset = 0x00000000;
-        opp->ipvp_reset = 0x80000000;
-        opp->ide_reset = 0x00000001;
+        opp->tifr_reset = 0;
+        opp->ipvp_reset = IPVP_MASK_MASK;
+        opp->ide_reset = 1 << 0;
         opp->max_irq = FSL_MPIC_20_MAX_IRQ;
         opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
         opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
@@ -1206,9 +1216,9 @@ static int openpic_init(SysBusDevice *dev)
         opp->vid = VID_REVISION_1_3;
         opp->veni = VENI_GENERIC;
         opp->spve_mask = 0xFF;
-        opp->tifr_reset = 0x003F7A00;
-        opp->ipvp_reset = 0xA0000000;
-        opp->ide_reset = 0x00000000;
+        opp->tifr_reset = 4160000;
+        opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
+        opp->ide_reset = 0;
         opp->max_irq = RAVEN_MAX_IRQ;
         opp->irq_ipi0 = RAVEN_IPI_IRQ;
         opp->irq_tim0 = RAVEN_TMR_IRQ;
commit 2b35e93fbfc52c2be6cf85e5a54a3707cdabd914
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Dec 5 09:23:25 2012 -0600

    target-s390: Claim maintainership
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/MAINTAINERS b/MAINTAINERS
index cf39e5a..4b7553e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -98,6 +98,7 @@ S: Maintained
 F: target-ppc/
 
 S390
+M: Richard Henderson <rth at twiddle.net>
 M: Alexander Graf <agraf at suse.de>
 S: Maintained
 F: target-s390x/
commit 26cc0a3fd11d537bdd2649b5f3c385ad858b1857
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 15 10:32:25 2012 -0800

    target-s390: Use noreturn for exception and load_psw
    
    Both always exit the cpu loop.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index dea7071..dd90d93 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -1,6 +1,6 @@
 #include "exec/def-helper.h"
 
-DEF_HELPER_2(exception, void, env, i32)
+DEF_HELPER_2(exception, noreturn, env, i32)
 DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
@@ -90,7 +90,7 @@ DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i64, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
-DEF_HELPER_3(load_psw, void, env, i64, i64)
+DEF_HELPER_3(load_psw, noreturn, env, i64, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
commit 893e1660d5b9be0900bb1f09e574b1856eb30783
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 15 10:31:29 2012 -0800

    target-s390: Use TCG_CALL_NO_WG for misc helpers
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index f5dabb7..dea7071 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -110,7 +110,7 @@ DEF_HELPER_3(csp, i32, env, i32, i64)
 DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
 DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
 DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
-DEF_HELPER_2(sacf, void, env, i64)
+DEF_HELPER_FLAGS_2(sacf, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_2(lra, i64, env, i64)
commit c20fec4055f06de6d96789d1a290f284fac48fc4
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 15 10:25:57 2012 -0800

    target-s390: Use TCG_CALL_NO_WG for integer helpers
    
    The division routines do not read or write tcg registers,
    but can raise fixed-point divide exceptions.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 77f8f7d..f5dabb7 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -9,10 +9,10 @@ DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
 DEF_HELPER_3(mvcl, i32, env, i32, i32)
 DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64)
 DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
-DEF_HELPER_3(divs32, s64, env, s64, s64)
-DEF_HELPER_3(divu32, i64, env, i64, i64)
-DEF_HELPER_3(divs64, s64, env, s64, s64)
-DEF_HELPER_4(divu64, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_3(divs32, TCG_CALL_NO_WG, s64, env, s64, s64)
+DEF_HELPER_FLAGS_3(divu32, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divs64, TCG_CALL_NO_WG, s64, env, s64, s64)
+DEF_HELPER_FLAGS_4(divu64, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_4(srst, i64, env, i64, i64, i64)
 DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
commit c482ea94eaf26761e5cc0e53259cf1a98db29622
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 15 10:21:54 2012 -0800

    target-s390: Use TCG_CALL_NO_WG for floating-point helpers
    
    None of them read or write tcg registers, but most can
    raise fp exceptions.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index e9664fa..77f8f7d 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -32,52 +32,52 @@ DEF_HELPER_3(cxgb, i64, env, s64, i32)
 DEF_HELPER_3(celgb, i64, env, i64, i32)
 DEF_HELPER_3(cdlgb, i64, env, i64, i32)
 DEF_HELPER_3(cxlgb, i64, env, i64, i32)
-DEF_HELPER_3(aeb, i64, env, i64, i64)
-DEF_HELPER_3(adb, i64, env, i64, i64)
-DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(seb, i64, env, i64, i64)
-DEF_HELPER_3(sdb, i64, env, i64, i64)
-DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(deb, i64, env, i64, i64)
-DEF_HELPER_3(ddb, i64, env, i64, i64)
-DEF_HELPER_5(dxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(meeb, i64, env, i64, i64)
-DEF_HELPER_3(mdeb, i64, env, i64, i64)
-DEF_HELPER_3(mdb, i64, env, i64, i64)
-DEF_HELPER_5(mxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_4(mxdb, i64, env, i64, i64, i64)
-DEF_HELPER_2(ldeb, i64, env, i64)
-DEF_HELPER_3(ldxb, i64, env, i64, i64)
-DEF_HELPER_2(lxdb, i64, env, i64)
-DEF_HELPER_2(lxeb, i64, env, i64)
-DEF_HELPER_2(ledb, i64, env, i64)
-DEF_HELPER_3(lexb, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(aeb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(adb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_5(axb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(seb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(sdb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_5(sxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(deb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(ddb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_5(dxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(meeb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mdeb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mdb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_5(mxb, TCG_CALL_NO_WG, i64, env, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_4(mxdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_2(ldeb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_3(ldxb, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(lxdb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(lxeb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(ledb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_3(lexb, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
-DEF_HELPER_3(cgeb, i64, env, i64, i32)
-DEF_HELPER_3(cgdb, i64, env, i64, i32)
-DEF_HELPER_4(cgxb, i64, env, i64, i64, i32)
-DEF_HELPER_3(cfeb, i64, env, i64, i32)
-DEF_HELPER_3(cfdb, i64, env, i64, i32)
-DEF_HELPER_4(cfxb, i64, env, i64, i64, i32)
-DEF_HELPER_3(clgeb, i64, env, i64, i32)
-DEF_HELPER_3(clgdb, i64, env, i64, i32)
-DEF_HELPER_4(clgxb, i64, env, i64, i64, i32)
-DEF_HELPER_3(clfeb, i64, env, i64, i32)
-DEF_HELPER_3(clfdb, i64, env, i64, i32)
-DEF_HELPER_4(clfxb, i64, env, i64, i64, i32)
-DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
-DEF_HELPER_4(madb, i64, env, i64, i64, i64)
-DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
-DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_3(cgeb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_3(cgdb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(cgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
+DEF_HELPER_FLAGS_3(cfeb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_3(cfdb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(cfxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
+DEF_HELPER_FLAGS_3(clgeb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_3(clgdb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(clgxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
+DEF_HELPER_FLAGS_3(clfeb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_3(clfdb, TCG_CALL_NO_WG, i64, env, i64, i32)
+DEF_HELPER_FLAGS_4(clfxb, TCG_CALL_NO_WG, i64, env, i64, i64, i32)
+DEF_HELPER_FLAGS_4(maeb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_4(madb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_4(mseb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
+DEF_HELPER_FLAGS_4(msdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i64, i64)
-DEF_HELPER_2(sqeb, i64, env, i64)
-DEF_HELPER_2(sqdb, i64, env, i64)
-DEF_HELPER_3(sqxb, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64)
+DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
 DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64)
commit d918a65c690c321f56e7ce4b5a9e1f2fbe32bb1b
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Nov 15 10:20:43 2012 -0800

    target-s390: Use TCG_CALL_NO_WG for memory helpers
    
    Those that do not read or write tcg registers, but can
    raise exceptions via memory faults.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index a5844b3..e9664fa 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -1,13 +1,13 @@
 #include "exec/def-helper.h"
 
 DEF_HELPER_2(exception, void, env, i32)
-DEF_HELPER_4(nc, i32, env, i32, i64, i64)
-DEF_HELPER_4(oc, i32, env, i32, i64, i64)
-DEF_HELPER_4(xc, i32, env, i32, i64, i64)
-DEF_HELPER_4(mvc, void, env, i32, i64, i64)
-DEF_HELPER_4(clc, i32, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(nc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(oc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(xc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(mvc, TCG_CALL_NO_WG, void, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(clc, TCG_CALL_NO_WG, i32, env, i32, i64, i64)
 DEF_HELPER_3(mvcl, i32, env, i32, i32)
-DEF_HELPER_4(clm, i32, env, i32, i32, i64)
+DEF_HELPER_FLAGS_4(clm, TCG_CALL_NO_WG, i32, env, i32, i32, i64)
 DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_3(divs32, s64, env, s64, s64)
 DEF_HELPER_3(divu32, i64, env, i64, i64)
@@ -22,8 +22,8 @@ DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
 DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
-DEF_HELPER_4(stam, void, env, i32, i64, i32)
-DEF_HELPER_4(lam, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
 DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
 DEF_HELPER_3(cegb, i64, env, s64, i32)
@@ -79,8 +79,8 @@ DEF_HELPER_2(sqeb, i64, env, i64)
 DEF_HELPER_2(sqdb, i64, env, i64)
 DEF_HELPER_3(sqxb, i64, env, i64, i64)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
-DEF_HELPER_4(unpk, void, env, i32, i64, i64)
-DEF_HELPER_4(tr, void, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64)
+DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
@@ -98,10 +98,10 @@ DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_4(stsi, i32, env, i64, i64, i64)
-DEF_HELPER_4(lctl, void, env, i32, i64, i32)
-DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
-DEF_HELPER_4(stctl, void, env, i32, i64, i32)
-DEF_HELPER_4(stctg, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(lctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(lctlg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(stctl, TCG_CALL_NO_WG, void, env, i32, i64, i32)
+DEF_HELPER_FLAGS_4(stctg, TCG_CALL_NO_WG, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64)
 DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
@@ -114,7 +114,7 @@ DEF_HELPER_2(sacf, void, env, i64)
 DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_2(lra, i64, env, i64)
-DEF_HELPER_3(stura, void, env, i64, i64)
+DEF_HELPER_FLAGS_3(stura, TCG_CALL_NO_WG, void, env, i64, i64)
 #endif
 
 #include "exec/def-helper.h"
commit b7886de3f36111b71ee0664a0b992f6c5b55de7d
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 20 17:09:35 2012 -0700

    target-s390: Perform COMPARE AND SWAP inline
    
    Still no proper solution for CONFIG_USER_ONLY, but the system
    version is significantly better.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index b737633..a5844b3 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -17,9 +17,6 @@ DEF_HELPER_4(srst, i64, env, i64, i64, i64)
 DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
 DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
-DEF_HELPER_4(csg, i64, env, i64, i64, i64)
-DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
-DEF_HELPER_4(cs, i64, env, i64, i64, i64)
 DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 480f1fd..b42ebb6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -193,13 +193,13 @@
     D(0xec7d, CLGIJ,   RIE_c, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
 
 /* COMPARE AND SWAP */
-    C(0xba00, CS,      RS_a,  Z,   r1_o, a2, new, r1_32, cs, 0)
-    C(0xeb14, CSY,     RSY_a, LD,  r1_o, a2, new, r1_32, cs, 0)
-    C(0xeb30, CSG,     RSY_a, Z,   r1_o, a2, r1, 0, csg, 0)
+    D(0xba00, CS,      RS_a,  Z,   r3_32u, r1_32u, new, r1_32, cs, 0, 0)
+    D(0xeb14, CSY,     RSY_a, LD,  r3_32u, r1_32u, new, r1_32, cs, 0, 0)
+    D(0xeb30, CSG,     RSY_a, Z,   r3_o, r1_o, new, r1, cs, 0, 1)
 /* COMPARE DOUBLE AND SWAP */
-    C(0xbb00, CDS,     RS_a,  Z,   r1_D32, a2, new, r1_D32, cds, 0)
-    C(0xeb31, CDSY,    RSY_a, LD,  r1_D32, a2, new, r1_D32, cds, 0)
-    C(0xeb3e, CDSG,    RSY_a, Z,   0, a2, 0, 0, cdsg, 0)
+    D(0xbb00, CDS,     RS_a,  Z,   r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
+    D(0xeb31, CDSY,    RSY_a, LD,  r3_D32, r1_D32, new, r1_D32, cs, 0, 1)
+    C(0xeb3e, CDSG,    RSY_a, Z,   0, 0, 0, 0, cdsg, 0)
 
 /* COMPARE AND TRAP */
     D(0xb972, CRT,     RRF_c, GIE, r1_32s, r2_32s, 0, 0, ct, 0, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 0e9bbd4..372334b 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -442,59 +442,6 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
     return d + len;
 }
 
-/* compare and swap 64-bit */
-uint64_t HELPER(csg)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
-{
-    /* FIXME: locking? */
-    uint64_t v2 = cpu_ldq_data(env, a2);
-    if (r1 == v2) {
-        cpu_stq_data(env, a2, r3);
-        env->cc_op = 0;
-        return r1;
-    } else {
-        env->cc_op = 1;
-        return v2;
-    }
-}
-
-/* compare double and swap 64-bit */
-uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
-{
-    /* FIXME: locking? */
-    uint32_t cc;
-    uint64_t v2_hi = cpu_ldq_data(env, a2);
-    uint64_t v2_lo = cpu_ldq_data(env, a2 + 8);
-    uint64_t v1_hi = env->regs[r1];
-    uint64_t v1_lo = env->regs[r1 + 1];
-
-    if ((v1_hi == v2_hi) && (v1_lo == v2_lo)) {
-        cc = 0;
-        cpu_stq_data(env, a2, env->regs[r3]);
-        cpu_stq_data(env, a2 + 8, env->regs[r3 + 1]);
-    } else {
-        cc = 1;
-        env->regs[r1] = v2_hi;
-        env->regs[r1 + 1] = v2_lo;
-    }
-
-    return cc;
-}
-
-/* compare and swap 32-bit */
-uint64_t HELPER(cs)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
-{
-    /* FIXME: locking? */
-    uint32_t v2 = cpu_ldl_data(env, a2);
-    if ((uint32_t)r1 == v2) {
-        cpu_stl_data(env, a2, (uint32_t)r3);
-        env->cc_op = 0;
-        return r1;
-    } else {
-        env->cc_op = 1;
-        return v2;
-    }
-}
-
 static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
                            uint32_t mask)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0ad78d2..a57296c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1078,8 +1078,9 @@ typedef struct {
 
 #define SPEC_r1_even    1
 #define SPEC_r2_even    2
-#define SPEC_r1_f128    4
-#define SPEC_r2_f128    8
+#define SPEC_r3_even    4
+#define SPEC_r1_f128    8
+#define SPEC_r2_f128    16
 
 /* Return values from translate_one, indicating the state of the TB.  */
 typedef enum {
@@ -1124,9 +1125,9 @@ typedef enum DisasFacility {
 
 struct DisasInsn {
     unsigned opc:16;
-    DisasFormat fmt:6;
-    DisasFacility fac:6;
-    unsigned spec:4;
+    DisasFormat fmt:8;
+    DisasFacility fac:8;
+    unsigned spec:8;
 
     const char *name;
 
@@ -1828,18 +1829,102 @@ static ExitStatus op_cps(DisasContext *s, DisasOps *o)
 
 static ExitStatus op_cs(DisasContext *s, DisasOps *o)
 {
-    int r3 = get_field(s->fields, r3);
-    potential_page_fault(s);
-    gen_helper_cs(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    /* FIXME: needs an atomic solution for CONFIG_USER_ONLY.  */
+    int d2 = get_field(s->fields, d2);
+    int b2 = get_field(s->fields, b2);
+    int is_64 = s->insn->data;
+    TCGv_i64 addr, mem, cc, z;
+
+    /* Note that in1 = R3 (new value) and
+       in2 = (zero-extended) R1 (expected value).  */
+
+    /* Load the memory into the (temporary) output.  While the PoO only talks
+       about moving the memory to R1 on inequality, if we include equality it
+       means that R1 is equal to the memory in all conditions.  */
+    addr = get_address(s, 0, b2, d2);
+    if (is_64) {
+        tcg_gen_qemu_ld64(o->out, addr, get_mem_index(s));
+    } else {
+        tcg_gen_qemu_ld32u(o->out, addr, get_mem_index(s));
+    }
+
+    /* Are the memory and expected values (un)equal?  Note that this setcond
+       produces the output CC value, thus the NE sense of the test.  */
+    cc = tcg_temp_new_i64();
+    tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out);
+
+    /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
+       Recall that we are allowed to unconditionally issue the store (and
+       thus any possible write trap), so (re-)store the original contents
+       of MEM in case of inequality.  */
+    z = tcg_const_i64(0);
+    mem = tcg_temp_new_i64();
+    tcg_gen_movcond_i64(TCG_COND_EQ, mem, cc, z, o->in1, o->out);
+    if (is_64) {
+        tcg_gen_qemu_st64(mem, addr, get_mem_index(s));
+    } else {
+        tcg_gen_qemu_st32(mem, addr, get_mem_index(s));
+    }
+    tcg_temp_free_i64(z);
+    tcg_temp_free_i64(mem);
+    tcg_temp_free_i64(addr);
+
+    /* Store CC back to cc_op.  Wait until after the store so that any
+       exception gets the old cc_op value.  */
+    tcg_gen_trunc_i64_i32(cc_op, cc);
+    tcg_temp_free_i64(cc);
     set_cc_static(s);
     return NO_EXIT;
 }
 
-static ExitStatus op_csg(DisasContext *s, DisasOps *o)
+static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
 {
+    /* FIXME: needs an atomic solution for CONFIG_USER_ONLY.  */
+    int r1 = get_field(s->fields, r1);
     int r3 = get_field(s->fields, r3);
-    potential_page_fault(s);
-    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    int d2 = get_field(s->fields, d2);
+    int b2 = get_field(s->fields, b2);
+    TCGv_i64 addrh, addrl, memh, meml, outh, outl, cc, z;
+
+    /* Note that R1:R1+1 = expected value and R3:R3+1 = new value.  */
+
+    addrh = get_address(s, 0, b2, d2);
+    addrl = get_address(s, 0, b2, d2 + 8);
+    outh = tcg_temp_new_i64();
+    outl = tcg_temp_new_i64();
+
+    tcg_gen_qemu_ld64(outh, addrh, get_mem_index(s));
+    tcg_gen_qemu_ld64(outl, addrl, get_mem_index(s));
+
+    /* Fold the double-word compare with arithmetic.  */
+    cc = tcg_temp_new_i64();
+    z = tcg_temp_new_i64();
+    tcg_gen_xor_i64(cc, outh, regs[r1]);
+    tcg_gen_xor_i64(z, outl, regs[r1 + 1]);
+    tcg_gen_or_i64(cc, cc, z);
+    tcg_gen_movi_i64(z, 0);
+    tcg_gen_setcond_i64(TCG_COND_NE, cc, cc, z);
+
+    memh = tcg_temp_new_i64();
+    meml = tcg_temp_new_i64();
+    tcg_gen_movcond_i64(TCG_COND_EQ, memh, cc, z, regs[r3], outh);
+    tcg_gen_movcond_i64(TCG_COND_EQ, meml, cc, z, regs[r3 + 1], outl);
+    tcg_temp_free_i64(z);
+
+    tcg_gen_qemu_st64(memh, addrh, get_mem_index(s));
+    tcg_gen_qemu_st64(meml, addrl, get_mem_index(s));
+    tcg_temp_free_i64(memh);
+    tcg_temp_free_i64(meml);
+    tcg_temp_free_i64(addrh);
+    tcg_temp_free_i64(addrl);
+
+    /* Save back state now that we've passed all exceptions.  */
+    tcg_gen_mov_i64(regs[r1], outh);
+    tcg_gen_mov_i64(regs[r1 + 1], outl);
+    tcg_gen_trunc_i64_i32(cc_op, cc);
+    tcg_temp_free_i64(outh);
+    tcg_temp_free_i64(outl);
+    tcg_temp_free_i64(cc);
     set_cc_static(s);
     return NO_EXIT;
 }
@@ -1856,29 +1941,6 @@ static ExitStatus op_csp(DisasContext *s, DisasOps *o)
 }
 #endif
 
-static ExitStatus op_cds(DisasContext *s, DisasOps *o)
-{
-    int r3 = get_field(s->fields, r3);
-    TCGv_i64 in3 = tcg_temp_new_i64();
-    tcg_gen_deposit_i64(in3, regs[r3 + 1], regs[r3], 32, 32);
-    potential_page_fault(s);
-    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, in3);
-    tcg_temp_free_i64(in3);
-    set_cc_static(s);
-    return NO_EXIT;
-}
-
-static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
-{
-    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
-    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
-    potential_page_fault(s);
-    /* XXX rewrite in tcg */
-    gen_helper_cdsg(cc_op, cpu_env, r1, o->in2, r3);
-    set_cc_static(s);
-    return NO_EXIT;
-}
-
 static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
@@ -4007,6 +4069,14 @@ static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 }
 #define SPEC_in1_r3_32u 0
 
+static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r3 = get_field(f, r3);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
+}
+#define SPEC_in1_r3_D32 SPEC_r3_even
+
 static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_freg32_i64(get_field(f, r1));
@@ -4121,6 +4191,14 @@ static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 }
 #define SPEC_in2_r1_32u 0
 
+static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r1 = get_field(f, r1);
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
+}
+#define SPEC_in2_r1_D32 SPEC_r1_even
+
 static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r2));
@@ -4580,6 +4658,12 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
                 excp = PGM_SPECIFICATION;
             }
         }
+        if (spec & SPEC_r3_even) {
+            r = get_field(&f, r3);
+            if (r & 1) {
+                excp = PGM_SPECIFICATION;
+            }
+        }
         if (spec & SPEC_r1_f128) {
             r = get_field(&f, r1);
             if (r > 13) {
commit bacf43c62e54ee21494c4bf0c39d96d2bcc0e260
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Sep 21 06:57:09 2012 -0700

    target-s390: Optimize get_address
    
    Don't load the displacement into a register first, add it second
    so that tcg_gen_addi_i64 can eliminate zeros.  Don't mask the
    displacement first so that we don't turn small negative numbers
    into large positive numbers.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8d293d3..0ad78d2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -331,37 +331,29 @@ static inline void check_privileged(DisasContext *s)
 
 static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
 {
-    TCGv_i64 tmp;
+    TCGv_i64 tmp = tcg_temp_new_i64();
+    bool need_31 = !(s->tb->flags & FLAG_MASK_64);
 
-    /* 31-bitify the immediate part; register contents are dealt with below */
-    if (!(s->tb->flags & FLAG_MASK_64)) {
-        d2 &= 0x7fffffffUL;
-    }
+    /* Note that d2 is limited to 20 bits, signed.  If we crop negative
+       displacements early we create larger immedate addends.  */
 
-    if (x2) {
-        if (d2) {
-            tmp = tcg_const_i64(d2);
-            tcg_gen_add_i64(tmp, tmp, regs[x2]);
-        } else {
-            tmp = load_reg(x2);
-        }
-        if (b2) {
-            tcg_gen_add_i64(tmp, tmp, regs[b2]);
-        }
+    /* Note that addi optimizes the imm==0 case.  */
+    if (b2 && x2) {
+        tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
+        tcg_gen_addi_i64(tmp, tmp, d2);
     } else if (b2) {
-        if (d2) {
-            tmp = tcg_const_i64(d2);
-            tcg_gen_add_i64(tmp, tmp, regs[b2]);
-        } else {
-            tmp = load_reg(b2);
-        }
+        tcg_gen_addi_i64(tmp, regs[b2], d2);
+    } else if (x2) {
+        tcg_gen_addi_i64(tmp, regs[x2], d2);
     } else {
-        tmp = tcg_const_i64(d2);
+        if (need_31) {
+            d2 &= 0x7fffffff;
+            need_31 = false;
+        }
+        tcg_gen_movi_i64(tmp, d2);
     }
-
-    /* 31-bit mode mask if there are values loaded from registers */
-    if (!(s->tb->flags & FLAG_MASK_64) && (x2 || b2)) {
-        tcg_gen_andi_i64(tmp, tmp, 0x7fffffffUL);
+    if (need_31) {
+        tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
     }
 
     return tmp;
commit c95ec459c6c39b7a7e1850f82abd95eca4ccfcce
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 20 09:51:40 2012 -0700

    target-s390: Optimize ADDC/SUBB
    
    Giving the proper mask to disas_jcc allows us to generate an inline
    comparison generating the carry/borrow with setcond.
    
    In the very worst case, when we must use the external helper to compute
    a value for CC, we generate (cc > 1) instead of (cc >> 1), which is only
    very slightly slower on common cpus.
    
    In the very best case, when the CC comes from a COMPARE insn and the
    compiler is using ALCG with zero, everything folds out to become just
    the setcond that the compiler wanted.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 04001e3..8d293d3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1344,18 +1344,28 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
 
 static ExitStatus op_addc(DisasContext *s, DisasOps *o)
 {
-    TCGv_i64 cc;
+    DisasCompare cmp;
+    TCGv_i64 carry;
 
     tcg_gen_add_i64(o->out, o->in1, o->in2);
 
-    /* XXX possible optimization point */
-    gen_op_calc_cc(s);
-    cc = tcg_temp_new_i64();
-    tcg_gen_extu_i32_i64(cc, cc_op);
-    tcg_gen_shri_i64(cc, cc, 1);
+    /* The carry flag is the msb of CC, therefore the branch mask that would
+       create that comparison is 3.  Feeding the generated comparison to
+       setcond produces the carry flag that we desire.  */
+    disas_jcc(s, &cmp, 3);
+    carry = tcg_temp_new_i64();
+    if (cmp.is_64) {
+        tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
+    } else {
+        TCGv_i32 t = tcg_temp_new_i32();
+        tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
+        tcg_gen_extu_i32_i64(carry, t);
+        tcg_temp_free_i32(t);
+    }
+    free_compare(&cmp);
 
-    tcg_gen_add_i64(o->out, o->out, cc);
-    tcg_temp_free_i64(cc);
+    tcg_gen_add_i64(o->out, o->out, carry);
+    tcg_temp_free_i64(carry);
     return NO_EXIT;
 }
 
@@ -3397,19 +3407,27 @@ static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 
 static ExitStatus op_subb(DisasContext *s, DisasOps *o)
 {
-    TCGv_i64 cc;
+    DisasCompare cmp;
+    TCGv_i64 borrow;
 
-    assert(!o->g_in2);
-    tcg_gen_not_i64(o->in2, o->in2);
-    tcg_gen_add_i64(o->out, o->in1, o->in2);
+    tcg_gen_sub_i64(o->out, o->in1, o->in2);
 
-    /* XXX possible optimization point */
-    gen_op_calc_cc(s);
-    cc = tcg_temp_new_i64();
-    tcg_gen_extu_i32_i64(cc, cc_op);
-    tcg_gen_shri_i64(cc, cc, 1);
-    tcg_gen_add_i64(o->out, o->out, cc);
-    tcg_temp_free_i64(cc);
+    /* The !borrow flag is the msb of CC.  Since we want the inverse of
+       that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4.  */
+    disas_jcc(s, &cmp, 8 | 4);
+    borrow = tcg_temp_new_i64();
+    if (cmp.is_64) {
+        tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
+    } else {
+        TCGv_i32 t = tcg_temp_new_i32();
+        tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
+        tcg_gen_extu_i32_i64(borrow, t);
+        tcg_temp_free_i32(t);
+    }
+    free_compare(&cmp);
+
+    tcg_gen_sub_i64(o->out, o->out, borrow);
+    tcg_temp_free_i64(borrow);
     return NO_EXIT;
 }
 
commit a359b770c60bf3085c244bc9d5a5fd8fcf286bce
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 20 09:41:33 2012 -0700

    target-s390: Optimize ADDU/SUBU CC testing
    
    We can easily generate some masks for logical add/subtract inline.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2949bb1..04001e3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -692,6 +692,49 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         account_inline_branch(s, old_cc_op);
         break;
 
+    case CC_OP_ADDU_32:
+    case CC_OP_ADDU_64:
+        switch (mask) {
+        case 8 | 2: /* vr == 0 */
+            cond = TCG_COND_EQ;
+            break;
+        case 4 | 1: /* vr != 0 */
+            cond = TCG_COND_NE;
+            break;
+        case 8 | 4: /* no carry -> vr >= src */
+            cond = TCG_COND_GEU;
+            break;
+        case 2 | 1: /* carry -> vr < src */
+            cond = TCG_COND_LTU;
+            break;
+        default:
+            goto do_dynamic;
+        }
+        account_inline_branch(s, old_cc_op);
+        break;
+
+    case CC_OP_SUBU_32:
+    case CC_OP_SUBU_64:
+        /* Note that CC=0 is impossible; treat it as dont-care.  */
+        switch (mask & 7) {
+        case 2: /* zero -> op1 == op2 */
+            cond = TCG_COND_EQ;
+            break;
+        case 4 | 1: /* !zero -> op1 != op2 */
+            cond = TCG_COND_NE;
+            break;
+        case 4: /* borrow (!carry) -> op1 < op2 */
+            cond = TCG_COND_LTU;
+            break;
+        case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
+            cond = TCG_COND_GEU;
+            break;
+        default:
+            goto do_dynamic;
+        }
+        account_inline_branch(s, old_cc_op);
+        break;
+
     default:
     do_dynamic:
         /* Calculate cc value.  */
@@ -719,6 +762,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         break;
     case CC_OP_LTGT_32:
     case CC_OP_LTUGTU_32:
+    case CC_OP_SUBU_32:
         c->is_64 = false;
         c->u.s32.a = tcg_temp_new_i32();
         tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
@@ -735,6 +779,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         break;
     case CC_OP_LTGT_64:
     case CC_OP_LTUGTU_64:
+    case CC_OP_SUBU_64:
         c->u.s64.a = cc_src;
         c->u.s64.b = cc_dst;
         c->g1 = c->g2 = true;
@@ -748,6 +793,29 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
         break;
 
+    case CC_OP_ADDU_32:
+        c->is_64 = false;
+        c->u.s32.a = tcg_temp_new_i32();
+        c->u.s32.b = tcg_temp_new_i32();
+        tcg_gen_trunc_i64_i32(c->u.s32.a, cc_vr);
+        if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
+            tcg_gen_movi_i32(c->u.s32.b, 0);
+        } else {
+            tcg_gen_trunc_i64_i32(c->u.s32.b, cc_src);
+        }
+        break;
+
+    case CC_OP_ADDU_64:
+        c->u.s64.a = cc_vr;
+        c->g1 = true;
+        if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
+            c->u.s64.b = tcg_const_i64(0);
+        } else {
+            c->u.s64.b = cc_src;
+            c->g2 = true;
+        }
+        break;
+
     case CC_OP_STATIC:
         c->is_64 = false;
         c->u.s32.a = cc_op;
commit de379661d5c7cc1d219000d0741f5d96ced56553
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Sep 20 07:55:51 2012 -0700

    target-s390: Tidy comparisons
    
    After full conversion, we can audit the uses of LTGT cc ops
    and see that none of the instructions can ever set CC=3.
    Thus we can extend the table to treat that bit as ignored.
    
    This fixes a regression wrt the pre-conversion translation
    in which NE was used for both m=6 and m=7.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index cfe3766..2949bb1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -577,30 +577,29 @@ static void account_inline_branch(DisasContext *s, int cc_op)
 }
 
 /* Table of mask values to comparison codes, given a comparison as input.
-   For a true comparison CC=3 will never be set, but we treat this
-   conservatively for possible use when CC=3 indicates overflow.  */
+   For such, CC=3 should not be possible.  */
 static const TCGCond ltgt_cond[16] = {
     TCG_COND_NEVER,  TCG_COND_NEVER,     /*    |    |    | x */
-    TCG_COND_GT,     TCG_COND_NEVER,     /*    |    | GT | x */
-    TCG_COND_LT,     TCG_COND_NEVER,     /*    | LT |    | x */
-    TCG_COND_NE,     TCG_COND_NEVER,     /*    | LT | GT | x */
-    TCG_COND_EQ,     TCG_COND_NEVER,     /* EQ |    |    | x */
-    TCG_COND_GE,     TCG_COND_NEVER,     /* EQ |    | GT | x */
-    TCG_COND_LE,     TCG_COND_NEVER,     /* EQ | LT |    | x */
+    TCG_COND_GT,     TCG_COND_GT,        /*    |    | GT | x */
+    TCG_COND_LT,     TCG_COND_LT,        /*    | LT |    | x */
+    TCG_COND_NE,     TCG_COND_NE,        /*    | LT | GT | x */
+    TCG_COND_EQ,     TCG_COND_EQ,        /* EQ |    |    | x */
+    TCG_COND_GE,     TCG_COND_GE,        /* EQ |    | GT | x */
+    TCG_COND_LE,     TCG_COND_LE,        /* EQ | LT |    | x */
     TCG_COND_ALWAYS, TCG_COND_ALWAYS,    /* EQ | LT | GT | x */
 };
 
 /* Table of mask values to comparison codes, given a logic op as input.
    For such, only CC=0 and CC=1 should be possible.  */
 static const TCGCond nz_cond[16] = {
-    /*    |    | x | x */
-    TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER,
-    /*    | NE | x | x */
-    TCG_COND_NE, TCG_COND_NE, TCG_COND_NE, TCG_COND_NE,
-    /* EQ |    | x | x */
-    TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ,
-    /* EQ | NE | x | x */
-    TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS,
+    TCG_COND_NEVER, TCG_COND_NEVER,      /*    |    | x | x */
+    TCG_COND_NEVER, TCG_COND_NEVER,
+    TCG_COND_NE, TCG_COND_NE,            /*    | NE | x | x */
+    TCG_COND_NE, TCG_COND_NE,
+    TCG_COND_EQ, TCG_COND_EQ,            /* EQ |    | x | x */
+    TCG_COND_EQ, TCG_COND_EQ,
+    TCG_COND_ALWAYS, TCG_COND_ALWAYS,    /* EQ | NE | x | x */
+    TCG_COND_ALWAYS, TCG_COND_ALWAYS,
 };
 
 /* Interpret MASK in terms of S->CC_OP, and fill in C with all the
@@ -1463,9 +1462,7 @@ static ExitStatus op_cj(DisasContext *s, DisasOps *o)
     bool is_imm;
     DisasCompare c;
 
-    /* Bit 3 of the m3 field is reserved and should be zero.
-       Choose to ignore it wrt the ltgt_cond table above.  */
-    c.cond = ltgt_cond[m3 & 14];
+    c.cond = ltgt_cond[m3];
     if (s->insn->data) {
         c.cond = tcg_unsigned_cond(c.cond);
     }
@@ -1831,9 +1828,7 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o)
     TCGv_i32 t;
     TCGCond c;
 
-    /* Bit 3 of the m3 field is reserved and should be zero.
-       Choose to ignore it wrt the ltgt_cond table above.  */
-    c = tcg_invert_cond(ltgt_cond[m3 & 14]);
+    c = tcg_invert_cond(ltgt_cond[m3]);
     if (s->insn->data) {
         c = tcg_unsigned_cond(c);
     }
commit f24c49c24a4979fe50eff7afe18f371f5809177d
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 19 13:50:07 2012 -0700

    target-s390: Optmize emitting discards
    
    While they aren't expensive, they aren't free to process.  When we
    know that the three cc helper variables are dead, don't kill them.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 7f8a550..cfe3766 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -367,25 +367,41 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
     return tmp;
 }
 
+static inline bool live_cc_data(DisasContext *s)
+{
+    return (s->cc_op != CC_OP_DYNAMIC
+            && s->cc_op != CC_OP_STATIC
+            && s->cc_op > 3);
+}
+
 static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
 {
+    if (live_cc_data(s)) {
+        tcg_gen_discard_i64(cc_src);
+        tcg_gen_discard_i64(cc_dst);
+        tcg_gen_discard_i64(cc_vr);
+    }
     s->cc_op = CC_OP_CONST0 + val;
 }
 
 static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
 {
-    tcg_gen_discard_i64(cc_src);
+    if (live_cc_data(s)) {
+        tcg_gen_discard_i64(cc_src);
+        tcg_gen_discard_i64(cc_vr);
+    }
     tcg_gen_mov_i64(cc_dst, dst);
-    tcg_gen_discard_i64(cc_vr);
     s->cc_op = op;
 }
 
 static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
                                   TCGv_i64 dst)
 {
+    if (live_cc_data(s)) {
+        tcg_gen_discard_i64(cc_vr);
+    }
     tcg_gen_mov_i64(cc_src, src);
     tcg_gen_mov_i64(cc_dst, dst);
-    tcg_gen_discard_i64(cc_vr);
     s->cc_op = op;
 }
 
@@ -421,9 +437,11 @@ static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
 /* CC value is in env->cc_op */
 static void set_cc_static(DisasContext *s)
 {
-    tcg_gen_discard_i64(cc_src);
-    tcg_gen_discard_i64(cc_dst);
-    tcg_gen_discard_i64(cc_vr);
+    if (live_cc_data(s)) {
+        tcg_gen_discard_i64(cc_src);
+        tcg_gen_discard_i64(cc_dst);
+        tcg_gen_discard_i64(cc_vr);
+    }
     s->cc_op = CC_OP_STATIC;
 }
 
commit d074ac6d266129f8f4e2aac5b0e6c39c22964d9a
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 19 13:48:46 2012 -0700

    target-s390: Optimize XC
    
    Notice XC with same address and convert that to store of zero.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e915984..480f1fd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -271,7 +271,7 @@
     C(0xb982, XGR,     RRE,   Z,   r1, r2, r1, 0, xor, nz64)
     C(0xb9e7, XGRK,    RRF_a, DO,  r2, r3, r1, 0, xor, nz64)
     C(0xe382, XG,      RXY_a, Z,   r1, m2_64, r1, 0, xor, nz64)
-    C(0xd700, XC,      SS_a,  Z,   la1, a2, 0, 0, xc, 0)
+    C(0xd700, XC,      SS_a,  Z,   0, 0, 0, 0, xc, 0)
 /* EXCLUSIVE OR IMMEDIATE */
     D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
     D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 34b9cdf..7f8a550 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3403,10 +3403,54 @@ static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
 
 static ExitStatus op_xc(DisasContext *s, DisasOps *o)
 {
-    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    int d1 = get_field(s->fields, d1);
+    int d2 = get_field(s->fields, d2);
+    int b1 = get_field(s->fields, b1);
+    int b2 = get_field(s->fields, b2);
+    int l = get_field(s->fields, l1);
+    TCGv_i32 t32;
+
+    o->addr1 = get_address(s, 0, b1, d1);
+
+    /* If the addresses are identical, this is a store/memset of zero.  */
+    if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
+        o->in2 = tcg_const_i64(0);
+
+        l++;
+        while (l >= 8) {
+            tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
+            l -= 8;
+            if (l > 0) {
+                tcg_gen_addi_i64(o->addr1, o->addr1, 8);
+            }
+        }
+        if (l >= 4) {
+            tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
+            l -= 4;
+            if (l > 0) {
+                tcg_gen_addi_i64(o->addr1, o->addr1, 4);
+            }
+        }
+        if (l >= 2) {
+            tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
+            l -= 2;
+            if (l > 0) {
+                tcg_gen_addi_i64(o->addr1, o->addr1, 2);
+            }
+        }
+        if (l) {
+            tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
+        }
+        gen_op_movi_cc(s, 0);
+        return NO_EXIT;
+    }
+
+    /* But in general we'll defer to a helper.  */
+    o->in2 = get_address(s, 0, b2, d2);
+    t32 = tcg_const_i32(l);
     potential_page_fault(s);
-    gen_helper_xc(cc_op, cpu_env, l, o->addr1, o->in2);
-    tcg_temp_free_i32(l);
+    gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
+    tcg_temp_free_i32(t32);
     set_cc_static(s);
     return NO_EXIT;
 }
commit 90b4f8ad7226960d3a21bd8fca894ce1e6b5e4cf
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 12 16:52:31 2012 -0700

    target-s390: Fix cpu_clone_regs
    
    R2 is the syscall return register, not R0.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index dc7bbc6..bc3fab2 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -116,7 +116,7 @@ static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
     if (newsp) {
         env->regs[15] = newsp;
     }
-    env->regs[0] = 0;
+    env->regs[2] = 0;
 }
 #endif
 
commit 411edc22cbab9a44f6d6c6cdef8637ba1f313e37
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Sep 10 17:23:13 2012 -0700

    target-s390: Implement LOAD/SET FP AND SIGNAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b6e5040..94375b6 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -674,19 +674,40 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     return RET128(ret);
 }
 
+static const int fpc_to_rnd[4] = {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_up,
+    float_round_down
+};
+
 /* set fpc */
 void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
 {
-    static const int rnd[4] = {
-        float_round_nearest_even,
-        float_round_to_zero,
-        float_round_up,
-        float_round_down
-    };
-
     /* Install everything in the main FPC.  */
     env->fpc = fpc;
 
     /* Install the rounding mode in the shadow fpu_status.  */
-    set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+}
+
+/* set fpc and signal */
+void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+{
+    uint32_t signalling = env->fpc;
+    uint32_t source = val;
+    uint32_t s390_exc;
+
+    /* The contents of the source operand are placed in the FPC register;
+       then the flags in the FPC register are set to the logical OR of the
+       signalling flags and the source flags.  */
+    env->fpc = source | (signalling & 0x00ff0000);
+    set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+
+    /* If any signalling flag is 1 and the corresponding source mask
+       is also 1, a simulated-iee-exception trap occurs.  */
+    s390_exc = (signalling >> 16) & (source >> 24);
+    if (s390_exc) {
+        ieee_exception(env, s390_exc | 3, GETPC());
+    }
 }
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 23d23d5..b737633 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -87,6 +87,7 @@ DEF_HELPER_4(tr, void, env, i32, i64, i64)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 
 #ifndef CONFIG_USER_ONLY
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 79341a4..e915984 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -433,6 +433,8 @@
 
 /* LOAD FPC */
     C(0xb29d, LFPC,    S,     Z,   0, m2_32u, 0, 0, sfpc, 0)
+/* LOAD FPC AND SIGNAL */
+    C(0xb2bd, LFAS,    S,     IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
 
 /* LOAD LENGTHENED */
     C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
@@ -566,6 +568,8 @@
     C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 /* SET FPC */
     C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
+/* SET FPC AND SIGNAL */
+    C(0xb385, SFASR,   RRE,   IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0)
 /* SET BFP ROUNDING MODE */
     C(0xb299, SRNM,    S,     Z,   0, 0, 0, 0, srnm, 0)
     C(0xb2b8, SRNMB,   S,     FPE, 0, 0, 0, 0, srnm, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c4d9fff..34b9cdf 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2921,6 +2921,12 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sfas(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
 {
     int b2 = get_field(s->fields, b2);
commit a12000b9ece917f62d6405e7ee83c8abb6ad7afa
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Sep 10 16:26:35 2012 -0700

    target-s390: Implement SET ROUNDING MODE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6e92790..79341a4 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -566,6 +566,11 @@
     C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 /* SET FPC */
     C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
+/* SET BFP ROUNDING MODE */
+    C(0xb299, SRNM,    S,     Z,   0, 0, 0, 0, srnm, 0)
+    C(0xb2b8, SRNMB,   S,     FPE, 0, 0, 0, 0, srnm, 0)
+/* SET DFP ROUNDING MODE */
+    C(0xb2b9, SRNMT,   S,     DFP, 0, 0, 0, 0, srnm, 0)
 
 /* SHIFT LEFT SINGLE */
     D(0x8b00, SLA,     RS_a,  Z,   r1, sh32, new, r1_32, sla, 0, 31)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b4dd68e..c4d9fff 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2921,6 +2921,45 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
+{
+    int b2 = get_field(s->fields, b2);
+    int d2 = get_field(s->fields, d2);
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i64 t2 = tcg_temp_new_i64();
+    int mask, pos, len;
+
+    switch (s->fields->op2) {
+    case 0x99: /* SRNM */
+        pos = 0, len = 2;
+        break;
+    case 0xb8: /* SRNMB */
+        pos = 0, len = 3;
+        break;
+    case 0xb9: /* SRNMT */
+        pos = 4, len = 3;
+    default:
+        tcg_abort();
+    }
+    mask = (1 << len) - 1;
+
+    /* Insert the value into the appropriate field of the FPC.  */
+    if (b2 == 0) {
+        tcg_gen_movi_i64(t1, d2 & mask);
+    } else {
+        tcg_gen_addi_i64(t1, regs[b2], d2);
+        tcg_gen_andi_i64(t1, t1, mask);
+    }
+    tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
+    tcg_gen_deposit_i64(t2, t2, t1, pos, len);
+    tcg_temp_free_i64(t1);
+
+    /* Then install the new FPC to set the rounding mode in fpu_status.  */
+    gen_helper_sfpc(cpu_env, t2);
+    tcg_temp_free_i64(t2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_spka(DisasContext *s, DisasOps *o)
 {
commit d2d9feac6fa9f6fd40e8f251bcfdd9a9a0f421f8
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Sep 9 16:04:17 2012 -0700

    target-s390: Use uint64_to_float128
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 58c2e61..b6e5040 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -419,8 +419,7 @@ uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
     int hold = swap_round_mode(env, m3);
-    /* ??? Not 50% correct.  */
-    float128 ret = int64_to_float128(v2, &env->fpu_status);
+    float128 ret = uint64_to_float128(v2, &env->fpu_status);
     set_float_rounding_mode(hold, &env->fpu_status);
     handle_exceptions(env, GETPC());
     return RET128(ret);
commit 1d1f63013539bccc877899116cccf106d318b04a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Sep 9 14:31:43 2012 -0700

    target-s390: Implement LCDFR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b023911..6e92790 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -356,6 +356,7 @@
     C(0xb303, LCEBR,   RRE,   Z,   0, e2, new, e1, negf32, f32)
     C(0xb313, LCDBR,   RRE,   Z,   0, f2_o, f1, 0, negf64, f64)
     C(0xb343, LCXBR,   RRE,   Z,   0, x2_o, x1, 0, negf128, f128)
+    C(0xb373, LCDFR,   RRE,   FPSSH, 0, f2_o, f1, 0, negf64, 0)
 /* LOAD HALFWORD */
     C(0xb927, LHR,     RRE,   EI,  0, r2_16s, 0, r1_32, mov2, 0)
     C(0xb907, LGHR,    RRE,   EI,  0, r2_16s, 0, r1, mov2, 0)
commit 49f7ee802fa6695af61dc1e88638f426d47a22a5
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Sep 7 16:16:57 2012 -0700

    target-s390: Check insn operand specifications
    
    Removes all the fixmes for even register numbers, etc.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2873f7d..b4dd68e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -993,6 +993,17 @@ typedef struct {
     TCGv_i64 addr1;
 } DisasOps;
 
+/* Instructions can place constraints on their operands, raising specification
+   exceptions if they are violated.  To make this easy to automate, each "in1",
+   "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
+   of the following, or 0.  To make this easy to document, we'll put the
+   SPEC_<name> defines next to <name>.  */
+
+#define SPEC_r1_even    1
+#define SPEC_r2_even    2
+#define SPEC_r1_f128    4
+#define SPEC_r2_f128    8
+
 /* Return values from translate_one, indicating the state of the TB.  */
 typedef enum {
     /* Continue the TB.  */
@@ -1038,6 +1049,7 @@ struct DisasInsn {
     unsigned opc:16;
     DisasFormat fmt:6;
     DisasFacility fac:6;
+    unsigned spec:4;
 
     const char *name;
 
@@ -3561,42 +3573,46 @@ static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->out = tcg_temp_new_i64();
 }
+#define SPEC_prep_new 0
 
 static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->out = tcg_temp_new_i64();
     o->out2 = tcg_temp_new_i64();
 }
+#define SPEC_prep_new_P 0
 
 static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->out = regs[get_field(f, r1)];
     o->g_out = true;
 }
+#define SPEC_prep_r1 0
 
 static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
     int r1 = get_field(f, r1);
     o->out = regs[r1];
-    o->out2 = regs[(r1 + 1) & 15];
+    o->out2 = regs[r1 + 1];
     o->g_out = o->g_out2 = true;
 }
+#define SPEC_prep_r1_P SPEC_r1_even
 
 static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->out = fregs[get_field(f, r1)];
     o->g_out = true;
 }
+#define SPEC_prep_f1 0
 
 static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be < 14.  */
     int r1 = get_field(f, r1);
     o->out = fregs[r1];
-    o->out2 = fregs[(r1 + 2) & 15];
+    o->out2 = fregs[r1 + 2];
     o->g_out = o->g_out2 = true;
 }
+#define SPEC_prep_x1 SPEC_r1_f128
 
 /* ====================================================================== */
 /* The "Write OUTput" generators.  These generally perform some non-trivial
@@ -3608,58 +3624,64 @@ static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg(get_field(f, r1), o->out);
 }
+#define SPEC_wout_r1 0
 
 static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int r1 = get_field(f, r1);
     tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
 }
+#define SPEC_wout_r1_8 0
 
 static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int r1 = get_field(f, r1);
     tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
 }
+#define SPEC_wout_r1_16 0
 
 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg32_i64(get_field(f, r1), o->out);
 }
+#define SPEC_wout_r1_32 0
 
 static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
     int r1 = get_field(f, r1);
     store_reg32_i64(r1, o->out);
-    store_reg32_i64((r1 + 1) & 15, o->out2);
+    store_reg32_i64(r1 + 1, o->out2);
 }
+#define SPEC_wout_r1_P32 SPEC_r1_even
 
 static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
     int r1 = get_field(f, r1);
-    store_reg32_i64((r1 + 1) & 15, o->out);
+    store_reg32_i64(r1 + 1, o->out);
     tcg_gen_shri_i64(o->out, o->out, 32);
     store_reg32_i64(r1, o->out);
 }
+#define SPEC_wout_r1_D32 SPEC_r1_even
 
 static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_freg32_i64(get_field(f, r1), o->out);
 }
+#define SPEC_wout_e1 0
 
 static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_freg(get_field(f, r1), o->out);
 }
+#define SPEC_wout_f1 0
 
 static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be < 14.  */
     int f1 = get_field(s->fields, r1);
     store_freg(f1, o->out);
-    store_freg((f1 + 2) & 15, o->out2);
+    store_freg(f1 + 2, o->out2);
 }
+#define SPEC_wout_x1 SPEC_r1_f128
 
 static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3667,6 +3689,7 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
         store_reg32_i64(get_field(f, r1), o->out);
     }
 }
+#define SPEC_wout_cond_r1r2_32 0
 
 static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3674,31 +3697,37 @@ static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
         store_freg32_i64(get_field(f, r1), o->out);
     }
 }
+#define SPEC_wout_cond_e1e2 0
 
 static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
 }
+#define SPEC_wout_m1_8 0
 
 static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
 }
+#define SPEC_wout_m1_16 0
 
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
 }
+#define SPEC_wout_m1_32 0
 
 static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
 }
+#define SPEC_wout_m1_64 0
 
 static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
 }
+#define SPEC_wout_m2_32 0
 
 /* ====================================================================== */
 /* The "INput 1" generators.  These load the first operand to an insn.  */
@@ -3707,126 +3736,138 @@ static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r1));
 }
+#define SPEC_in1_r1 0
 
 static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = regs[get_field(f, r1)];
     o->g_in1 = true;
 }
+#define SPEC_in1_r1_o 0
 
 static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = tcg_temp_new_i64();
     tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
 }
+#define SPEC_in1_r1_32s 0
 
 static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = tcg_temp_new_i64();
     tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
 }
+#define SPEC_in1_r1_32u 0
 
 static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = tcg_temp_new_i64();
     tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
 }
+#define SPEC_in1_r1_sr32 0
 
 static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
-    int r1 = get_field(f, r1);
-    o->in1 = load_reg((r1 + 1) & 15);
+    o->in1 = load_reg(get_field(f, r1) + 1);
 }
+#define SPEC_in1_r1p1 SPEC_r1_even
 
 static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
-    int r1 = get_field(f, r1);
     o->in1 = tcg_temp_new_i64();
-    tcg_gen_ext32s_i64(o->in1, regs[(r1 + 1) & 15]);
+    tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
 }
+#define SPEC_in1_r1p1_32s SPEC_r1_even
 
 static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
-    int r1 = get_field(f, r1);
     o->in1 = tcg_temp_new_i64();
-    tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
+    tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
 }
+#define SPEC_in1_r1p1_32u SPEC_r1_even
 
 static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be even.  */
     int r1 = get_field(f, r1);
     o->in1 = tcg_temp_new_i64();
     tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
 }
+#define SPEC_in1_r1_D32 SPEC_r1_even
 
 static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r2));
 }
+#define SPEC_in1_r2 0
 
 static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r3));
 }
+#define SPEC_in1_r3 0
 
 static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = regs[get_field(f, r3)];
     o->g_in1 = true;
 }
+#define SPEC_in1_r3_o 0
 
 static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = tcg_temp_new_i64();
     tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
 }
+#define SPEC_in1_r3_32s 0
 
 static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = tcg_temp_new_i64();
     tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
 }
+#define SPEC_in1_r3_32u 0
 
 static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_freg32_i64(get_field(f, r1));
 }
+#define SPEC_in1_e1 0
 
 static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = fregs[get_field(f, r1)];
     o->g_in1 = true;
 }
+#define SPEC_in1_f1_o 0
 
 static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be < 14.  */
     int r1 = get_field(f, r1);
     o->out = fregs[r1];
-    o->out2 = fregs[(r1 + 2) & 15];
+    o->out2 = fregs[r1 + 2];
     o->g_out = o->g_out2 = true;
 }
+#define SPEC_in1_x1_o SPEC_r1_f128
 
 static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = fregs[get_field(f, r3)];
     o->g_in1 = true;
 }
+#define SPEC_in1_f3_o 0
 
 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
 }
+#define SPEC_in1_la1 0
 
 static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
     o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
 }
+#define SPEC_in1_la2 0
 
 static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3834,6 +3875,7 @@ static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_8u 0
 
 static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3841,6 +3883,7 @@ static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_16s 0
 
 static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3848,6 +3891,7 @@ static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_16u 0
 
 static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3855,6 +3899,7 @@ static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_32s 0
 
 static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3862,6 +3907,7 @@ static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_32u 0
 
 static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3869,6 +3915,7 @@ static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = tcg_temp_new_i64();
     tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
 }
+#define SPEC_in1_m1_64 0
 
 /* ====================================================================== */
 /* The "INput 2" generators.  These load the second operand to an insn.  */
@@ -3878,29 +3925,34 @@ static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = regs[get_field(f, r1)];
     o->g_in2 = true;
 }
+#define SPEC_in2_r1_o 0
 
 static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
 }
+#define SPEC_in2_r1_16u 0
 
 static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
 }
+#define SPEC_in2_r1_32u 0
 
 static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r2));
 }
+#define SPEC_in2_r2 0
 
 static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = regs[get_field(f, r2)];
     o->g_in2 = true;
 }
+#define SPEC_in2_r2_o 0
 
 static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
 {
@@ -3909,185 +3961,216 @@ static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
         o->in2 = load_reg(r2);
     }
 }
+#define SPEC_in2_r2_nz 0
 
 static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_8s 0
 
 static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_8u 0
 
 static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_16s 0
 
 static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_16u 0
 
 static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r3));
 }
+#define SPEC_in2_r3 0
 
 static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_32s 0
 
 static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
     tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
 }
+#define SPEC_in2_r2_32u 0
 
 static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_freg32_i64(get_field(f, r2));
 }
+#define SPEC_in2_e2 0
 
 static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = fregs[get_field(f, r2)];
     o->g_in2 = true;
 }
+#define SPEC_in2_f2_o 0
 
 static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    /* ??? Specification exception: r1 must be < 14.  */
     int r2 = get_field(f, r2);
     o->in1 = fregs[r2];
-    o->in2 = fregs[(r2 + 2) & 15];
+    o->in2 = fregs[r2 + 2];
     o->g_in1 = o->g_in2 = true;
 }
+#define SPEC_in2_x2_o SPEC_r2_f128
 
 static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = get_address(s, 0, get_field(f, r2), 0);
 }
+#define SPEC_in2_ra2 0
 
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
     o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
 }
+#define SPEC_in2_a2 0
 
 static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
 }
+#define SPEC_in2_ri2 0
 
 static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     help_l2_shift(s, f, o, 31);
 }
+#define SPEC_in2_sh32 0
 
 static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     help_l2_shift(s, f, o, 63);
 }
+#define SPEC_in2_sh64 0
 
 static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_8u 0
 
 static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_16s 0
 
 static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_16u 0
 
 static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_32s 0
 
 static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_32u 0
 
 static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
     tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_m2_64 0
 
 static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_ri2(s, f, o);
     tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_mri2_16u 0
 
 static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_ri2(s, f, o);
     tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_mri2_32s 0
 
 static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_ri2(s, f, o);
     tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_mri2_32u 0
 
 static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_ri2(s, f, o);
     tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
 }
+#define SPEC_in2_mri2_64 0
 
 static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64(get_field(f, i2));
 }
+#define SPEC_in2_i2 0
 
 static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
 }
+#define SPEC_in2_i2_8u 0
 
 static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
 }
+#define SPEC_in2_i2_16u 0
 
 static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
 }
+#define SPEC_in2_i2_32u 0
 
 static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     uint64_t i2 = (uint16_t)get_field(f, i2);
     o->in2 = tcg_const_i64(i2 << s->insn->data);
 }
+#define SPEC_in2_i2_16u_shl 0
 
 static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     uint64_t i2 = (uint32_t)get_field(f, i2);
     o->in2 = tcg_const_i64(i2 << s->insn->data);
 }
+#define SPEC_in2_i2_32u_shl 0
 
 /* ====================================================================== */
 
@@ -4106,18 +4189,19 @@ enum DisasInsnEnum {
 };
 
 #undef D
-#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
-    .opc = OPC,                           \
-    .fmt = FMT_##FT,                      \
-    .fac = FAC_##FC,                      \
-    .name = #NM,                          \
-    .help_in1 = in1_##I1,                 \
-    .help_in2 = in2_##I2,                 \
-    .help_prep = prep_##P,                \
-    .help_wout = wout_##W,                \
-    .help_cout = cout_##CC,               \
-    .help_op = op_##OP,                   \
-    .data = D                             \
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) {                       \
+    .opc = OPC,                                                             \
+    .fmt = FMT_##FT,                                                        \
+    .fac = FAC_##FC,                                                        \
+    .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W,  \
+    .name = #NM,                                                            \
+    .help_in1 = in1_##I1,                                                   \
+    .help_in2 = in2_##I2,                                                   \
+    .help_prep = prep_##P,                                                  \
+    .help_wout = wout_##W,                                                  \
+    .help_cout = cout_##CC,                                                 \
+    .help_op = op_##OP,                                                     \
+    .data = D                                                               \
  },
 
 /* Allow 0 to be used for NULL in the table below.  */
@@ -4128,6 +4212,11 @@ enum DisasInsnEnum {
 #define cout_0  NULL
 #define op_0  NULL
 
+#define SPEC_in1_0 0
+#define SPEC_in2_0 0
+#define SPEC_prep_0 0
+#define SPEC_wout_0 0
+
 static const DisasInsn insn_info[] = {
 #include "insn-data.def"
 };
@@ -4295,6 +4384,40 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
         return EXIT_NORETURN;
     }
 
+    /* Check for insn specification exceptions.  */
+    if (insn->spec) {
+        int spec = insn->spec, excp = 0, r;
+
+        if (spec & SPEC_r1_even) {
+            r = get_field(&f, r1);
+            if (r & 1) {
+                excp = PGM_SPECIFICATION;
+            }
+        }
+        if (spec & SPEC_r2_even) {
+            r = get_field(&f, r2);
+            if (r & 1) {
+                excp = PGM_SPECIFICATION;
+            }
+        }
+        if (spec & SPEC_r1_f128) {
+            r = get_field(&f, r1);
+            if (r > 13) {
+                excp = PGM_SPECIFICATION;
+            }
+        }
+        if (spec & SPEC_r2_f128) {
+            r = get_field(&f, r2);
+            if (r > 13) {
+                excp = PGM_SPECIFICATION;
+            }
+        }
+        if (excp) {
+            gen_program_exception(s, excp);
+            return EXIT_NORETURN;
+        }
+    }
+
     /* Set up the strutures we use to communicate with the helpers. */
     s->insn = insn;
     s->fields = &f;
commit 2db014b5a73f295f6edbdc2c8400a94ccfc90624
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 14:13:52 2012 -0700

    target-s390: Implement CPSDR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 49e4a44..b023911 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -104,6 +104,9 @@
 /* CHECKSUM */
     C(0xb241, CKSM,    RRE,   Z,   r1_o, ra2, new, r1_32, cksm, 0)
 
+/* COPY SIGN */
+    C(0xb372, CPSDR,   RRF_b, FPSSH, f3_o, f2_o, f1, 0, cps, 0)
+
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
     C(0x5900, C,       RX_a,  Z,   r1_o, m2_32s, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index fe88095..2873f7d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1719,6 +1719,16 @@ static ExitStatus op_clst(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_cps(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t = tcg_temp_new_i64();
+    tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull);
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
+    tcg_gen_or_i64(o->out, o->out, t);
+    tcg_temp_free_i64(t);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cs(DisasContext *s, DisasOps *o)
 {
     int r3 = get_field(s->fields, r3);
@@ -3801,6 +3811,12 @@ static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_out = o->g_out2 = true;
 }
 
+static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = fregs[get_field(f, r3)];
+    o->g_in1 = true;
+}
+
 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
commit 99b4f24b3e636ab241b53bc16bf8f0a0ac4a2271
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 11:14:04 2012 -0700

    target-s390: Implement POPCNT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index aef6f0f..23d23d5 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -87,6 +87,7 @@ DEF_HELPER_4(tr, void, env, i32, i64, i64)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0777b55..49e4a44 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -539,6 +539,9 @@
     C(0xe336, PFD,     RXY_b, GIE, 0, 0, 0, 0, 0, 0)
     C(0xc602, PFDRL,   RIL_c, GIE, 0, 0, 0, 0, 0, 0)
 
+/* POPULATION COUNT */
+    C(0xb9e1, POPCNT,  RRE,   PC,  0, r2_o, r1, 0, popcnt, nz64)
+
 /* ROTATE LEFT SINGLE LOGICAL */
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index dc16de2..6858301 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -191,3 +191,15 @@ uint64_t HELPER(cvd)(int32_t bin)
 
     return dec;
 }
+
+uint64_t HELPER(popcnt)(uint64_t r2)
+{
+    uint64_t ret = 0;
+    int i;
+
+    for (i = 0; i < 64; i += 8) {
+        uint64_t t = ctpop32((r2 >> i) & 0xff);
+        ret |= t << i;
+    }
+    return ret;
+}
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dc5aac7..fe88095 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2558,6 +2558,12 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
+{
+    gen_helper_popcnt(o->out, o->in2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
 {
commit 2112bf1bfb696def31b211425e5e74e89f9574c3
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 11:08:17 2012 -0700

    target-s390: Implement CONVERT FROM LOGICAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 6a76541..58c2e61 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -395,6 +395,37 @@ uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
     return RET128(ret);
 }
 
+/* convert 64-bit uint to 32-bit float */
+uint64_t HELPER(celgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float32 ret = uint64_to_float32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit uint to 64-bit float */
+uint64_t HELPER(cdlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float64 ret = uint64_to_float64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit uint to 128-bit float */
+uint64_t HELPER(cxlgb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    /* ??? Not 50% correct.  */
+    float128 ret = int64_to_float128(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
+}
+
 /* convert 32-bit float to 64-bit int */
 uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0204e85..aef6f0f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -32,6 +32,9 @@ DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
 DEF_HELPER_3(cegb, i64, env, s64, i32)
 DEF_HELPER_3(cdgb, i64, env, s64, i32)
 DEF_HELPER_3(cxgb, i64, env, s64, i32)
+DEF_HELPER_3(celgb, i64, env, i64, i32)
+DEF_HELPER_3(cdlgb, i64, env, i64, i32)
+DEF_HELPER_3(cxlgb, i64, env, i64, i32)
 DEF_HELPER_3(aeb, i64, env, i64, i64)
 DEF_HELPER_3(adb, i64, env, i64, i64)
 DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a67fdcc..0777b55 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -233,6 +233,13 @@
     C(0xb3ac, CLGEBR,  RRF_e, FPE, 0, e2, r1, 0, clgeb, 0)
     C(0xb3ad, CLGDBR,  RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0)
     C(0xb3ae, CLGXBR,  RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0)
+/* CONVERT FROM LOGICAL */
+    C(0xb390, CELFBR,  RRF_e, FPE, 0, r2_32u, new, e1, celgb, 0)
+    C(0xb391, CDLFBR,  RRF_e, FPE, 0, r2_32u, f1, 0, cdlgb, 0)
+    C(0xb392, CXLFBR,  RRF_e, FPE, 0, r2_32u, x1, 0, cxlgb, 0)
+    C(0xb3a0, CELGBR,  RRF_e, FPE, 0, r2_o, new, e1, celgb, 0)
+    C(0xb3a1, CDLGBR,  RRF_e, FPE, 0, r2_o, f1, 0, cdlgb, 0)
+    C(0xb3a2, CXLGBR,  RRF_e, FPE, 0, r2_o, x1, 0, cxlgb, 0)
 
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1b7a8dc..dc5aac7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1609,6 +1609,31 @@ static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_celgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_celgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
 {
     int r2 = get_field(s->fields, r2);
commit 6ac1b45f9b3cb788255c0fde7637ba663eba632c
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 10:42:54 2012 -0700

    target-s390: Implement CONVERT TO LOGICAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 74b94f2..6a76541 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -457,6 +457,72 @@ uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
     return ret;
 }
 
+/* convert 32-bit float to 64-bit uint */
+uint64_t HELPER(clgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    uint64_t ret;
+    v2 = float32_to_float64(v2, &env->fpu_status);
+    ret = float64_to_uint64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit float to 64-bit uint */
+uint64_t HELPER(clgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    uint64_t ret = float64_to_uint64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 128-bit float to 64-bit uint */
+uint64_t HELPER(clgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float128 v2 = make_float128(h, l);
+    /* ??? Not 100% correct.  */
+    uint64_t ret = float128_to_int64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 32-bit float to 32-bit uint */
+uint64_t HELPER(clfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    uint32_t ret = float32_to_uint32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit float to 32-bit uint */
+uint64_t HELPER(clfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    uint32_t ret = float64_to_uint32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 128-bit float to 32-bit uint */
+uint64_t HELPER(clfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float128 v2 = make_float128(h, l);
+    /* Not 100% correct.  */
+    uint32_t ret = float128_to_int64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
 /* 32-bit FP multiply and add */
 uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5d8a821..0204e85 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -61,6 +61,12 @@ DEF_HELPER_4(cgxb, i64, env, i64, i64, i32)
 DEF_HELPER_3(cfeb, i64, env, i64, i32)
 DEF_HELPER_3(cfdb, i64, env, i64, i32)
 DEF_HELPER_4(cfxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(clgeb, i64, env, i64, i32)
+DEF_HELPER_3(clgdb, i64, env, i64, i32)
+DEF_HELPER_4(clgxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(clfeb, i64, env, i64, i32)
+DEF_HELPER_3(clfdb, i64, env, i64, i32)
+DEF_HELPER_4(clfxb, i64, env, i64, i64, i32)
 DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
 DEF_HELPER_4(madb, i64, env, i64, i64, i64)
 DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 00b95b6..a67fdcc 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -226,6 +226,13 @@
     C(0xb3a4, CEGBR,   RRF_e, Z,   0, r2_o, new, e1, cegb, 0)
     C(0xb3a5, CDGBR,   RRF_e, Z,   0, r2_o, f1, 0, cdgb, 0)
     C(0xb3a6, CXGBR,   RRF_e, Z,   0, r2_o, x1, 0, cxgb, 0)
+/* CONVERT TO LOGICAL */
+    C(0xb39c, CLFEBR,  RRF_e, FPE, 0, e2, new, r1_32, clfeb, 0)
+    C(0xb39d, CLFDBR,  RRF_e, FPE, 0, f2_o, new, r1_32, clfdb, 0)
+    C(0xb39e, CLFXBR,  RRF_e, FPE, 0, x2_o, new, r1_32, clfxb, 0)
+    C(0xb3ac, CLGEBR,  RRF_e, FPE, 0, e2, r1, 0, clgeb, 0)
+    C(0xb3ad, CLGDBR,  RRF_e, FPE, 0, f2_o, r1, 0, clgdb, 0)
+    C(0xb3ae, CLGXBR,  RRF_e, FPE, 0, x2_o, r1, 0, clgxb, 0)
 
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 321fc46..1b7a8dc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1530,6 +1530,60 @@ static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_clfeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clfdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clfxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clgeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clgdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_clgxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
commit b92fa33486b240404923308b483a3318eb804c4a
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 09:45:20 2012 -0700

    target-s390: Implement STORE ON CONDITION
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 91ee055..00b95b6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -601,6 +601,9 @@
     C(0xe370, STHY,    RXY_a, LD,  r1_o, a2, 0, 0, st16, 0)
 /* STORE HALFWORD RELATIVE LONG */
     C(0xc407, STHRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+/* STORE ON CONDITION */
+    D(0xebf3, STOC,    RSY_b, LOC, 0, 0, 0, 0, soc, 0, 0)
+    D(0xebe3, STOCG,   RSY_b, LOC, 0, 0, 0, 0, soc, 0, 1)
 /* STORE REVERSED */
     C(0xe33f, STRVH,   RXY_a, Z,   la2, r1_16u, new, m1_16, rev16, 0)
     C(0xe33e, STRV,    RXY_a, Z,   la2, r1_32u, new, m1_32, rev32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1edb066..321fc46 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2747,6 +2747,35 @@ static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_soc(DisasContext *s, DisasOps *o)
+{
+    DisasCompare c;
+    TCGv_i64 a;
+    int lab, r1;
+
+    disas_jcc(s, &c, get_field(s->fields, m3));
+
+    lab = gen_new_label();
+    if (c.is_64) {
+        tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
+    } else {
+        tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
+    }
+    free_compare(&c);
+
+    r1 = get_field(s->fields, r1);
+    a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
+    if (s->insn->data) {
+        tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
+    } else {
+        tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
+    }
+    tcg_temp_free_i64(a);
+
+    gen_set_label(lab);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sla(DisasContext *s, DisasOps *o)
 {
     uint64_t sign = 1ull << s->insn->data;
commit 632086da28e1682c0129276656ee0d32274fcd17
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:55:00 2012 -0700

    target-s390: Implement LOAD ON CONDITION
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b739d70..91ee055 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -390,6 +390,11 @@
     C(0xb301, LNEBR,   RRE,   Z,   0, e2, new, e1, nabsf32, f32)
     C(0xb311, LNDBR,   RRE,   Z,   0, f2_o, f1, 0, nabsf64, f64)
     C(0xb341, LNXBR,   RRE,   Z,   0, x2_o, x1, 0, nabsf128, f128)
+/* LOAD ON CONDITION */
+    C(0xb9f2, LOCR,    RRF_c, LOC, r1, r2, new, r1_32, loc, 0)
+    C(0xb9e2, LOCGR,   RRF_c, LOC, r1, r2, r1, 0, loc, 0)
+    C(0xebf2, LOC,     RSY_b, LOC, r1, m2_32u, new, r1_32, loc, 0)
+    C(0xebe2, LOCG,    RSY_b, LOC, r1, m2_64, r1, 0, loc, 0)
 /* LOAD POSITIVE */
     C(0x1000, LPR,     RR_a,  Z,   0, r2_32s, new, r1_32, abs, abs32)
     C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e94c663..1edb066 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2045,6 +2045,36 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_loc(DisasContext *s, DisasOps *o)
+{
+    DisasCompare c;
+
+    disas_jcc(s, &c, get_field(s->fields, m3));
+
+    if (c.is_64) {
+        tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
+                            o->in2, o->in1);
+        free_compare(&c);
+    } else {
+        TCGv_i32 t32 = tcg_temp_new_i32();
+        TCGv_i64 t, z;
+
+        tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
+        free_compare(&c);
+
+        t = tcg_temp_new_i64();
+        tcg_gen_extu_i32_i64(t, t32);
+        tcg_temp_free_i32(t32);
+
+        z = tcg_const_i64(0);
+        tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
+        tcg_temp_free_i64(t);
+        tcg_temp_free_i64(z);
+    }
+
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
 {
commit 1c2687518235aa38dd3dd270fc216e559d0509eb
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 17:32:54 2012 -0700

    target-s390: Implement COMPARE AND TRAP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5c19aef..b739d70 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -198,6 +198,17 @@
     C(0xeb31, CDSY,    RSY_a, LD,  r1_D32, a2, new, r1_D32, cds, 0)
     C(0xeb3e, CDSG,    RSY_a, Z,   0, a2, 0, 0, cdsg, 0)
 
+/* COMPARE AND TRAP */
+    D(0xb972, CRT,     RRF_c, GIE, r1_32s, r2_32s, 0, 0, ct, 0, 0)
+    D(0xb960, CGRT,    RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 0)
+    D(0xec72, CIT,     RIE_a, GIE, r1_32s, i2, 0, 0, ct, 0, 0)
+    D(0xec70, CGIT,    RIE_a, GIE, r1_o, i2, 0, 0, ct, 0, 0)
+/* COMPARE LOGICAL AND TRAP */
+    D(0xb973, CLRT,    RRF_c, GIE, r1_32u, r2_32u, 0, 0, ct, 0, 1)
+    D(0xb961, CLGRT,   RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 1)
+    D(0xec73, CLFIT,   RIE_a, GIE, r1_32u, i2_32u, 0, 0, ct, 0, 1)
+    D(0xec71, CLGIT,   RIE_a, GIE, r1_o, i2_32u, 0, 0, ct, 0, 0)
+
 /* CONVERT TO DECIMAL */
     C(0x4e00, CVD,     RX_a,  Z,   r1_o, a2, 0, 0, cvd, 0)
     C(0xe326, CVDY,    RXY_a, LD,  r1_o, a2, 0, 0, cvd, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dbc43a6..e94c663 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1705,6 +1705,35 @@ static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ct(DisasContext *s, DisasOps *o)
+{
+    int m3 = get_field(s->fields, m3);
+    int lab = gen_new_label();
+    TCGv_i32 t;
+    TCGCond c;
+
+    /* Bit 3 of the m3 field is reserved and should be zero.
+       Choose to ignore it wrt the ltgt_cond table above.  */
+    c = tcg_invert_cond(ltgt_cond[m3 & 14]);
+    if (s->insn->data) {
+        c = tcg_unsigned_cond(c);
+    }
+    tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
+
+    /* Set DXC to 0xff.  */
+    t = tcg_temp_new_i32();
+    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
+    tcg_gen_ori_i32(t, t, 0xff00);
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
+    tcg_temp_free_i32(t);
+
+    /* Trap.  */
+    gen_program_exception(s, PGM_DATA);
+
+    gen_set_label(lab);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_diag(DisasContext *s, DisasOps *o)
 {
commit 403e217f4073b885b7e02a1b64054ceca7202bf6
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:54:00 2012 -0700

    target-s390: Implement COMPARE RELATIVE LONG
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index eb88c55..5c19aef 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -120,6 +120,10 @@
 /* COMPARE IMMEDIATE */
     C(0xc20d, CFI,     RIL_a, EI,  r1, i2, 0, 0, 0, cmps32)
     C(0xc20c, CGFI,    RIL_a, EI,  r1, i2, 0, 0, 0, cmps64)
+/* COMPARE RELATIVE LONG */
+    C(0xc60d, CRL,     RIL_b, GIE, r1, mri2_32s, 0, 0, 0, cmps32)
+    C(0xc608, CGRL,    RIL_b, GIE, r1, mri2_64, 0, 0, 0, cmps64)
+    C(0xc60c, CGFRL,   RIL_b, GIE, r1, mri2_32s, 0, 0, 0, cmps64)
 /* COMPARE HALFWORD */
     C(0x4900, CH,      RX_a,  Z,   r1_o, m2_16s, 0, 0, 0, cmps32)
     C(0xe379, CHY,     RXY_a, LD,  r1_o, m2_16s, 0, 0, 0, cmps32)
commit e0def9094ef1997613e488768405bcfb589f0596
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 31 14:10:05 2012 -0700

    target-s390: Implement PREFETCH
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9582f0c..eb88c55 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -500,6 +500,11 @@
     C(0x9600, OI,      SI,    Z,   m1_8u, i2_8u, new, m1_8, or, nz64)
     C(0xeb56, OIY,     SIY,   LD,  m1_8u, i2_8u, new, m1_8, or, nz64)
 
+/* PREFETCH */
+    /* Implemented as nops of course.  */
+    C(0xe336, PFD,     RXY_b, GIE, 0, 0, 0, 0, 0, 0)
+    C(0xc602, PFDRL,   RIL_c, GIE, 0, 0, 0, 0, 0, 0)
+
 /* ROTATE LEFT SINGLE LOGICAL */
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
commit d6c6372e186e7f17fe9eeec0c50a43b484669d71
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 31 13:54:13 2012 -0700

    target-s390: Implement R[NOX]SBG
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8bcfb2b..9582f0c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,6 +508,10 @@
     C(0xec55, RISBG,   RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
     C(0xec5d, RISBHG,  RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
     C(0xec51, RISBLG,  RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+/* ROTATE_THEN <OP> SELECTED BITS */
+    C(0xec54, RNSBG,   RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+    C(0xec56, ROSBG,   RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
+    C(0xec57, RXSBG,   RIE_f, GIE, 0, r2, r1, 0, rosbg, 0)
 
 /* SEARCH STRING */
     C(0xb25e, SRST,    RRE,   Z,   r1_o, r2_o, 0, 0, srst, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1f8659f..dbc43a6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2512,6 +2512,59 @@ static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
+{
+    int i3 = get_field(s->fields, i3);
+    int i4 = get_field(s->fields, i4);
+    int i5 = get_field(s->fields, i5);
+    uint64_t mask;
+
+    /* If this is a test-only form, arrange to discard the result.  */
+    if (i3 & 0x80) {
+        o->out = tcg_temp_new_i64();
+        o->g_out = false;
+    }
+
+    i3 &= 63;
+    i4 &= 63;
+    i5 &= 63;
+
+    /* MASK is the set of bits to be operated on from R2.
+       Take care for I3/I4 wraparound.  */
+    mask = ~0ull >> i3;
+    if (i3 <= i4) {
+        mask ^= ~0ull >> i4 >> 1;
+    } else {
+        mask |= ~(~0ull >> i4 >> 1);
+    }
+
+    /* Rotate the input as necessary.  */
+    tcg_gen_rotli_i64(o->in2, o->in2, i5);
+
+    /* Operate.  */
+    switch (s->fields->op2) {
+    case 0x55: /* AND */
+        tcg_gen_ori_i64(o->in2, o->in2, ~mask);
+        tcg_gen_and_i64(o->out, o->out, o->in2);
+        break;
+    case 0x56: /* OR */
+        tcg_gen_andi_i64(o->in2, o->in2, mask);
+        tcg_gen_or_i64(o->out, o->out, o->in2);
+        break;
+    case 0x57: /* XOR */
+        tcg_gen_andi_i64(o->in2, o->in2, mask);
+        tcg_gen_xor_i64(o->out, o->out, o->in2);
+        break;
+    default:
+        abort();
+    }
+
+    /* Set the CC.  */
+    tcg_gen_andi_i64(cc_dst, o->out, mask);
+    set_cc_nz_u64(s, cc_dst);
+    return NO_EXIT;
+}
+
 static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
 {
     tcg_gen_bswap16_i64(o->out, o->in2);
commit 143cbbc5ebc4a5b5beb82dc31ecc5ac5f6d511d2
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:52:08 2012 -0700

    target-s390: Implement LDGR, LGDR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c80a386..8bcfb2b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -364,6 +364,10 @@
 /* LOAD LOGICAL THIRTY ONE BITS */
     C(0xb917, LLGTR,   RRE,   Z,  0, r2_o, r1, 0, llgt, 0)
     C(0xe317, LLGT,    RXY_a, Z,  0, m2_32u, r1, 0, llgt, 0)
+/* LOAD FPR FROM GR */
+    C(0xb3c1, LDGR,    RRE,   FPRGR, 0, r2_o, 0, f1, mov2, 0)
+/* LOAD GR FROM FPR */
+    C(0xb3cd, LGDR,    RRE,   FPRGR, 0, f2_o, 0, r1, mov2, 0)
 /* LOAD NEGATIVE */
     C(0x1100, LNR,     RR_a,  Z,   0, r2_32s, new, r1_32, nabs, nabs32)
     C(0xb901, LNGR,    RRE,   Z,   0, r2, r1, 0, nabs, nabs64)
commit 2d6a869833d99d89fc4bbe42bdb35b2c1d808067
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 31 12:50:06 2012 -0700

    target-s390: Implement RISBG
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4478d1c..c80a386 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -500,6 +500,11 @@
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
 
+/* ROTATE THEN INSERT SELECTED BITS */
+    C(0xec55, RISBG,   RIE_f, GIE, 0, r2, r1, 0, risbg, s64)
+    C(0xec5d, RISBHG,  RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+    C(0xec51, RISBLG,  RIE_f, GIE, 0, r2, r1, 0, risbg, 0)
+
 /* SEARCH STRING */
     C(0xb25e, SRST,    RRE,   Z,   r1_o, r2_o, 0, 0, srst, 0)
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d6f7121..1f8659f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2429,6 +2429,89 @@ static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
+{
+    int i3 = get_field(s->fields, i3);
+    int i4 = get_field(s->fields, i4);
+    int i5 = get_field(s->fields, i5);
+    int do_zero = i4 & 0x80;
+    uint64_t mask, imask, pmask;
+    int pos, len, rot;
+
+    /* Adjust the arguments for the specific insn.  */
+    switch (s->fields->op2) {
+    case 0x55: /* risbg */
+        i3 &= 63;
+        i4 &= 63;
+        pmask = ~0;
+        break;
+    case 0x5d: /* risbhg */
+        i3 &= 31;
+        i4 &= 31;
+        pmask = 0xffffffff00000000ull;
+        break;
+    case 0x51: /* risblg */
+        i3 &= 31;
+        i4 &= 31;
+        pmask = 0x00000000ffffffffull;
+        break;
+    default:
+        abort();
+    }
+
+    /* MASK is the set of bits to be inserted from R2.
+       Take care for I3/I4 wraparound.  */
+    mask = pmask >> i3;
+    if (i3 <= i4) {
+        mask ^= pmask >> i4 >> 1;
+    } else {
+        mask |= ~(pmask >> i4 >> 1);
+    }
+    mask &= pmask;
+
+    /* IMASK is the set of bits to be kept from R1.  In the case of the high/low
+       insns, we need to keep the other half of the register.  */
+    imask = ~mask | ~pmask;
+    if (do_zero) {
+        if (s->fields->op2 == 0x55) {
+            imask = 0;
+        } else {
+            imask = ~pmask;
+        }
+    }
+
+    /* In some cases we can implement this with deposit, which can be more
+       efficient on some hosts.  */
+    if (~mask == imask && i3 <= i4) {
+        if (s->fields->op2 == 0x5d) {
+            i3 += 32, i4 += 32;
+        }
+        /* Note that we rotate the bits to be inserted to the lsb, not to
+           the position as described in the PoO.  */
+        len = i4 - i3 + 1;
+        pos = 63 - i4;
+        rot = (i5 - pos) & 63;
+    } else {
+        pos = len = -1;
+        rot = i5 & 63;
+    }
+
+    /* Rotate the input as necessary.  */
+    tcg_gen_rotli_i64(o->in2, o->in2, rot);
+
+    /* Insert the selected bits into the output.  */
+    if (pos >= 0) {
+        tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
+    } else if (imask == 0) {
+        tcg_gen_andi_i64(o->out, o->in2, mask);
+    } else {
+        tcg_gen_andi_i64(o->in2, o->in2, mask);
+        tcg_gen_andi_i64(o->out, o->out, imask);
+        tcg_gen_or_i64(o->out, o->out, o->in2);
+    }
+    return NO_EXIT;
+}
+
 static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
 {
     tcg_gen_bswap16_i64(o->out, o->in2);
commit 5550359f07b54d6fb6f38ee5dcbc198cff42bf51
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 31 10:53:49 2012 -0700

    target-s390: Implement COMPARE AND BRANCH
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8b89ce6..4478d1c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -166,6 +166,25 @@
 /* COMPARE LOGICAL STRING */
     C(0xb25d, CLST,    RRE,   Z,   r1_o, r2_o, 0, 0, clst, 0)
 
+/* COMPARE AND BRANCH */
+    D(0xecf6, CRB,     RRS,   GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
+    D(0xece4, CGRB,    RRS,   GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
+    D(0xec76, CRJ,     RIE_b, GIE, r1_32s, r2_32s, 0, 0, cj, 0, 0)
+    D(0xec64, CGRJ,    RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 0)
+    D(0xecfe, CIB,     RIS,   GIE, r1_32s, i2, 0, 0, cj, 0, 0)
+    D(0xecfc, CGIB,    RIS,   GIE, r1_o, i2, 0, 0, cj, 0, 0)
+    D(0xec7e, CIJ,     RIE_c, GIE, r1_32s, i2, 0, 0, cj, 0, 0)
+    D(0xec7c, CGIJ,    RIE_c, GIE, r1_o, i2, 0, 0, cj, 0, 0)
+/* COMPARE LOGICAL AND BRANCH */
+    D(0xecf7, CLRB,    RRS,   GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
+    D(0xece5, CLGRB,   RRS,   GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
+    D(0xec77, CLRJ,    RIE_b, GIE, r1_32u, r2_32u, 0, 0, cj, 0, 1)
+    D(0xec65, CLGRJ,   RIE_b, GIE, r1_o, r2_o, 0, 0, cj, 0, 1)
+    D(0xecff, CLIB,    RIS,   GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
+    D(0xecfd, CLGIB,   RIS,   GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
+    D(0xec7f, CLIJ,    RIE_c, GIE, r1_32u, i2_8u, 0, 0, cj, 0, 1)
+    D(0xec7d, CLGIJ,   RIE_c, GIE, r1_o, i2_8u, 0, 0, cj, 0, 1)
+
 /* COMPARE AND SWAP */
     C(0xba00, CS,      RS_a,  Z,   r1_o, a2, new, r1_32, cs, 0)
     C(0xeb14, CSY,     RSY_a, LD,  r1_o, a2, new, r1_32, cs, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c87d97f..d6f7121 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1427,6 +1427,34 @@ static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_cj(DisasContext *s, DisasOps *o)
+{
+    int imm, m3 = get_field(s->fields, m3);
+    bool is_imm;
+    DisasCompare c;
+
+    /* Bit 3 of the m3 field is reserved and should be zero.
+       Choose to ignore it wrt the ltgt_cond table above.  */
+    c.cond = ltgt_cond[m3 & 14];
+    if (s->insn->data) {
+        c.cond = tcg_unsigned_cond(c.cond);
+    }
+    c.is_64 = c.g1 = c.g2 = true;
+    c.u.s64.a = o->in1;
+    c.u.s64.b = o->in2;
+
+    is_imm = have_field(s->fields, i4);
+    if (is_imm) {
+        imm = get_field(s->fields, i4);
+    } else {
+        imm = 0;
+        o->out = get_address(s, 0, get_field(s->fields, b4),
+                             get_field(s->fields, d4));
+    }
+
+    return help_branch(s, &c, is_imm, imm, o->out);
+}
+
 static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
 {
     gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
commit 7a6c7067f034c5b887cda5e45ef660fe50ebbd1b
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 17:28:17 2012 -0700

    target-s390: Tidy s->op_cc handling
    
    There's no need to force computation of the true cc_op when taking an
    exception or single stepping.  In either case we'll enter the next TB
    with s->cc_op = DYNAMIC and recompute anyway.  Just make sure that
    s->cc_op is stored back to env->cc_op as needed.
    
    Delete some dead functions, avoid allocating unused TCG temps, drop
    the old s->is_jmp setting.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6553e48..c87d97f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -55,7 +55,6 @@ struct DisasContext {
     uint64_t pc, next_pc;
     enum cc_op cc_op;
     bool singlestep_enabled;
-    int is_jmp;
 };
 
 /* Information carried about a condition to be evaluated.  */
@@ -72,8 +71,6 @@ typedef struct {
 
 #define DISAS_EXCP 4
 
-static void gen_op_calc_cc(DisasContext *s);
-
 #ifdef DEBUG_INLINE_BRANCHES
 static uint64_t inline_branch_hit[CC_OP_MAX];
 static uint64_t inline_branch_miss[CC_OP_MAX];
@@ -246,12 +243,17 @@ static void update_psw_addr(DisasContext *s)
     tcg_gen_movi_i64(psw_addr, s->pc);
 }
 
+static void update_cc_op(DisasContext *s)
+{
+    if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
+        tcg_gen_movi_i32(cc_op, s->cc_op);
+    }
+}
+
 static void potential_page_fault(DisasContext *s)
 {
-#ifndef CONFIG_USER_ONLY
     update_psw_addr(s);
-    gen_op_calc_cc(s);
-#endif
+    update_cc_op(s);
 }
 
 static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
@@ -309,13 +311,10 @@ static void gen_program_exception(DisasContext *s, int code)
     update_psw_addr(s);
 
     /* Save off cc.  */
-    gen_op_calc_cc(s);
+    update_cc_op(s);
 
     /* Trigger exception.  */
     gen_exception(EXCP_PGM);
-
-    /* End TB here.  */
-    s->is_jmp = DISAS_EXCP;
 }
 
 static inline void gen_illegal_opcode(DisasContext *s)
@@ -428,23 +427,40 @@ static void set_cc_static(DisasContext *s)
     s->cc_op = CC_OP_STATIC;
 }
 
-static void gen_op_set_cc_op(DisasContext *s)
-{
-    if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
-        tcg_gen_movi_i32(cc_op, s->cc_op);
-    }
-}
-
-static void gen_update_cc_op(DisasContext *s)
-{
-    gen_op_set_cc_op(s);
-}
-
 /* calculates cc into cc_op */
 static void gen_op_calc_cc(DisasContext *s)
 {
-    TCGv_i32 local_cc_op = tcg_const_i32(s->cc_op);
-    TCGv_i64 dummy = tcg_const_i64(0);
+    TCGv_i32 local_cc_op;
+    TCGv_i64 dummy;
+
+    TCGV_UNUSED_I32(local_cc_op);
+    TCGV_UNUSED_I64(dummy);
+    switch (s->cc_op) {
+    default:
+        dummy = tcg_const_i64(0);
+        /* FALLTHRU */
+    case CC_OP_ADD_64:
+    case CC_OP_ADDU_64:
+    case CC_OP_ADDC_64:
+    case CC_OP_SUB_64:
+    case CC_OP_SUBU_64:
+    case CC_OP_SUBB_64:
+    case CC_OP_ADD_32:
+    case CC_OP_ADDU_32:
+    case CC_OP_ADDC_32:
+    case CC_OP_SUB_32:
+    case CC_OP_SUBU_32:
+    case CC_OP_SUBB_32:
+        local_cc_op = tcg_const_i32(s->cc_op);
+        break;
+    case CC_OP_CONST0:
+    case CC_OP_CONST1:
+    case CC_OP_CONST2:
+    case CC_OP_CONST3:
+    case CC_OP_STATIC:
+    case CC_OP_DYNAMIC:
+        break;
+    }
 
     switch (s->cc_op) {
     case CC_OP_CONST0:
@@ -508,8 +524,12 @@ static void gen_op_calc_cc(DisasContext *s)
         tcg_abort();
     }
 
-    tcg_temp_free_i32(local_cc_op);
-    tcg_temp_free_i64(dummy);
+    if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
+        tcg_temp_free_i32(local_cc_op);
+    }
+    if (!TCGV_IS_UNUSED_I64(dummy)) {
+        tcg_temp_free_i64(dummy);
+    }
 
     /* We now have cc in cc_op as constant */
     set_cc_static(s);
@@ -1054,7 +1074,7 @@ static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
         return NO_EXIT;
     }
     if (use_goto_tb(s, dest)) {
-        gen_update_cc_op(s);
+        update_cc_op(s);
         tcg_gen_goto_tb(0);
         tcg_gen_movi_i64(psw_addr, dest);
         tcg_gen_exit_tb((tcg_target_long)s->tb);
@@ -1103,7 +1123,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
     if (use_goto_tb(s, s->next_pc)) {
         if (is_imm && use_goto_tb(s, dest)) {
             /* Both exits can use goto_tb.  */
-            gen_update_cc_op(s);
+            update_cc_op(s);
 
             lab = gen_new_label();
             if (c->is_64) {
@@ -1141,7 +1161,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
             }
 
             /* Branch not taken.  */
-            gen_update_cc_op(s);
+            update_cc_op(s);
             tcg_gen_goto_tb(0);
             tcg_gen_movi_i64(psw_addr, s->next_pc);
             tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
@@ -1749,7 +1769,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
     TCGv_i64 tmp;
 
     update_psw_addr(s);
-    gen_op_calc_cc(s);
+    update_cc_op(s);
 
     tmp = tcg_const_i64(s->next_pc);
     gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
@@ -2913,7 +2933,7 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     TCGv_i32 t;
 
     update_psw_addr(s);
-    gen_op_calc_cc(s);
+    update_cc_op(s);
 
     t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
     tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
@@ -3999,7 +4019,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
     do_debug = dc.singlestep_enabled = env->singlestep_enabled;
-    dc.is_jmp = DISAS_NEXT;
 
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
@@ -4073,17 +4092,13 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         update_psw_addr(&dc);
         /* FALLTHRU */
     case EXIT_PC_UPDATED:
-        if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
-            gen_op_calc_cc(&dc);
-        } else {
-            /* Next TB starts off with CC_OP_DYNAMIC,
-               so make sure the cc op type is in env */
-            gen_op_set_cc_op(&dc);
-        }
+        /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
+           cc op type is in env */
+        update_cc_op(&dc);
+        /* Exit the TB, either by raising a debug exception or by return.  */
         if (do_debug) {
             gen_exception(EXCP_DEBUG);
         } else {
-            /* Generate the return instruction */
             tcg_gen_exit_tb(0);
         }
         break;
commit 2cf5e350c4f7ec08aab5d70193310c721b8179e9
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 29 12:57:55 2012 -0700

    target-s390: Implement BRANCH ON INDEX
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index cd773d0..8b89ce6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -90,6 +90,16 @@
 /* BRANCH RELATIVE ON COUNT */
     C(0xa706, BRCT,    RI_b,  Z,   0, 0, 0, 0, bct32, 0)
     C(0xa707, BRCTG,   RI_b,  Z,   0, 0, 0, 0, bct64, 0)
+/* BRANCH ON INDEX */
+    D(0x8600, BXH,     RS_a,  Z,   0, a2, 0, 0, bx32, 0, 0)
+    D(0x8700, BXLE,    RS_a,  Z,   0, a2, 0, 0, bx32, 0, 1)
+    D(0xeb44, BXHG,    RSY_a, Z,   0, a2, 0, 0, bx64, 0, 0)
+    D(0xeb45, BXLEG,   RSY_a, Z,   0, a2, 0, 0, bx64, 0, 1)
+/* BRANCH RELATIVE ON INDEX */
+    D(0x8400, BRXH,    RSI,   Z,   0, 0, 0, 0, bx32, 0, 0)
+    D(0x8500, BRXLE,   RSI,   Z,   0, 0, 0, 0, bx32, 0, 1)
+    D(0xec44, BRXHG,   RIE_e, Z,   0, 0, 0, 0, bx64, 0, 0)
+    D(0xec45, BRXHLE,  RIE_e, Z,   0, 0, 0, 0, bx64, 0, 1)
 
 /* CHECKSUM */
     C(0xb241, CKSM,    RRE,   Z,   r1_o, ra2, new, r1_32, cksm, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 3d92a56..6553e48 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1355,6 +1355,58 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_bx32(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    bool is_imm = have_field(s->fields, i2);
+    int imm = is_imm ? get_field(s->fields, i2) : 0;
+    DisasCompare c;
+    TCGv_i64 t;
+
+    c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+    c.is_64 = false;
+    c.g1 = false;
+    c.g2 = false;
+
+    t = tcg_temp_new_i64();
+    tcg_gen_add_i64(t, regs[r1], regs[r3]);
+    c.u.s32.a = tcg_temp_new_i32();
+    c.u.s32.b = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(c.u.s32.a, t);
+    tcg_gen_trunc_i64_i32(c.u.s32.b, regs[r3 | 1]);
+    store_reg32_i64(r1, t);
+    tcg_temp_free_i64(t);
+
+    return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
+static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    bool is_imm = have_field(s->fields, i2);
+    int imm = is_imm ? get_field(s->fields, i2) : 0;
+    DisasCompare c;
+
+    c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
+    c.is_64 = true;
+
+    if (r1 == (r3 | 1)) {
+        c.u.s64.b = load_reg(r3 | 1);
+        c.g2 = false;
+    } else {
+        c.u.s64.b = regs[r3 | 1];
+        c.g2 = true;
+    }
+
+    tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
+    c.u.s64.a = regs[r1];
+    c.g1 = true;
+
+    return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
 static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
 {
     gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
commit 4f3adfb2a63416c434fdafdfa406604f2a18392b
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 11:33:58 2012 -0700

    target-s390: Delete dead code from old translator
    
    The use of inline restricts detection of static functions that are
    no longer used.  Limit the use of inline to those functions that
    are conditionally used based on CONFIG_USER_ONLY.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b4b197b..3d92a56 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -79,12 +79,7 @@ static uint64_t inline_branch_hit[CC_OP_MAX];
 static uint64_t inline_branch_miss[CC_OP_MAX];
 #endif
 
-static inline void debug_insn(uint64_t insn)
-{
-    LOG_DISAS("insn: 0x%" PRIx64 "\n", insn);
-}
-
-static inline uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
+static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
 {
     if (!(s->tb->flags & FLAG_MASK_64)) {
         if (s->tb->flags & FLAG_MASK_32) {
@@ -200,112 +195,58 @@ void s390x_translate_init(void)
 #include "helper.h"
 }
 
-static inline TCGv_i64 load_reg(int reg)
+static TCGv_i64 load_reg(int reg)
 {
     TCGv_i64 r = tcg_temp_new_i64();
     tcg_gen_mov_i64(r, regs[reg]);
     return r;
 }
 
-static inline TCGv_i64 load_freg(int reg)
-{
-    TCGv_i64 r = tcg_temp_new_i64();
-    tcg_gen_mov_i64(r, fregs[reg]);
-    return r;
-}
-
-static inline TCGv_i32 load_freg32(int reg)
-{
-    TCGv_i32 r = tcg_temp_new_i32();
-#if HOST_LONG_BITS == 32
-    tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
-#else
-    tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
-#endif
-    return r;
-}
-
-static inline TCGv_i64 load_freg32_i64(int reg)
+static TCGv_i64 load_freg32_i64(int reg)
 {
     TCGv_i64 r = tcg_temp_new_i64();
     tcg_gen_shri_i64(r, fregs[reg], 32);
     return r;
 }
 
-static inline TCGv_i32 load_reg32(int reg)
-{
-    TCGv_i32 r = tcg_temp_new_i32();
-    tcg_gen_trunc_i64_i32(r, regs[reg]);
-    return r;
-}
-
-static inline TCGv_i64 load_reg32_i64(int reg)
-{
-    TCGv_i64 r = tcg_temp_new_i64();
-    tcg_gen_ext32s_i64(r, regs[reg]);
-    return r;
-}
-
-static inline void store_reg(int reg, TCGv_i64 v)
+static void store_reg(int reg, TCGv_i64 v)
 {
     tcg_gen_mov_i64(regs[reg], v);
 }
 
-static inline void store_freg(int reg, TCGv_i64 v)
+static void store_freg(int reg, TCGv_i64 v)
 {
     tcg_gen_mov_i64(fregs[reg], v);
 }
 
-static inline void store_reg32(int reg, TCGv_i32 v)
-{
-    /* 32 bit register writes keep the upper half */
-#if HOST_LONG_BITS == 32
-    tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
-#else
-    tcg_gen_deposit_i64(regs[reg], regs[reg],
-                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
-#endif
-}
-
-static inline void store_reg32_i64(int reg, TCGv_i64 v)
+static void store_reg32_i64(int reg, TCGv_i64 v)
 {
     /* 32 bit register writes keep the upper half */
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
 }
 
-static inline void store_reg32h_i64(int reg, TCGv_i64 v)
+static void store_reg32h_i64(int reg, TCGv_i64 v)
 {
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
 }
 
-static inline void store_freg32(int reg, TCGv_i32 v)
-{
-    /* 32 bit register writes keep the lower half */
-#if HOST_LONG_BITS == 32
-    tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
-#else
-    tcg_gen_deposit_i64(fregs[reg], fregs[reg],
-                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
-#endif
-}
-
-static inline void store_freg32_i64(int reg, TCGv_i64 v)
+static void store_freg32_i64(int reg, TCGv_i64 v)
 {
     tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
 }
 
-static inline void return_low128(TCGv_i64 dest)
+static void return_low128(TCGv_i64 dest)
 {
     tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
 }
 
-static inline void update_psw_addr(DisasContext *s)
+static void update_psw_addr(DisasContext *s)
 {
     /* psw.addr */
     tcg_gen_movi_i64(psw_addr, s->pc);
 }
 
-static inline void potential_page_fault(DisasContext *s)
+static void potential_page_fault(DisasContext *s)
 {
 #ifndef CONFIG_USER_ONLY
     update_psw_addr(s);
@@ -328,7 +269,7 @@ static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
     return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
 }
 
-static inline int get_mem_index(DisasContext *s)
+static int get_mem_index(DisasContext *s)
 {
     switch (s->tb->flags & FLAG_MASK_ASC) {
     case PSW_ASC_PRIMARY >> 32:
@@ -440,14 +381,6 @@ static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
     s->cc_op = op;
 }
 
-static void gen_op_update1_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 dst)
-{
-    tcg_gen_discard_i64(cc_src);
-    tcg_gen_extu_i32_i64(cc_dst, dst);
-    tcg_gen_discard_i64(cc_vr);
-    s->cc_op = op;
-}
-
 static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
                                   TCGv_i64 dst)
 {
@@ -457,15 +390,6 @@ static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
     s->cc_op = op;
 }
 
-static void gen_op_update2_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
-                                  TCGv_i32 dst)
-{
-    tcg_gen_extu_i32_i64(cc_src, src);
-    tcg_gen_extu_i32_i64(cc_dst, dst);
-    tcg_gen_discard_i64(cc_vr);
-    s->cc_op = op;
-}
-
 static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
                                   TCGv_i64 dst, TCGv_i64 vr)
 {
@@ -475,104 +399,28 @@ static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
     s->cc_op = op;
 }
 
-static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
-{
-    gen_op_update1_cc_i32(s, CC_OP_NZ, val);
-}
-
-static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
+static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
 {
     gen_op_update1_cc_i64(s, CC_OP_NZ, val);
 }
 
-static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
+static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
 {
     gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
 }
 
-static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
+static void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
 {
     gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
 }
 
-static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
+static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
 {
     gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
 }
 
-static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
-                          enum cc_op cond)
-{
-    gen_op_update2_cc_i32(s, cond, v1, v2);
-}
-
-static inline void cmp_64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
-                          enum cc_op cond)
-{
-    gen_op_update2_cc_i64(s, cond, v1, v2);
-}
-
-static inline void cmp_s32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
-    cmp_32(s, v1, v2, CC_OP_LTGT_32);
-}
-
-static inline void cmp_u32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
-    cmp_32(s, v1, v2, CC_OP_LTUGTU_32);
-}
-
-static inline void cmp_s32c(DisasContext *s, TCGv_i32 v1, int32_t v2)
-{
-    /* XXX optimize for the constant? put it in s? */
-    TCGv_i32 tmp = tcg_const_i32(v2);
-    cmp_32(s, v1, tmp, CC_OP_LTGT_32);
-    tcg_temp_free_i32(tmp);
-}
-
-static inline void cmp_u32c(DisasContext *s, TCGv_i32 v1, uint32_t v2)
-{
-    TCGv_i32 tmp = tcg_const_i32(v2);
-    cmp_32(s, v1, tmp, CC_OP_LTUGTU_32);
-    tcg_temp_free_i32(tmp);
-}
-
-static inline void cmp_s64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
-{
-    cmp_64(s, v1, v2, CC_OP_LTGT_64);
-}
-
-static inline void cmp_u64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2)
-{
-    cmp_64(s, v1, v2, CC_OP_LTUGTU_64);
-}
-
-static inline void cmp_s64c(DisasContext *s, TCGv_i64 v1, int64_t v2)
-{
-    TCGv_i64 tmp = tcg_const_i64(v2);
-    cmp_s64(s, v1, tmp);
-    tcg_temp_free_i64(tmp);
-}
-
-static inline void cmp_u64c(DisasContext *s, TCGv_i64 v1, uint64_t v2)
-{
-    TCGv_i64 tmp = tcg_const_i64(v2);
-    cmp_u64(s, v1, tmp);
-    tcg_temp_free_i64(tmp);
-}
-
-static inline void set_cc_s32(DisasContext *s, TCGv_i32 val)
-{
-    gen_op_update1_cc_i32(s, CC_OP_LTGT0_32, val);
-}
-
-static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
-{
-    gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
-}
-
 /* CC value is in env->cc_op */
-static inline void set_cc_static(DisasContext *s)
+static void set_cc_static(DisasContext *s)
 {
     tcg_gen_discard_i64(cc_src);
     tcg_gen_discard_i64(cc_dst);
@@ -580,14 +428,14 @@ static inline void set_cc_static(DisasContext *s)
     s->cc_op = CC_OP_STATIC;
 }
 
-static inline void gen_op_set_cc_op(DisasContext *s)
+static void gen_op_set_cc_op(DisasContext *s)
 {
     if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
         tcg_gen_movi_i32(cc_op, s->cc_op);
     }
 }
 
-static inline void gen_update_cc_op(DisasContext *s)
+static void gen_update_cc_op(DisasContext *s)
 {
     gen_op_set_cc_op(s);
 }
@@ -667,51 +515,6 @@ static void gen_op_calc_cc(DisasContext *s)
     set_cc_static(s);
 }
 
-static inline void decode_rr(DisasContext *s, uint64_t insn, int *r1, int *r2)
-{
-    debug_insn(insn);
-
-    *r1 = (insn >> 4) & 0xf;
-    *r2 = insn & 0xf;
-}
-
-static inline TCGv_i64 decode_rx(DisasContext *s, uint64_t insn, int *r1,
-                                 int *x2, int *b2, int *d2)
-{
-    debug_insn(insn);
-
-    *r1 = (insn >> 20) & 0xf;
-    *x2 = (insn >> 16) & 0xf;
-    *b2 = (insn >> 12) & 0xf;
-    *d2 = insn & 0xfff;
-
-    return get_address(s, *x2, *b2, *d2);
-}
-
-static inline void decode_rs(DisasContext *s, uint64_t insn, int *r1, int *r3,
-                             int *b2, int *d2)
-{
-    debug_insn(insn);
-
-    *r1 = (insn >> 20) & 0xf;
-    /* aka m3 */
-    *r3 = (insn >> 16) & 0xf;
-    *b2 = (insn >> 12) & 0xf;
-    *d2 = insn & 0xfff;
-}
-
-static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
-                                 int *b1, int *d1)
-{
-    debug_insn(insn);
-
-    *i2 = (insn >> 16) & 0xff;
-    *b1 = (insn >> 12) & 0xf;
-    *d1 = insn & 0xfff;
-
-    return get_address(s, 0, *b1, *d1);
-}
-
 static int use_goto_tb(DisasContext *s, uint64_t dest)
 {
     /* NOTE: we handle the case where the TB spans two pages here */
@@ -721,29 +524,14 @@ static int use_goto_tb(DisasContext *s, uint64_t dest)
             && !(s->tb->cflags & CF_LAST_IO));
 }
 
-static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
-{
-    gen_update_cc_op(s);
-
-    if (use_goto_tb(s, pc)) {
-        tcg_gen_goto_tb(tb_num);
-        tcg_gen_movi_i64(psw_addr, pc);
-        tcg_gen_exit_tb((tcg_target_long)s->tb + tb_num);
-    } else {
-        /* jump to another page: currently not optimized */
-        tcg_gen_movi_i64(psw_addr, pc);
-        tcg_gen_exit_tb(0);
-    }
-}
-
-static inline void account_noninline_branch(DisasContext *s, int cc_op)
+static void account_noninline_branch(DisasContext *s, int cc_op)
 {
 #ifdef DEBUG_INLINE_BRANCHES
     inline_branch_miss[cc_op]++;
 #endif
 }
 
-static inline void account_inline_branch(DisasContext *s, int cc_op)
+static void account_inline_branch(DisasContext *s, int cc_op)
 {
 #ifdef DEBUG_INLINE_BRANCHES
     inline_branch_hit[cc_op]++;
@@ -1018,43 +806,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
-                     uint32_t insn)
-{
-#ifndef CONFIG_USER_ONLY
-    switch (op) {
-    default:
-#endif
-        LOG_DISAS("illegal b2 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-#ifndef CONFIG_USER_ONLY
-        break;
-    }
-#endif
-}
-
-static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
-{
-    unsigned char opc;
-    uint64_t insn;
-    int op;
-
-    opc = cpu_ldub_code(env, s->pc);
-    LOG_DISAS("opc 0x%x\n", opc);
-
-    switch (opc) {
-    case 0xb2:
-        insn = ld_code4(env, s->pc);
-        op = (insn >> 16) & 0xff;
-        disas_b2(env, s, op, insn);
-        break;
-    default:
-        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
 /* ====================================================================== */
 /* Define the insn format enumeration.  */
 #define F0(N)                         FMT_##N,
@@ -4108,30 +3859,15 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
     DisasFields f;
     DisasOps o;
 
+    /* Search for the insn in the table.  */
     insn = extract_insn(env, s, &f);
 
-    /* If not found, try the old interpreter.  This includes ILLOPC.  */
+    /* Not found means unimplemented/illegal opcode.  */
     if (insn == NULL) {
-        disas_s390_insn(env, s);
-        switch (s->is_jmp) {
-        case DISAS_NEXT:
-            ret = NO_EXIT;
-            break;
-        case DISAS_TB_JUMP:
-            ret = EXIT_GOTO_TB;
-            break;
-        case DISAS_JUMP:
-            ret = EXIT_PC_UPDATED;
-            break;
-        case DISAS_EXCP:
-            ret = EXIT_NORETURN;
-            break;
-        default:
-            abort();
-        }
-
-        s->pc = s->next_pc;
-        return ret;
+        qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
+                      f.op, f.op2);
+        gen_illegal_opcode(s);
+        return EXIT_NORETURN;
     }
 
     /* Set up the strutures we use to communicate with the helpers. */
commit dc458df91d00986885fe12ed25876aa6d0604cee
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 11:12:40 2012 -0700

    target-s390: Convert SERVC
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index f2eaef4..5d8a821 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -80,7 +80,7 @@ DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
 
 #ifndef CONFIG_USER_ONLY
-DEF_HELPER_3(servc, i32, env, i32, i64)
+DEF_HELPER_3(servc, i32, env, i64, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b0cf908..cd773d0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -641,6 +641,8 @@
     C(0xb20d, PTLB,    S,     Z,   0, 0, 0, 0, ptlb, 0)
 /* RESET REFERENCE BIT EXTENDED */
     C(0xb22a, RRBE,    RRE,   Z,   0, r2_o, 0, 0, rrbe, 0)
+/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
+    C(0xb220, SERVC,   RRE,   Z,   r1_o, r2_o, 0, 0, servc, 0)
 /* SET ADDRESSING MODE */
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 60e6538..3015bfe 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -88,11 +88,9 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
 }
 
 /* SCLP service call */
-uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
 {
-    int r;
-
-    r = sclp_service_call(r1, r2);
+    int r = sclp_service_call(r1, r2);
     if (r < 0) {
         program_interrupt(env, -r, 4);
         return 0;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5472dfc..b4b197b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1022,27 +1022,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
                      uint32_t insn)
 {
 #ifndef CONFIG_USER_ONLY
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1;
-    int r1, r2;
-
-    r1 = (insn >> 4) & 0xf;
-    r2 = insn & 0xf;
-
-    LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
-
     switch (op) {
-    case 0x20: /* SERVC     R1,R2     [RRE] */
-        /* SCLP Service call (PV hypercall) */
-        check_privileged(s);
-        potential_page_fault(s);
-        tmp32_1 = load_reg32(r2);
-        tmp = load_reg(r1);
-        gen_helper_servc(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
 #endif
         LOG_DISAS("illegal b2 operation 0x%x\n", op);
@@ -2701,6 +2681,15 @@ static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
 }
 
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_servc(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit 7ab938d706b515cfe4680a823525693124e2047d
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 11:04:48 2012 -0700

    target-s390: Convert LPSWE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba070f1..b0cf908 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -627,6 +627,8 @@
     C(0xeb2f, LCTLG,   RSY_a, Z,   0, a2, 0, 0, lctlg, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
+/* LOAD PSW EXTENDED */
+    C(0xb2b2, LPSWE,   S,     Z,   0, a2, 0, 0, lpswe, 0)
 /* LOAD REAL ADDRESS */
     C(0xb100, LRA,     RX_a,  Z,   0, a2, r1, 0, lra, 0)
     C(0xe313, LRAY,    RXY_a, LD,  0, a2, r1, 0, lra, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b5cc573..5472dfc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1022,10 +1022,9 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
                      uint32_t insn)
 {
 #ifndef CONFIG_USER_ONLY
-    TCGv_i64 tmp, tmp2, tmp3;
+    TCGv_i64 tmp;
     TCGv_i32 tmp32_1;
     int r1, r2;
-    int r3, d2, b2;
 
     r1 = (insn >> 4) & 0xf;
     r2 = insn & 0xf;
@@ -1033,23 +1032,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0xb2: /* LPSWE    D2(B2)     [S] */
-        /* Load PSW Extended */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
-        tcg_gen_addi_i64(tmp, tmp, 8);
-        tcg_gen_qemu_ld64(tmp3, tmp, get_mem_index(s));
-        gen_helper_load_psw(cpu_env, tmp2, tmp3);
-        /* we need to keep cc_op intact */
-        s->is_jmp = DISAS_JUMP;
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x20: /* SERVC     R1,R2     [RRE] */
         /* SCLP Service call (PV hypercall) */
         check_privileged(s);
@@ -2254,6 +2236,23 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
     tcg_temp_free_i64(t2);
     return EXIT_NORETURN;
 }
+
+static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t1, t2;
+
+    check_privileged(s);
+
+    t1 = tcg_temp_new_i64();
+    t2 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
+    tcg_gen_addi_i64(o->in2, o->in2, 8);
+    tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
+    gen_helper_load_psw(cpu_env, t1, t2);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    return EXIT_NORETURN;
+}
 #endif
 
 static ExitStatus op_lam(DisasContext *s, DisasOps *o)
commit fc778b55a5ae45abac2a94d591e7490622917872
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 10:58:59 2012 -0700

    target-s390: Convert STFL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5de3256..ba070f1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -678,6 +678,8 @@
     C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
 /* STORE CPU TIMER */
     C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
+/* STORE FACILITY LIST */
+    C(0xb2b1, STFL,    S,     Z,   0, 0, 0, 0, stfl, 0)
 /* STORE PREFIX */
     C(0xb211, STPX,    S,     Z,   la2, 0, new, m1_32, stpx, 0)
 /* STORE SYSTEM INFORMATION */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6f1f799..b5cc573 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0xb1: /* STFL     D2(B2)     [S] */
-        /* Store Facility List (CPU features) at 200 */
-        check_privileged(s);
-        tmp2 = tcg_const_i64(0xc0000000);
-        tmp = tcg_const_i64(200);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0xb2: /* LPSWE    D2(B2)     [S] */
         /* Load PSW Extended */
         check_privileged(s);
@@ -2875,6 +2866,20 @@ static ExitStatus op_spt(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 f, a;
+    /* We really ought to have more complete indication of facilities
+       that we implement.  Address this when STFLE is implemented.  */
+    check_privileged(s);
+    f = tcg_const_i64(0xc0000000);
+    a = tcg_const_i64(200);
+    tcg_gen_qemu_st32(f, a, get_mem_index(s));
+    tcg_temp_free_i64(f);
+    tcg_temp_free_i64(a);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit d14b3e09b21a297fddc62c0c7839156022079d05
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 10:43:38 2012 -0700

    target-s390: Convert STSI
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 3d7472e..f2eaef4 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -89,7 +89,7 @@ DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
-DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
+DEF_HELPER_4(stsi, i32, env, i64, i64, i64)
 DEF_HELPER_4(lctl, void, env, i32, i64, i32)
 DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
 DEF_HELPER_4(stctl, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a389f15..5de3256 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -680,6 +680,8 @@
     C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
 /* STORE PREFIX */
     C(0xb211, STPX,    S,     Z,   la2, 0, new, m1_32, stpx, 0)
+/* STORE SYSTEM INFORMATION */
+    C(0xb27d, STSI,    S,     Z,   0, a2, 0, 0, stsi, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 409df4f..60e6538 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -200,8 +200,8 @@ uint64_t HELPER(stpt)(CPUS390XState *env)
 }
 
 /* Store System Information */
-uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint32_t r0,
-                      uint32_t r1)
+uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
+                      uint64_t r0, uint64_t r1)
 {
     int cc = 0;
     int sel1, sel2;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 491f8fd..6f1f799 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1023,7 +1023,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
 {
 #ifndef CONFIG_USER_ONLY
     TCGv_i64 tmp, tmp2, tmp3;
-    TCGv_i32 tmp32_1, tmp32_2;
+    TCGv_i32 tmp32_1;
     int r1, r2;
     int r3, d2, b2;
 
@@ -1033,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x7d: /* STSI     D2,(B2)     [S] */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = load_reg32(1);
-        potential_page_fault(s);
-        gen_helper_stsi(cc_op, cpu_env, tmp, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xb1: /* STFL     D2(B2)     [S] */
         /* Store Facility List (CPU features) at 200 */
         check_privileged(s);
@@ -2895,6 +2882,15 @@ static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_spx(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit 14244b21a041161185bb53c3eb29e3d8dc7bfe6e
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 10:17:16 2012 -0700

    target-s390: Convert SACF
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 75729fe..a389f15 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -643,6 +643,8 @@
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
     C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
+/* SET ADDRESS SPACE CONTROL FAST */
+    C(0xb279, SACF,    S,     Z,   0, a2, 0, 0, sacf, 0)
 /* SET CLOCK */
     /* ??? Not implemented - is it necessary? */
     C(0xb204, SCK,     S,     Z,   0, 0, 0, 0, 0, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e5c3ee6..491f8fd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x79: /* SACF    D2(B2)     [S] */
-        /* Set Address Space Control Fast */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sacf(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        /* addressing mode has changed, so end the block */
-        s->pc = s->next_pc;
-        update_psw_addr(s);
-        s->is_jmp = DISAS_JUMP;
-        break;
     case 0x7d: /* STSI     D2,(B2)     [S] */
         check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2681,6 +2668,14 @@ static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
     set_cc_static(s);
     return NO_EXIT;
 }
+
+static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_sacf(cpu_env, o->in2);
+    /* Addressing mode has changed, so end the block.  */
+    return EXIT_PC_STALE;
+}
 #endif
 
 static ExitStatus op_sar(DisasContext *s, DisasOps *o)
commit 39a5003c89191a46ec6af722ade3dfdf457e9f58
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 10:11:36 2012 -0700

    target-s390: Convert STCKE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c359377..3d7472e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -85,7 +85,6 @@ DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
-DEF_HELPER_2(stcke, i32, env, i64)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 12468a3..75729fe 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -663,6 +663,8 @@
 /* STORE CLOCK */
     C(0xb205, STCK,    S,     Z,   la2, 0, new, m1_64, stck, 0)
     C(0xb27c, STCKF,   S,     Z,   la2, 0, new, m1_64, stck, 0)
+/* STORE CLOCK EXTENDED */
+    C(0xb278, STCKE,   S,     Z,   0, a2, 0, 0, stcke, 0)
 /* STORE CLOCK COMPARATOR */
     C(0xb207, STCKC,   S,     Z,   la2, 0, new, m1_64, stckc, 0)
 /* STORE CONTROL */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index b098e88..409df4f 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -157,20 +157,6 @@ uint64_t HELPER(stck)(CPUS390XState *env)
     return clock_value(env);
 }
 
-/* Store Clock Extended */
-uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
-{
-    cpu_stb_data(env, a1, 0);
-    /* basically the same value as stck */
-    cpu_stq_data(env, a1 + 1, clock_value(env) | env->cpu_num);
-    /* more fine grained than stck */
-    cpu_stq_data(env, a1 + 9, 0);
-    /* XXX programmable fields */
-    cpu_stw_data(env, a1 + 17, 0);
-
-    return 0;
-}
-
 /* Set Clock Comparator */
 void HELPER(sckc)(CPUS390XState *env, uint64_t time)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 19781ed..e5c3ee6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x78: /* STCKE    D2(B2)     [S] */
-        /* Store Clock Extended */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stcke(cc_op, cpu_env, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x79: /* SACF    D2(B2)     [S] */
         /* Set Address Space Control Fast */
         check_privileged(s);
@@ -2828,6 +2819,28 @@ static ExitStatus op_stck(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 c1 = tcg_temp_new_i64();
+    TCGv_i64 c2 = tcg_temp_new_i64();
+    gen_helper_stck(c1, cpu_env);
+    /* Shift the 64-bit value into its place as a zero-extended
+       104-bit value.  Note that "bit positions 64-103 are always
+       non-zero so that they compare differently to STCK"; we set
+       the least significant bit to 1.  */
+    tcg_gen_shli_i64(c2, c1, 56);
+    tcg_gen_shri_i64(c1, c1, 8);
+    tcg_gen_ori_i64(c2, c2, 0x10000);
+    tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
+    tcg_gen_addi_i64(o->in2, o->in2, 8);
+    tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
+    tcg_temp_free_i64(c1);
+    tcg_temp_free_i64(c2);
+    /* ??? We don't implement clock states.  */
+    gen_op_movi_cc(s, 0);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit 3d596f491250d66fffabbc60d0621ea72859e96c
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:57:18 2012 -0700

    target-s390: Convert CSP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 4597b58..c359377 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -99,7 +99,7 @@ DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64)
 DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64)
-DEF_HELPER_3(csp, i32, env, i32, i32)
+DEF_HELPER_3(csp, i32, env, i32, i64)
 DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
 DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
 DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8e457cb..12468a3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -614,6 +614,8 @@
     C(0xf300, UNPK,    SS_a,  Z,   la1, a2, 0, 0, unpk, 0)
 
 #ifndef CONFIG_USER_ONLY
+/* COMPARE AND SWAP AND PURGE */
+    C(0xb250, CSP,     RRE,   Z,   0, ra2, 0, 0, csp, 0)
 /* DIAGNOSE (KVM hypercall) */
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
 /* INSERT STORAGE KEY EXTENDED */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 8987bbb..0e9bbd4 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -984,16 +984,16 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
 }
 
 /* compare and swap and purge */
-uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint32_t HELPER(csp)(CPUS390XState *env, uint32_t r1, uint64_t r2)
 {
     uint32_t cc;
     uint32_t o1 = env->regs[r1];
-    uint64_t a2 = get_address_31fix(env, r2) & ~3ULL;
+    uint64_t a2 = r2 & ~3ULL;
     uint32_t o2 = cpu_ldl_data(env, a2);
 
     if (o1 == o2) {
         cpu_stl_data(env, a2, env->regs[(r1 + 1) & 15]);
-        if (env->regs[r2] & 0x3) {
+        if (r2 & 0x3) {
             /* flush TLB / ALB */
             tlb_flush(env, 1);
         }
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8079c6f..19781ed 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x50: /* CSP      R1,R2      [RRE] */
-        /* Compare And Swap And Purge */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        gen_helper_csp(cc_op, cpu_env, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x78: /* STCKE    D2(B2)     [S] */
         /* Store Clock Extended */
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -1901,6 +1889,18 @@ static ExitStatus op_csg(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_csp(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    check_privileged(s);
+    gen_helper_csp(cc_op, cpu_env, r1, o->in2);
+    tcg_temp_free_i32(r1);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_cds(DisasContext *s, DisasOps *o)
 {
     int r3 = get_field(s->fields, r3);
commit 204504e2fa0ec0f11c806ad335edf6bd1f499e34
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:45:38 2012 -0700

    target-s390: Convert STURA
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 9bcf4d6..4597b58 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -107,7 +107,7 @@ DEF_HELPER_2(sacf, void, env, i64)
 DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_2(lra, i64, env, i64)
-DEF_HELPER_3(stura, void, env, i64, i32)
+DEF_HELPER_3(stura, void, env, i64, i64)
 #endif
 
 #include "exec/def-helper.h"
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 24a419c..8e457cb 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -678,6 +678,8 @@
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
     C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
+/* STORE USING REAL ADDRESS */
+    C(0xb246, STURA,   RRE,   Z,   r1_o, r2_o, 0, 0, stura, 0)
 /* TEST PROTECTION */
     C(0xe501, TPROT,   SSE,   Z,   la1, a2, 0, 0, tprot, 0)
 
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 406ec9b..8987bbb 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -1093,9 +1093,9 @@ void HELPER(ptlb)(CPUS390XState *env)
 }
 
 /* store using real address */
-void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
+void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint64_t v1)
 {
-    stw_phys(get_address(env, 0, 0, addr), v1);
+    stw_phys(get_address(env, 0, 0, addr), (uint32_t)v1);
 }
 
 /* load real address */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1172031..8079c6f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x46: /* STURA    R1,R2      [RRE] */
-        /* Store Using Real Address */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        potential_page_fault(s);
-        gen_helper_stura(cpu_env, tmp, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x50: /* CSP      R1,R2      [RRE] */
         /* Compare And Swap And Purge */
         check_privileged(s);
@@ -2945,6 +2933,14 @@ static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
     }
     return NO_EXIT;
 }
+
+static ExitStatus op_stura(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stura(cpu_env, o->in2, o->in1);
+    return NO_EXIT;
+}
 #endif
 
 static ExitStatus op_st8(DisasContext *s, DisasOps *o)
commit 2c423fc070b3e260fc368e2573c76d7ddd52e165
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:36:20 2012 -0700

    target-s390: Convert subchannel instructions
    
    While we're at it, list all of the chapter 14 subchannel insns.
    Which is easy since all merely need indicate non-operation.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2a04572..24a419c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -680,4 +680,18 @@
     C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* TEST PROTECTION */
     C(0xe501, TPROT,   SSE,   Z,   la1, a2, 0, 0, tprot, 0)
+
+/* I/O Instructions.  For each we simply indicate non-operation.  */
+    C(0xb276, XSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb230, CSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb231, HSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb232, MSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb23b, RCHP,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb238, RSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb233, SSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb234, STSCH,   S,     Z,   0, 0, 0, 0, subchannel, 0)
+    C(0xb235, TSCH,    S,     Z,   0, 0, 0, 0, subchannel, 0)
+    /* ??? Not listed in PoO ninth edition, but there's a linux driver that
+       uses it: "A CHSC subchannel is usually present on LPAR only."  */
+    C(0xb25f, CHSC,    S,     Z,   0, 0, 0, 0, subchannel, 0)
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d7d991c..1172031 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,11 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x34: /* STCH ? */
-        /* Store Subchannel */
-        check_privileged(s);
-        gen_op_movi_cc(s, 3);
-        break;
     case 0x46: /* STURA    R1,R2      [RRE] */
         /* Store Using Real Address */
         check_privileged(s);
@@ -1062,11 +1057,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x5f: /* CHSC ? */
-        /* Channel Subsystem Call */
-        check_privileged(s);
-        gen_op_movi_cc(s, 3);
-        break;
     case 0x78: /* STCKE    D2(B2)     [S] */
         /* Store Clock Extended */
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2916,6 +2906,14 @@ static ExitStatus op_spx(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_subchannel(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    /* Not operational.  */
+    gen_op_movi_cc(s, 3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit 5cc69c54f606005ea0432d83dafbec0f5b0e831a
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:22:13 2012 -0700

    target-s390: Convert RRBE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 9ff0c36..9bcf4d6 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -98,7 +98,7 @@ DEF_HELPER_4(stctg, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64)
 DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
-DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_NO_RWG, i32, env, i32, i64)
+DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64)
 DEF_HELPER_3(csp, i32, env, i32, i32)
 DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
 DEF_HELPER_4(mvcp, i32, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f554c1b..2a04572 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -635,6 +635,8 @@
     C(0xdb00, MVCS,    SS_d,  Z,   la1, a2, 0, 0, mvcs, 0)
 /* PURGE TLB */
     C(0xb20d, PTLB,    S,     Z,   0, 0, 0, 0, ptlb, 0)
+/* RESET REFERENCE BIT EXTENDED */
+    C(0xb22a, RRBE,    RRE,   Z,   0, r2_o, 0, 0, rrbe, 0)
 /* SET ADDRESSING MODE */
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 0997241..406ec9b 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -958,7 +958,7 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
 }
 
 /* reset reference bit extended */
-uint32_t HELPER(rrbe)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
 {
     uint8_t re;
     uint8_t key;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2b07a8e..d7d991c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x2a: /* RRBE     R1,R2      [RRE] */
-        /* Set Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        gen_helper_rrbe(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x34: /* STCH ? */
         /* Store Subchannel */
         check_privileged(s);
@@ -2716,6 +2704,16 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_rrbe(cc_op, cpu_env, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_sar(DisasContext *s, DisasOps *o)
 {
     int r1 = get_field(s->fields, r1);
commit 2bbde27f2548cb48f362eada1080e590f5453404
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:18:01 2012 -0700

    target-s390: Convert SSKE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index d7736e3..9ff0c36 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -97,7 +97,7 @@ DEF_HELPER_4(stctl, void, env, i32, i64, i32)
 DEF_HELPER_4(stctg, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64)
 DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64)
-DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_NO_RWG, i32, env, i32, i64)
 DEF_HELPER_3(csp, i32, env, i32, i32)
 DEF_HELPER_4(mvcs, i32, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 87daec1..f554c1b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -650,6 +650,8 @@
     C(0xb210, SPX,     S,     Z,   0, m2_32u, 0, 0, spx, 0)
 /* SET PSW KEY FROM ADDRESS */
     C(0xb20a, SPKA,    S,     Z,   0, a2, 0, 0, spka, 0)
+/* SET STORAGE KEY EXTENDED */
+    C(0xb22b, SSKE,    RRF_c, Z,   r1_o, r2_o, 0, 0, sske, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 59877ee..0997241 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -946,7 +946,7 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2)
 }
 
 /* set storage key extended */
-void HELPER(sske)(CPUS390XState *env, uint32_t r1, uint64_t r2)
+void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2)
 {
     uint64_t addr = get_address(env, 0, 0, r2);
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b9647d8..2b07a8e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1045,17 +1045,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-    case 0x2b: /* SSKE     R1,R2      [RRE] */
-        /* Set Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp32_1 = load_reg32(r1);
-        tmp = load_reg(r2);
-        gen_helper_sske(cpu_env, tmp32_1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x34: /* STCH ? */
         /* Store Subchannel */
         check_privileged(s);
@@ -2831,6 +2820,13 @@ static ExitStatus op_spka(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sske(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_sske(cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit 8026417c7169e7efd1696f3ed15e51306729176a
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 09:13:38 2012 -0700

    target-s390: Convert ISKE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c8368cf..87daec1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -616,6 +616,8 @@
 #ifndef CONFIG_USER_ONLY
 /* DIAGNOSE (KVM hypercall) */
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
+/* INSERT STORAGE KEY EXTENDED */
+    C(0xb229, ISKE,    RRE,   Z,   0, r2_o, new, r1_8, iske, 0)
 /* INVALIDATE PAGE TABLE ENTRY */
     C(0xb221, IPTE,    RRF_a, Z,   r1_o, r2_o, 0, 0, ipte, 0)
 /* LOAD CONTROL */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b25a5e6..b9647d8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x29: /* ISKE     R1,R2      [RRE] */
-        /* Insert Storage Key Extended */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp = load_reg(r2);
-        tmp2 = tcg_temp_new_i64();
-        gen_helper_iske(tmp2, cpu_env, tmp);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x2a: /* RRBE     R1,R2      [RRE] */
         /* Set Storage Key Extended */
         check_privileged(s);
@@ -2209,6 +2197,13 @@ static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
     gen_helper_ipte(cpu_env, o->in1, o->in2);
     return NO_EXIT;
 }
+
+static ExitStatus op_iske(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_iske(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
 #endif
 
 static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
commit cfef53e356119bddcba0724c0c26fd5940f231e3
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 16:25:28 2012 -0700

    target-s390: Convert IPTE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f68e586..c8368cf 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -616,6 +616,8 @@
 #ifndef CONFIG_USER_ONLY
 /* DIAGNOSE (KVM hypercall) */
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
+/* INVALIDATE PAGE TABLE ENTRY */
+    C(0xb221, IPTE,    RRF_a, Z,   r1_o, r2_o, 0, 0, ipte, 0)
 /* LOAD CONTROL */
     C(0xb700, LCTL,    RS_a,  Z,   0, a2, 0, 0, lctl, 0)
     C(0xeb2f, LCTLG,   RSY_a, Z,   0, a2, 0, 0, lctlg, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5ffbdb3..b25a5e6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,17 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x21: /* IPTE     R1,R2      [RRE] */
-        /* Invalidate PTE */
-        check_privileged(s);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        gen_helper_ipte(cpu_env, tmp, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x29: /* ISKE     R1,R2      [RRE] */
         /* Insert Storage Key Extended */
         check_privileged(s);
@@ -2213,6 +2202,15 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_ipte(cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
 {
     gen_helper_ldeb(o->out, cpu_env, o->in2);
commit 411fea3d8400af5479690d6e22c6492c15e10a4a
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 16:18:33 2012 -0700

    target-s390: Convert STAP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 87a77a2..f68e586 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -658,6 +658,8 @@
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
+/* STORE CPU ADDRESS */
+    C(0xb212, STAP,    S,     Z,   la2, 0, new, m1_16, stap, 0)
 /* STORE CPU ID */
     C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
 /* STORE CPU TIMER */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e355de2..5ffbdb3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,20 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x12: /* STAP     D2(B2)     [S] */
-        /* Store CPU Address */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, cpu_num));
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x21: /* IPTE     R1,R2      [RRE] */
         /* Invalidate PTE */
         check_privileged(s);
@@ -2859,6 +2845,16 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stap(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    /* ??? Surely cpu address != cpu number.  In any case the previous
+       version of this stored more than the required half-word, so it
+       is unlikely this has ever been tested.  */
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+    return NO_EXIT;
+}
+
 static ExitStatus op_stck(DisasContext *s, DisasOps *o)
 {
     gen_helper_stck(o->out, cpu_env);
commit e805a0d39e26fc85681db7e1bf58c91a5628eaff
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 16:11:32 2012 -0700

    target-s390: Convert SPX, STPX
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e9b9dc1..87a77a2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -642,6 +642,8 @@
     C(0xb206, SCKC,    S,     Z,   0, m2_64, 0, 0, sckc, 0)
 /* SET CPU TIMER */
     C(0xb208, SPT,     S,     Z,   0, m2_64, 0, 0, spt, 0)
+/* SET PREFIX */
+    C(0xb210, SPX,     S,     Z,   0, m2_32u, 0, 0, spx, 0)
 /* SET PSW KEY FROM ADDRESS */
     C(0xb20a, SPKA,    S,     Z,   0, a2, 0, 0, spka, 0)
 /* SET SYSTEM MASK */
@@ -660,6 +662,8 @@
     C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
 /* STORE CPU TIMER */
     C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
+/* STORE PREFIX */
+    C(0xb211, STPX,    S,     Z,   la2, 0, new, m1_32, stpx, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 4318242..b098e88 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -134,10 +134,8 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
 /* Set Prefix */
 void HELPER(spx)(CPUS390XState *env, uint64_t a1)
 {
-    uint32_t prefix;
-
-    prefix = cpu_ldl_data(env, a1);
-    env->psa = prefix & 0xfffff000;
+    uint32_t prefix = a1 & 0x7fffe000;
+    env->psa = prefix;
     qemu_log("prefix: %#x\n", prefix);
     tlb_flush_page(env, 0);
     tlb_flush_page(env, TARGET_PAGE_SIZE);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 563c2e7..e355de2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,26 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x10: /* SPX      D2(B2)     [S] */
-        /* Set Prefix Register */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_spx(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x11: /* STPX     D2(B2)     [S] */
-        /* Store Prefix */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_ld_i64(tmp2, cpu_env, offsetof(CPUS390XState, psa));
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x12: /* STAP     D2(B2)     [S] */
         /* Store CPU Address */
         check_privileged(s);
@@ -2946,6 +2926,21 @@ static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_spx(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_spx(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
+    tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
 {
     uint64_t i2 = get_field(s->fields, i2);
commit 0568d8aab0b48cb033aad8ecaef5bc0c531ce9ff
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:59:26 2012 -0700

    target-s390: Convert PTLB
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f95ba11..e9b9dc1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -629,6 +629,8 @@
     C(0xda00, MVCP,    SS_d,  Z,   la1, a2, 0, 0, mvcp, 0)
 /* MOVE TO SECONDARY */
     C(0xdb00, MVCS,    SS_d,  Z,   la1, a2, 0, 0, mvcs, 0)
+/* PURGE TLB */
+    C(0xb20d, PTLB,    S,     Z,   0, 0, 0, 0, ptlb, 0)
 /* SET ADDRESSING MODE */
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6296113..563c2e7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,11 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x0d: /* PTLB                [S] */
-        /* Purge TLB */
-        check_privileged(s);
-        gen_helper_ptlb(cpu_env);
-        break;
     case 0x10: /* SPX      D2(B2)     [S] */
         /* Set Prefix Register */
         check_privileged(s);
@@ -2725,6 +2720,15 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_ptlb(cpu_env);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
 {
     tcg_gen_bswap16_i64(o->out, o->in2);
commit 28d555566719dada8e2d028ff611b4fb8a984e0c
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:55:34 2012 -0700

    target-s390: Convert SPKA
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a45454c..f95ba11 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,8 @@
     C(0xb206, SCKC,    S,     Z,   0, m2_64, 0, 0, sckc, 0)
 /* SET CPU TIMER */
     C(0xb208, SPT,     S,     Z,   0, m2_64, 0, 0, spt, 0)
+/* SET PSW KEY FROM ADDRESS */
+    C(0xb20a, SPKA,    S,     Z,   0, a2, 0, 0, spka, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a318492..6296113 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,18 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x0a: /* SPKA     D2(B2)     [S] */
-        /* Set PSW Key from Address */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_andi_i64(tmp2, psw_mask, ~PSW_MASK_KEY);
-        tcg_gen_shli_i64(tmp, tmp, PSW_SHIFT_KEY - 4);
-        tcg_gen_or_i64(psw_mask, tmp2, tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x0d: /* PTLB                [S] */
         /* Purge TLB */
         check_privileged(s);
@@ -2872,6 +2860,14 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
 }
 
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_spka(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_shri_i64(o->in2, o->in2, 4);
+    tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
commit c4f0a863c3b980694e2ccb8fa3252a0eb8ef6a97
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:47:26 2012 -0700

    target-s390: Convert SPT, STPT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index a55aa9f..d7736e3 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -89,7 +89,7 @@ DEF_HELPER_2(stcke, i32, env, i64)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_2(stpt, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(stpt, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
 DEF_HELPER_4(lctl, void, env, i32, i64, i32)
 DEF_HELPER_4(lctlg, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 06c780b..a45454c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -638,6 +638,8 @@
     C(0xb204, SCK,     S,     Z,   0, 0, 0, 0, 0, 0)
 /* SET CLOCK COMPARATOR */
     C(0xb206, SCKC,    S,     Z,   0, m2_64, 0, 0, sckc, 0)
+/* SET CPU TIMER */
+    C(0xb208, SPT,     S,     Z,   0, m2_64, 0, 0, spt, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
@@ -652,6 +654,8 @@
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
 /* STORE CPU ID */
     C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
+/* STORE CPU TIMER */
+    C(0xb209, STPT,    S,     Z,   la2, 0, new, m1_64, stpt, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 9263ae7..4318242 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -196,10 +196,8 @@ uint64_t HELPER(stckc)(CPUS390XState *env)
 }
 
 /* Set CPU Timer */
-void HELPER(spt)(CPUS390XState *env, uint64_t a1)
+void HELPER(spt)(CPUS390XState *env, uint64_t time)
 {
-    uint64_t time = cpu_ldq_data(env, a1);
-
     if (time == -1ULL) {
         return;
     }
@@ -211,10 +209,10 @@ void HELPER(spt)(CPUS390XState *env, uint64_t a1)
 }
 
 /* Store CPU Timer */
-void HELPER(stpt)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stpt)(CPUS390XState *env)
 {
     /* XXX implement */
-    cpu_stq_data(env, a1, 0);
+    return 0;
 }
 
 /* Store System Information */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 30c7ace..a318492 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,24 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x08: /* SPT      D2(B2)     [S] */
-        /* Set CPU Timer */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_spt(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x09: /* STPT     D2(B2)     [S] */
-        /* Store CPU Timer */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stpt(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x0a: /* SPKA     D2(B2)     [S] */
         /* Set PSW Key from Address */
         check_privileged(s);
@@ -2950,6 +2932,20 @@ static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_spt(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_spt(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_stpt(o->out, cpu_env);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
 {
     uint64_t i2 = get_field(s->fields, i2);
commit dd3eb7b54f0dbcf76e3ccfdf8535201049670378
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:36:58 2012 -0700

    target-s390: Convert SCKC, STCKC
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index d3a30cb..a55aa9f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -87,7 +87,7 @@ DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
 DEF_HELPER_2(stcke, i32, env, i64)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_2(stckc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(stckc, TCG_CALL_NO_RWG, i64, env)
 DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(stpt, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_4(stsi, i32, env, i64, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4404791..06c780b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -636,6 +636,8 @@
 /* SET CLOCK */
     /* ??? Not implemented - is it necessary? */
     C(0xb204, SCK,     S,     Z,   0, 0, 0, 0, 0, 0)
+/* SET CLOCK COMPARATOR */
+    C(0xb206, SCKC,    S,     Z,   0, m2_64, 0, 0, sckc, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
@@ -643,6 +645,8 @@
 /* STORE CLOCK */
     C(0xb205, STCK,    S,     Z,   la2, 0, new, m1_64, stck, 0)
     C(0xb27c, STCKF,   S,     Z,   la2, 0, new, m1_64, stck, 0)
+/* STORE CLOCK COMPARATOR */
+    C(0xb207, STCKC,   S,     Z,   la2, 0, new, m1_64, stckc, 0)
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index f1edf6c..9263ae7 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -174,10 +174,8 @@ uint32_t HELPER(stcke)(CPUS390XState *env, uint64_t a1)
 }
 
 /* Set Clock Comparator */
-void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
+void HELPER(sckc)(CPUS390XState *env, uint64_t time)
 {
-    uint64_t time = cpu_ldq_data(env, a1);
-
     if (time == -1ULL) {
         return;
     }
@@ -191,10 +189,10 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t a1)
 }
 
 /* Store Clock Comparator */
-void HELPER(stckc)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stckc)(CPUS390XState *env)
 {
     /* XXX implement */
-    cpu_stq_data(env, a1, 0);
+    return 0;
 }
 
 /* Set CPU Timer */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 624ee8d..30c7ace 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,24 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x06: /* SCKC     D2(B2)     [S] */
-        /* Set Clock Comparator */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sckc(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x07: /* STCKC    D2(B2)     [S] */
-        /* Store Clock Comparator */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stckc(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x08: /* SPT      D2(B2)     [S] */
         /* Set CPU Timer */
         check_privileged(s);
@@ -2923,6 +2905,20 @@ static ExitStatus op_stck(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_sckc(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    gen_helper_stckc(o->out, cpu_env);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit 434c91a5f4ed7219819678315b5529fbc35435e6
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:31:07 2012 -0700

    target-s390: Convert STCK
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 3591a92..d3a30cb 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -84,7 +84,7 @@ DEF_HELPER_3(servc, i32, env, i32, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_2(stck, i32, env, i64)
+DEF_HELPER_FLAGS_1(stck, TCG_CALL_NO_RWG_SE, i64, env)
 DEF_HELPER_2(stcke, i32, env, i64)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(stckc, TCG_CALL_NO_RWG, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 824e9dc..4404791 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,9 @@
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
     C(0xae00, SIGP,    RS_a,  Z,   r3_o, a2, 0, 0, sigp, 0)
+/* STORE CLOCK */
+    C(0xb205, STCK,    S,     Z,   la2, 0, new, m1_64, stck, 0)
+    C(0xb27c, STCKF,   S,     Z,   la2, 0, new, m1_64, stck, 0)
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index c163591..f1edf6c 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -154,11 +154,9 @@ static inline uint64_t clock_value(CPUS390XState *env)
 }
 
 /* Store Clock */
-uint32_t HELPER(stck)(CPUS390XState *env, uint64_t a1)
+uint64_t HELPER(stck)(CPUS390XState *env)
 {
-    cpu_stq_data(env, a1, clock_value(env));
-
-    return 0;
+    return clock_value(env);
 }
 
 /* Store Clock Extended */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e835df0..624ee8d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x05: /* STCK     D2(B2)     [S] */
-        /* Store Clock */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stck(cc_op, cpu_env, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x06: /* SCKC     D2(B2)     [S] */
         /* Set Clock Comparator */
         check_privileged(s);
@@ -2924,6 +2915,14 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stck(DisasContext *s, DisasOps *o)
+{
+    gen_helper_stck(o->out, cpu_env);
+    /* ??? We don't implement clock states.  */
+    gen_op_movi_cc(s, 0);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit 352897995147c4a054679654048f5c128ca32743
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 15:20:49 2012 -0700

    target-s390: Convert SCK
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 8e90741..3591a92 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -84,7 +84,6 @@ DEF_HELPER_3(servc, i32, env, i32, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
-DEF_HELPER_FLAGS_1(sck, TCG_CALL_NO_RWG, i32, i64)
 DEF_HELPER_2(stck, i32, env, i64)
 DEF_HELPER_2(stcke, i32, env, i64)
 DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4d9ecf4..824e9dc 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -633,6 +633,9 @@
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
     C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
+/* SET CLOCK */
+    /* ??? Not implemented - is it necessary? */
+    C(0xb204, SCK,     S,     Z,   0, 0, 0, 0, 0, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 009cc92..c163591 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -143,14 +143,6 @@ void HELPER(spx)(CPUS390XState *env, uint64_t a1)
     tlb_flush_page(env, TARGET_PAGE_SIZE);
 }
 
-/* Set Clock */
-uint32_t HELPER(sck)(uint64_t a1)
-{
-    /* XXX not implemented - is it necessary? */
-
-    return 0;
-}
-
 static inline uint64_t clock_value(CPUS390XState *env)
 {
     uint64_t time;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d57c737..e835df0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,16 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x04: /* SCK       D2(B2)     [S] */
-        /* Set Clock */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_sck(cc_op, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x05: /* STCK     D2(B2)     [S] */
         /* Store Clock */
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
commit 71bd666963ad9fb004d7aa919b7222165e602173
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:21:47 2012 -0700

    target-s390: Convert STIDP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index dd7479a..8e90741 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_3(servc, i32, env, i32, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
-DEF_HELPER_FLAGS_2(stidp, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(sck, TCG_CALL_NO_RWG, i32, i64)
 DEF_HELPER_2(stck, i32, env, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 5e1f8fd..4d9ecf4 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -640,6 +640,8 @@
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
     C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
+/* STORE CPU ID */
+    C(0xb202, STIDP,   S,     Z,   la2, 0, new, m1_64, stidp, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 6dca0eb..009cc92 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -131,12 +131,6 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
     return r;
 }
 
-/* Store CPU ID */
-void HELPER(stidp)(CPUS390XState *env, uint64_t a1)
-{
-    cpu_stq_data(env, a1, env->cpu_num);
-}
-
 /* Set Prefix */
 void HELPER(spx)(CPUS390XState *env, uint64_t a1)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bbbd5fe..d57c737 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1033,15 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x02: /* STIDP     D2(B2)     [S] */
-        /* Store CPU ID */
-        check_privileged(s);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        potential_page_fault(s);
-        gen_helper_stidp(cpu_env, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x04: /* SCK       D2(B2)     [S] */
         /* Set Clock */
         check_privileged(s);
@@ -2967,6 +2958,13 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
+    return NO_EXIT;
+}
+
 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
 {
     uint64_t i2 = get_field(s->fields, i2);
commit 4600c994d93fc9af2b045086dd31e613d2f9d7bc
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 14:27:42 2012 -0700

    target-s390: Convert SRST
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 999d5d0..dd7479a 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -13,7 +13,7 @@ DEF_HELPER_3(divs32, s64, env, s64, s64)
 DEF_HELPER_3(divu32, i64, env, i64, i64)
 DEF_HELPER_3(divs64, s64, env, s64, s64)
 DEF_HELPER_4(divu64, i64, env, i64, i64, i64)
-DEF_HELPER_4(srst, i32, env, i32, i32, i32)
+DEF_HELPER_4(srst, i64, env, i64, i64, i64)
 DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
 DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b485b85..5e1f8fd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -471,6 +471,9 @@
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
 
+/* SEARCH STRING */
+    C(0xb25e, SRST,    RRE,   Z,   r1_o, r2_o, 0, 0, srst, 0)
+
 /* SET ACCESS */
     C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 /* SET FPC */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 7d87c74..59877ee 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -331,25 +331,38 @@ static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
 }
 
 /* search string (c is byte to search, r2 is string, r1 end of string) */
-uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(srst)(CPUS390XState *env, uint64_t r0, uint64_t end,
+                      uint64_t str)
 {
-    uint64_t i;
-    uint32_t cc = 2;
-    uint64_t str = get_address_31fix(env, r2);
-    uint64_t end = get_address_31fix(env, r1);
+    uint32_t len;
+    uint8_t v, c = r0;
 
-    HELPER_LOG("%s: c %d *r1 0x%" PRIx64 " *r2 0x%" PRIx64 "\n", __func__,
-               c, env->regs[r1], env->regs[r2]);
+    str = fix_address(env, str);
+    end = fix_address(env, end);
 
-    for (i = str; i != end; i++) {
-        if (cpu_ldub_data(env, i) == c) {
-            env->regs[r1] = i;
-            cc = 1;
-            break;
+    /* Assume for now that R2 is unmodified.  */
+    env->retxl = str;
+
+    /* Lest we fail to service interrupts in a timely manner, limit the
+       amount of work we're willing to do.  For now, lets cap at 8k.  */
+    for (len = 0; len < 0x2000; ++len) {
+        if (str + len == end) {
+            /* Character not found.  R1 & R2 are unmodified.  */
+            env->cc_op = 2;
+            return end;
+        }
+        v = cpu_ldub_data(env, str + len);
+        if (v == c) {
+            /* Character found.  Set R1 to the location; R2 is unmodified.  */
+            env->cc_op = 1;
+            return str + len;
         }
     }
 
-    return cc;
+    /* CPU-determined bytes processed.  Advance R2 to next byte to process.  */
+    env->retxl = str + len;
+    env->cc_op = 3;
+    return end;
 }
 
 /* unsigned string compare (c is string terminator) */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f1eb4bb..bbbd5fe 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1021,12 +1021,11 @@ static void free_compare(DisasCompare *c)
 static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
                      uint32_t insn)
 {
+#ifndef CONFIG_USER_ONLY
     TCGv_i64 tmp, tmp2, tmp3;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i32 tmp32_1, tmp32_2;
     int r1, r2;
-#ifndef CONFIG_USER_ONLY
     int r3, d2, b2;
-#endif
 
     r1 = (insn >> 4) & 0xf;
     r2 = insn & 0xf;
@@ -1034,19 +1033,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x5e: /* SRST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_srst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-
-#ifndef CONFIG_USER_ONLY
     case 0x02: /* STIDP     D2(B2)     [S] */
         /* Store CPU ID */
         check_privileged(s);
@@ -1314,12 +1300,14 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-#endif
     default:
+#endif
         LOG_DISAS("illegal b2 operation 0x%x\n", op);
         gen_illegal_opcode(s);
+#ifndef CONFIG_USER_ONLY
         break;
     }
+#endif
 }
 
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
@@ -3136,6 +3124,15 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_srst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
commit aa31bf60312157aefb09f887e2f750c7d59a8bbc
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:20:53 2012 -0700

    target-s390: Convert CLST, MVST
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c6afcbc..999d5d0 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -14,9 +14,9 @@ DEF_HELPER_3(divu32, i64, env, i64, i64)
 DEF_HELPER_3(divs64, s64, env, s64, s64)
 DEF_HELPER_4(divu64, i64, env, i64, i64, i64)
 DEF_HELPER_4(srst, i32, env, i32, i32, i32)
-DEF_HELPER_4(clst, i32, env, i32, i32, i32)
+DEF_HELPER_4(clst, i64, env, i64, i64, i64)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
-DEF_HELPER_4(mvst, void, env, i32, i32, i32)
+DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
 DEF_HELPER_4(csg, i64, env, i64, i64, i64)
 DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
 DEF_HELPER_4(cs, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4223d35..b485b85 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -153,6 +153,8 @@
     C(0xbd00, CLM,     RS_b,  Z,   r1_o, a2, 0, 0, clm, 0)
     C(0xeb21, CLMY,    RSY_b, LD,  r1_o, a2, 0, 0, clm, 0)
     C(0xeb20, CLMH,    RSY_b, Z,   r1_sr32, a2, 0, 0, clm, 0)
+/* COMPARE LOGICAL STRING */
+    C(0xb25d, CLST,    RRE,   Z,   r1_o, r2_o, 0, 0, clst, 0)
 
 /* COMPARE AND SWAP */
     C(0xba00, CS,      RS_a,  Z,   r1_o, a2, new, r1_32, cs, 0)
@@ -396,6 +398,8 @@
     C(0xa800, MVCLE,   RS_a,  Z,   0, a2, 0, 0, mvcle, 0)
 /* MOVE PAGE */
     C(0xb254, MVPG,    RRE,   Z,   r1_o, r2_o, 0, 0, mvpg, 0)
+/* MOVE STRING */
+    C(0xb255, MVST,    RRE,   Z,   r1_o, r2_o, 0, 0, mvst, 0)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 61c35a2..7d87c74 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -304,36 +304,30 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
     return cc;
 }
 
+static inline uint64_t fix_address(CPUS390XState *env, uint64_t a)
+{
+    /* 31-Bit mode */
+    if (!(env->psw.mask & PSW_MASK_64)) {
+        a &= 0x7fffffff;
+    }
+    return a;
+}
+
 static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
 {
     uint64_t r = d2;
-
     if (x2) {
         r += env->regs[x2];
     }
-
     if (b2) {
         r += env->regs[b2];
     }
-
-    /* 31-Bit mode */
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        r &= 0x7fffffff;
-    }
-
-    return r;
+    return fix_address(env, r);
 }
 
 static inline uint64_t get_address_31fix(CPUS390XState *env, int reg)
 {
-    uint64_t r = env->regs[reg];
-
-    /* 31-Bit mode */
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        r &= 0x7fffffff;
-    }
-
-    return r;
+    return fix_address(env, env->regs[reg]);
 }
 
 /* search string (c is byte to search, r2 is string, r1 end of string) */
@@ -359,39 +353,40 @@ uint32_t HELPER(srst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 }
 
 /* unsigned string compare (c is string terminator) */
-uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, uint64_t s1, uint64_t s2)
 {
-    uint64_t s1 = get_address_31fix(env, r1);
-    uint64_t s2 = get_address_31fix(env, r2);
-    uint8_t v1, v2;
-    uint32_t cc;
+    uint32_t len;
 
     c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
-    if (!c) {
-        HELPER_LOG("%s: comparing '%s' and '%s'\n",
-                   __func__, (char *)g2h(s1), (char *)g2h(s2));
-    }
-#endif
-    for (;;) {
-        v1 = cpu_ldub_data(env, s1);
-        v2 = cpu_ldub_data(env, s2);
-        if ((v1 == c || v2 == c) || (v1 != v2)) {
-            break;
+    s1 = fix_address(env, s1);
+    s2 = fix_address(env, s2);
+
+    /* Lest we fail to service interrupts in a timely manner, limit the
+       amount of work we're willing to do.  For now, lets cap at 8k.  */
+    for (len = 0; len < 0x2000; ++len) {
+        uint8_t v1 = cpu_ldub_data(env, s1 + len);
+        uint8_t v2 = cpu_ldub_data(env, s2 + len);
+        if (v1 == v2) {
+            if (v1 == c) {
+                /* Equal.  CC=0, and don't advance the registers.  */
+                env->cc_op = 0;
+                env->retxl = s2;
+                return s1;
+            }
+        } else {
+            /* Unequal.  CC={1,2}, and advance the registers.  Note that
+               the terminator need not be zero, but the string that contains
+               the terminator is by definition "low".  */
+            env->cc_op = (v1 == c ? 1 : v2 == c ? 2 : v1 < v2 ? 1 : 2);
+            env->retxl = s2 + len;
+            return s1 + len;
         }
-        s1++;
-        s2++;
     }
 
-    if (v1 == v2) {
-        cc = 0;
-    } else {
-        cc = (v1 < v2) ? 1 : 2;
-        /* FIXME: 31-bit mode! */
-        env->regs[r1] = s1;
-        env->regs[r2] = s2;
-    }
-    return cc;
+    /* CPU-determined bytes equal; advance the registers.  */
+    env->cc_op = 3;
+    env->retxl = s2 + len;
+    return s1 + len;
 }
 
 /* move page */
@@ -407,29 +402,31 @@ void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
 }
 
 /* string copy (c is string terminator) */
-void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
+uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
 {
-    uint64_t dest = get_address_31fix(env, r1);
-    uint64_t src = get_address_31fix(env, r2);
-    uint8_t v;
+    uint32_t len;
 
     c = c & 0xff;
-#ifdef CONFIG_USER_ONLY
-    if (!c) {
-        HELPER_LOG("%s: copy '%s' to 0x%lx\n", __func__, (char *)g2h(src),
-                   dest);
-    }
-#endif
-    for (;;) {
-        v = cpu_ldub_data(env, src);
-        cpu_stb_data(env, dest, v);
+    d = fix_address(env, d);
+    s = fix_address(env, s);
+
+    /* Lest we fail to service interrupts in a timely manner, limit the
+       amount of work we're willing to do.  For now, lets cap at 8k.  */
+    for (len = 0; len < 0x2000; ++len) {
+        uint8_t v = cpu_ldub_data(env, s + len);
+        cpu_stb_data(env, d + len, v);
         if (v == c) {
-            break;
+            /* Complete.  Set CC=1 and advance R1.  */
+            env->cc_op = 1;
+            env->retxl = s;
+            return d + len;
         }
-        src++;
-        dest++;
     }
-    env->regs[r1] = dest; /* FIXME: 31-bit mode! */
+
+    /* Incomplete.  Set CC=3 and signal to advance R1 and R2.  */
+    env->cc_op = 3;
+    env->retxl = s + len;
+    return d + len;
 }
 
 /* compare and swap 64-bit */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d77b30f..f1eb4bb 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -427,7 +427,7 @@ static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
     return tmp;
 }
 
-static void gen_op_movi_cc(DisasContext *s, uint32_t val)
+static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
 {
     s->cc_op = CC_OP_CONST0 + val;
 }
@@ -1034,28 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x55: /* MVST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_mvst(cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        gen_op_movi_cc(s, 1);
-        break;
-    case 0x5d: /* CLST     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(0);
-        tmp32_2 = tcg_const_i32(r1);
-        tmp32_3 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_clst(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0x5e: /* SRST     R1,R2     [RRE] */
         tmp32_1 = load_reg32(0);
         tmp32_2 = tcg_const_i32(r1);
@@ -2091,6 +2069,15 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_clst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cs(DisasContext *s, DisasOps *o)
 {
     int r3 = get_field(s->fields, r3);
@@ -2650,6 +2637,15 @@ static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return_low128(o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
commit ee6c38d5b10fda25175fa85febde532a12456346
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:19:44 2012 -0700

    target-s390: Convert MVPG
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c4ce7e2..4223d35 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -394,6 +394,8 @@
     C(0x0e00, MVCL,    RR_a,  Z,   0, 0, 0, 0, mvcl, 0)
 /* MOVE LONG EXTENDED */
     C(0xa800, MVCLE,   RS_a,  Z,   0, a2, 0, 0, mvcle, 0)
+/* MOVE PAGE */
+    C(0xb254, MVPG,    RRE,   Z,   r1_o, r2_o, 0, 0, mvpg, 0)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 9c7815a..61c35a2 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -398,12 +398,9 @@ uint32_t HELPER(clst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 void HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t r2)
 {
     /* XXX missing r0 handling */
+    env->cc_op = 0;
 #ifdef CONFIG_USER_ONLY
-    int i;
-
-    for (i = 0; i < TARGET_PAGE_SIZE; i++) {
-        cpu_stb_data(env, r1 + i, cpu_ldub_data(env, r2 + i));
-    }
+    memmove(g2h(r1), g2h(r2), TARGET_PAGE_SIZE);
 #else
     mvc_fast_memmove(env, TARGET_PAGE_SIZE, r1, r2);
 #endif
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index de9e2fe..d77b30f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,18 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x54: /* MVPG     R1,R2     [RRE] */
-        tmp = load_reg(0);
-        tmp2 = load_reg(r1);
-        tmp3 = load_reg(r2);
-        potential_page_fault(s);
-        gen_helper_mvpg(cpu_env, tmp, tmp2, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        /* XXX check CCO bit and set CC accordingly */
-        gen_op_movi_cc(s, 0);
-        break;
     case 0x55: /* MVST     R1,R2     [RRE] */
         tmp32_1 = load_reg32(0);
         tmp32_2 = tcg_const_i32(r1);
@@ -2654,6 +2642,14 @@ static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
commit d62a4c97f2cab0bd8649e3cd0b7692f989dbb577
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 11:54:04 2012 -0700

    target-s390: Convert EAR, SAR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 74f1032..c4ce7e2 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -220,6 +220,8 @@
 /* EXECUTE RELATIVE LONG */
     C(0xc600, EXRL,    RIL_b, EE,  r1_o, ri2, 0, 0, ex, 0)
 
+/* EXTRACT ACCESS */
+    C(0xb24f, EAR,     RRE,   Z,   0, 0, new, r1_32, ear, 0)
 /* EXTRACT FPC */
     C(0xb38c, EFPC,    RRE,   Z,   0, 0, new, r1_32, efpc, 0)
 
@@ -463,6 +465,8 @@
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
 
+/* SET ACCESS */
+    C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 /* SET FPC */
     C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ea2b1dc..de9e2fe 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,17 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x4e: /* SAR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x4f: /* EAR     R1,R2     [RRE] */
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r2]));
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x54: /* MVPG     R1,R2     [RRE] */
         tmp = load_reg(0);
         tmp2 = load_reg(r1);
@@ -2230,6 +2219,13 @@ static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ear(DisasContext *s, DisasOps *o)
+{
+    int r2 = get_field(s->fields, r2);
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
+    return NO_EXIT;
+}
+
 static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
 {
     tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
@@ -2864,6 +2860,13 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sar(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
+    return NO_EXIT;
+}
+
 static ExitStatus op_seb(DisasContext *s, DisasOps *o)
 {
     gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
commit 374724f91ab236b4f60ec4796f1601720486d06b
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 11:38:12 2012 -0700

    target-s390: Convert CKSM
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 6336678..c6afcbc 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -75,7 +75,7 @@ DEF_HELPER_3(sqxb, i64, env, i64, i64)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
 DEF_HELPER_4(unpk, void, env, i32, i64, i64)
 DEF_HELPER_4(tr, void, env, i32, i64, i64)
-DEF_HELPER_3(cksm, void, env, i32, i32)
+DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
 
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 13b1771..74f1032 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -91,6 +91,9 @@
     C(0xa706, BRCT,    RI_b,  Z,   0, 0, 0, 0, bct32, 0)
     C(0xa707, BRCTG,   RI_b,  Z,   0, 0, 0, 0, bct64, 0)
 
+/* CHECKSUM */
+    C(0xb241, CKSM,    RRE,   Z,   r1_o, ra2, new, r1_32, cksm, 0)
+
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
     C(0x5900, C,       RX_a,  Z,   r1_o, m2_32s, 0, 0, 0, cmps32)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 9c3ade8..9c7815a 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -747,42 +747,49 @@ uint32_t HELPER(clcle)(CPUS390XState *env, uint32_t r1, uint64_t a2,
 }
 
 /* checksum */
-void HELPER(cksm)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint64_t HELPER(cksm)(CPUS390XState *env, uint64_t r1,
+                      uint64_t src, uint64_t src_len)
 {
-    uint64_t src = get_address_31fix(env, r2);
-    uint64_t src_len = env->regs[(r2 + 1) & 15];
-    uint64_t cksm = (uint32_t)env->regs[r1];
+    uint64_t max_len, len;
+    uint64_t cksm = (uint32_t)r1;
 
-    while (src_len >= 4) {
-        cksm += cpu_ldl_data(env, src);
+    /* Lest we fail to service interrupts in a timely manner, limit the
+       amount of work we're willing to do.  For now, lets cap at 8k.  */
+    max_len = (src_len > 0x2000 ? 0x2000 : src_len);
 
-        /* move to next word */
-        src_len -= 4;
-        src += 4;
+    /* Process full words as available.  */
+    for (len = 0; len + 4 <= max_len; len += 4, src += 4) {
+        cksm += (uint32_t)cpu_ldl_data(env, src);
     }
 
-    switch (src_len) {
-    case 0:
-        break;
+    switch (max_len - len) {
     case 1:
         cksm += cpu_ldub_data(env, src) << 24;
+        len += 1;
         break;
     case 2:
         cksm += cpu_lduw_data(env, src) << 16;
+        len += 2;
         break;
     case 3:
         cksm += cpu_lduw_data(env, src) << 16;
         cksm += cpu_ldub_data(env, src + 2) << 8;
+        len += 3;
         break;
     }
 
-    /* indicate we've processed everything */
-    env->regs[r2] = src + src_len;
-    env->regs[(r2 + 1) & 15] = 0;
+    /* Fold the carry from the checksum.  Note that we can see carry-out
+       during folding more than once (but probably not more than twice).  */
+    while (cksm > 0xffffffffull) {
+        cksm = (uint32_t)cksm + (cksm >> 32);
+    }
+
+    /* Indicate whether or not we've processed everything.  */
+    env->cc_op = (len == src_len ? 0 : 3);
 
-    /* store result */
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        ((uint32_t)cksm + (cksm >> 32));
+    /* Return both cksm and processed length.  */
+    env->retxl = cksm;
+    return len;
 }
 
 void HELPER(unpk)(CPUS390XState *env, uint32_t len, uint64_t dest,
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 702b174..ea2b1dc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,15 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x41: /* CKSM    R1,R2     [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_cksm(cpu_env, tmp32_1, tmp32_2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        gen_op_movi_cc(s, 0);
-        break;
     case 0x4e: /* SAR     R1,R2     [RRE] */
         tmp32_1 = load_reg32(r2);
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, aregs[r1]));
@@ -2047,6 +2038,23 @@ static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
+{
+    int r2 = get_field(s->fields, r2);
+    TCGv_i64 len = tcg_temp_new_i64();
+
+    potential_page_fault(s);
+    gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
+    set_cc_static(s);
+    return_low128(o->out);
+
+    tcg_gen_add_i64(regs[r2], regs[r2], len);
+    tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
+    tcg_temp_free_i64(len);
+
+    return NO_EXIT;
+}
+
 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
 {
     int l = get_field(s->fields, l1);
@@ -3847,6 +3855,11 @@ static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = o->g_in2 = true;
 }
 
+static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = get_address(s, 0, get_field(f, r2), 0);
+}
+
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
commit 6e2704e74d317ba077b680c2fc881724686fb24a
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:18:21 2012 -0700

    target-s390: Convert IPM
    
    Note that the previous placement of the PM field was incorrect.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index e3bed16..a6d60bf 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -544,18 +544,6 @@ uint32_t HELPER(calc_cc)(CPUS390XState *env, uint32_t cc_op, uint64_t src,
     return do_calc_cc(env, cc_op, src, dst, vr);
 }
 
-/* insert psw mask and condition code into r1 */
-void HELPER(ipm)(CPUS390XState *env, uint32_t cc, uint32_t r1)
-{
-    uint64_t r = env->regs[r1];
-
-    r &= 0xffffffff00ffffffULL;
-    r |= (cc << 28) | ((env->psw.mask >> 40) & 0xf);
-    env->regs[r1] = r;
-    HELPER_LOG("%s: cc %d psw.mask 0x%lx r1 0x%lx\n", __func__,
-               cc, env->psw.mask, r);
-}
-
 #ifndef CONFIG_USER_ONLY
 void HELPER(load_psw)(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 3cc4cbd..6336678 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -25,7 +25,6 @@ DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
 DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
-DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b319beb..13b1771 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -237,6 +237,8 @@
     D(0xa501, IIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1020)
     D(0xa502, IILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1010)
     D(0xa503, IILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1000)
+/* INSERT PROGRAM MASK */
+    C(0xb222, IPM,     RRE,   Z,   0, 0, r1, 0, ipm, 0)
 
 /* LOAD */
     C(0x1800, LR,      RR_a,  Z,   0, r2_o, 0, cond_r1r2_32, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d4f1bc4..702b174 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1034,12 +1034,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     LOG_DISAS("disas_b2: op 0x%x r1 %d r2 %d\n", op, r1, r2);
 
     switch (op) {
-    case 0x22: /* IPM    R1               [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_op_calc_cc(s);
-        gen_helper_ipm(cpu_env, cc_op, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x41: /* CKSM    R1,R2     [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r2);
@@ -2348,6 +2342,25 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t1;
+
+    gen_op_calc_cc(s);
+    tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
+
+    t1 = tcg_temp_new_i64();
+    tcg_gen_shli_i64(t1, psw_mask, 20);
+    tcg_gen_shri_i64(t1, t1, 36);
+    tcg_gen_or_i64(o->out, o->out, t1);
+
+    tcg_gen_extu_i32_i64(t1, cc_op);
+    tcg_gen_shli_i64(t1, t1, 28);
+    tcg_gen_or_i64(o->out, o->out, t1);
+    tcg_temp_free_i64(t1);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
 {
     gen_helper_ldeb(o->out, cpu_env, o->in2);
commit 8379bfdbca195af9df1e6ecf67f04402bd80d471
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 07:44:43 2012 -0700

    target-s390: Convert LFPC, SFPC
    
    Note that we were failing to set the rounding mode in fpu_status.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index ac530e9..74b94f2 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -577,3 +577,20 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     handle_exceptions(env, GETPC());
     return RET128(ret);
 }
+
+/* set fpc */
+void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
+{
+    static const int rnd[4] = {
+        float_round_nearest_even,
+        float_round_to_zero,
+        float_round_up,
+        float_round_down
+    };
+
+    /* Install everything in the main FPC.  */
+    env->fpc = fpc;
+
+    /* Install the rounding mode in the shadow fpu_status.  */
+    set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
+}
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index e64b46d..3cc4cbd 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -78,6 +78,7 @@ DEF_HELPER_4(unpk, void, env, i32, i64, i64)
 DEF_HELPER_4(tr, void, env, i32, i64, i64)
 DEF_HELPER_3(cksm, void, env, i32, i32)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
 
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 771baaf..b319beb 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -351,6 +351,9 @@
     C(0xb375, LZDR,    RRE,   Z,   0, 0, 0, f1, zero, 0)
     C(0xb376, LZXR,    RRE,   Z,   0, 0, 0, x1, zero2, 0)
 
+/* LOAD FPC */
+    C(0xb29d, LFPC,    S,     Z,   0, m2_32u, 0, 0, sfpc, 0)
+
 /* LOAD LENGTHENED */
     C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
     C(0xb305, LXDBR,   RRE,   Z,   0, f2_o, x1, 0, lxdb, 0)
@@ -455,6 +458,9 @@
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
 
+/* SET FPC */
+    C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
+
 /* SHIFT LEFT SINGLE */
     D(0x8b00, SLA,     RS_a,  Z,   r1, sh32, new, r1_32, sla, 0, 31)
     D(0xebdd, SLAK,    RSY_a, DO,  r3, sh32, new, r1_32, sla, 0, 31)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e674c93..d4f1bc4 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1337,18 +1337,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x9d: /* LFPC      D2(B2)   [S] */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0xb1: /* STFL     D2(B2)     [S] */
         /* Store Facility List (CPU features) at 200 */
         check_privileged(s);
@@ -1394,47 +1382,11 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     }
 }
 
-static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
-                     int r1, int r2)
-{
-    TCGv_i32 tmp32_1;
-    LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
-#define FP_HELPER(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-#define FP_HELPER_CC(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
-    set_cc_static(s); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-    switch (op) {
-    case 0x84: /* SFPC        R1                [RRE] */
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    default:
-        LOG_DISAS("illegal b3 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-
-#undef FP_HELPER_CC
-#undef FP_HELPER
-}
-
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3;
+    int op;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -1445,14 +1397,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b2(env, s, op, insn);
         break;
-    case 0xb3:
-        insn = ld_code4(env, s->pc);
-        op = (insn >> 16) & 0xff;
-        r3 = (insn >> 12) & 0xf; /* aka m3 */
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        disas_b3(env, s, op, r3, r1, r2);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -2981,6 +2925,12 @@ static ExitStatus op_srl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sfpc(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
commit 102bf2c63535122cba0d7917ed8cfb8cc1c7b14c
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 24 07:39:11 2012 -0700

    target-s390: Convert FLOGR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index f1038be..e3bed16 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -399,6 +399,11 @@ static uint32_t cc_calc_sla_64(uint64_t src, int shift)
     return 2;
 }
 
+static uint32_t cc_calc_flogr(uint64_t dst)
+{
+    return dst ? 2 : 0;
+}
+
 static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                   uint64_t src, uint64_t dst, uint64_t vr)
 {
@@ -504,6 +509,9 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
     case CC_OP_SLA_64:
         r =  cc_calc_sla_64(src, dst);
         break;
+    case CC_OP_FLOGR:
+        r = cc_calc_flogr(dst);
+        break;
 
     case CC_OP_NZ_F32:
         r = set_cc_nz_f32(dst);
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index f1d4dc6..dc7bbc6 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -478,6 +478,7 @@ enum cc_op {
     CC_OP_ICM,                  /* insert characters under mask */
     CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
     CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
+    CC_OP_FLOGR,                /* find leftmost one */
     CC_OP_MAX
 };
 
@@ -521,6 +522,7 @@ static const char *cc_names[] = {
     [CC_OP_ICM]       = "CC_OP_ICM",
     [CC_OP_SLA_32]    = "CC_OP_SLA_32",
     [CC_OP_SLA_64]    = "CC_OP_SLA_64",
+    [CC_OP_FLOGR]     = "CC_OP_FLOGR",
 };
 
 static inline const char *cc_name(int cc_op)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index d9f630e..e64b46d 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -69,7 +69,7 @@ DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
-DEF_HELPER_3(flogr, i32, env, i32, i64)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_2(sqeb, i64, env, i64)
 DEF_HELPER_2(sqdb, i64, env, i64)
 DEF_HELPER_3(sqxb, i64, env, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index d5e1c5c..771baaf 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -220,6 +220,9 @@
 /* EXTRACT FPC */
     C(0xb38c, EFPC,    RRE,   Z,   0, 0, new, r1_32, efpc, 0)
 
+/* FIND LEFTMOST ONE */
+    C(0xb983, FLOGR,   RRE,   EI,  0, r2_o, r1_P, 0, flogr, 0)
+
 /* INSERT CHARACTER */
     C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
     C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index 839c0e1..dc16de2 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -165,26 +165,10 @@ int64_t HELPER(nabs_i64)(int64_t val)
     }
 }
 
-/* find leftmost one */
-uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+/* count leading zeros, for find leftmost one */
+uint64_t HELPER(clz)(uint64_t v)
 {
-    uint64_t res = 0;
-    uint64_t ov2 = v2;
-
-    while (!(v2 & 0x8000000000000000ULL) && v2) {
-        v2 <<= 1;
-        res++;
-    }
-
-    if (!v2) {
-        env->regs[r1] = 64;
-        env->regs[r1 + 1] = 0;
-        return 0;
-    } else {
-        env->regs[r1] = res;
-        env->regs[r1 + 1] = ov2 & ~(0x8000000000000000ULL >> res);
-        return 2;
-    }
+    return clz64(v);
 }
 
 uint64_t HELPER(cvd)(int32_t bin)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 47ccc67..e674c93 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -620,6 +620,7 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_COMP_64:
     case CC_OP_NZ_F32:
     case CC_OP_NZ_F64:
+    case CC_OP_FLOGR:
         /* 1 argument */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
         break;
@@ -852,6 +853,20 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
         account_inline_branch(s, old_cc_op);
         break;
 
+    case CC_OP_FLOGR:
+        switch (mask & 0xa) {
+        case 8: /* src == 0 -> no one bit found */
+            cond = TCG_COND_EQ;
+            break;
+        case 2: /* src != 0 -> one bit found */
+            cond = TCG_COND_NE;
+            break;
+        default:
+            goto do_dynamic;
+        }
+        account_inline_branch(s, old_cc_op);
+        break;
+
     default:
     do_dynamic:
         /* Calculate cc value.  */
@@ -888,6 +903,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
 
     case CC_OP_LTGT0_64:
     case CC_OP_NZ:
+    case CC_OP_FLOGR:
         c->u.s64.a = cc_dst;
         c->u.s64.b = tcg_const_i64(0);
         c->g1 = true;
@@ -1414,29 +1430,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
 #undef FP_HELPER
 }
 
-static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int r2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1;
-
-    LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
-    switch (op) {
-    case 0x83: /* FLOGR R1,R2 [RRE] */
-        tmp = load_reg(r2);
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_flogr(cc_op, cpu_env, tmp32_1, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    default:
-        LOG_DISAS("illegal b9 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     unsigned char opc;
@@ -1460,13 +1453,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         r2 = insn & 0xf;
         disas_b3(env, s, op, r3, r1, r2);
         break;
-    case 0xb9:
-        insn = ld_code4(env, s->pc);
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        op = (insn >> 16) & 0xff;
-        disas_b9(env, s, op, r1, r2);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -2330,6 +2316,26 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
+{
+    /* We'll use the original input for cc computation, since we get to
+       compare that against 0, which ought to be better than comparing
+       the real output against 64.  It also lets cc_dst be a convenient
+       temporary during our computation.  */
+    gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
+
+    /* R1 = IN ? CLZ(IN) : 64.  */
+    gen_helper_clz(o->out, o->in2);
+
+    /* R1+1 = IN & ~(found bit).  Note that we may attempt to shift this
+       value by 64, which is undefined.  But since the shift is 64 iff the
+       input is zero, we still get the correct result after and'ing.  */
+    tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
+    tcg_gen_shr_i64(o->out2, o->out2, o->out);
+    tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_icm(DisasContext *s, DisasOps *o)
 {
     int m3 = get_field(s->fields, m3);
commit 683bb9a8889cd00e69b05ba78bd5ba27f2e4e958
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 21:08:22 2012 -0700

    target-s390: Convert CONVERT FROM FIXED
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index ff3b435..ac530e9 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -134,57 +134,6 @@ uint32_t set_cc_nz_f128(float128 v)
     }
 }
 
-/* convert 32-bit int to 64-bit float */
-void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
-    HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
-    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 32-bit int to 128-bit float */
-void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
-    CPU_QuadU v1;
-
-    v1.q = int32_to_float128(v2, &env->fpu_status);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
-/* convert 64-bit int to 32-bit float */
-void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
-    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
-    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 64-bit float */
-void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
-    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
-    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
-}
-
-/* convert 64-bit int to 128-bit float */
-void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
-{
-    CPU_QuadU x1;
-
-    x1.q = int64_to_float128(v2, &env->fpu_status);
-    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
-               x1.ll.upper, x1.ll.lower);
-    env->fregs[f1].ll = x1.ll.upper;
-    env->fregs[f1 + 2].ll = x1.ll.lower;
-}
-
-/* convert 32-bit int to 32-bit float */
-void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
-{
-    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
-    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
-               env->fregs[f1].l.upper, f1);
-}
-
 /* 32-bit FP addition */
 uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
@@ -416,6 +365,36 @@ static int swap_round_mode(CPUS390XState *env, int m3)
     return ret;
 }
 
+/* convert 64-bit int to 32-bit float */
+uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float32 ret = int64_to_float32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit int to 64-bit float */
+uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float64 ret = int64_to_float64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* convert 64-bit int to 128-bit float */
+uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3)
+{
+    int hold = swap_round_mode(env, m3);
+    float128 ret = int64_to_float128(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
+}
+
 /* convert 32-bit float to 64-bit int */
 uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 1439b5e..d9f630e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -30,12 +30,9 @@ DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
 DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
-DEF_HELPER_3(cefbr, void, env, i32, s32)
-DEF_HELPER_3(cdfbr, void, env, i32, s32)
-DEF_HELPER_3(cxfbr, void, env, i32, s32)
-DEF_HELPER_3(cegbr, void, env, i32, s64)
-DEF_HELPER_3(cdgbr, void, env, i32, s64)
-DEF_HELPER_3(cxgbr, void, env, i32, s64)
+DEF_HELPER_3(cegb, i64, env, s64, i32)
+DEF_HELPER_3(cdgb, i64, env, s64, i32)
+DEF_HELPER_3(cxgb, i64, env, s64, i32)
 DEF_HELPER_3(aeb, i64, env, i64, i64)
 DEF_HELPER_3(adb, i64, env, i64, i64)
 DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2d88b70..d5e1c5c 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -170,6 +170,13 @@
     C(0xb3a8, CGEBR,   RRF_e, Z,   0, e2, r1, 0, cgeb, 0)
     C(0xb3a9, CGDBR,   RRF_e, Z,   0, f2_o, r1, 0, cgdb, 0)
     C(0xb3aa, CGXBR,   RRF_e, Z,   0, x2_o, r1, 0, cgxb, 0)
+/* CONVERT FROM FIXED */
+    C(0xb394, CEFBR,   RRF_e, Z,   0, r2_32s, new, e1, cegb, 0)
+    C(0xb395, CDFBR,   RRF_e, Z,   0, r2_32s, f1, 0, cdgb, 0)
+    C(0xb396, CXFBR,   RRF_e, Z,   0, r2_32s, x1, 0, cxgb, 0)
+    C(0xb3a4, CEGBR,   RRF_e, Z,   0, r2_o, new, e1, cegb, 0)
+    C(0xb3a5, CDGBR,   RRF_e, Z,   0, r2_o, f1, 0, cdgb, 0)
+    C(0xb3a6, CXGBR,   RRF_e, Z,   0, r2_o, x1, 0, cxgb, 0)
 
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 03fae68..47ccc67 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1381,8 +1381,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
 static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
                      int r1, int r2)
 {
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2;
+    TCGv_i32 tmp32_1;
     LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
 #define FP_HELPER(i) \
     tmp32_1 = tcg_const_i32(r1); \
@@ -1405,51 +1404,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x94: /* CEFBR       R1,R2             [RRE] */
-    case 0x95: /* CDFBR       R1,R2             [RRE] */
-    case 0x96: /* CXFBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = load_reg32(r2);
-        switch (op) {
-        case 0x94:
-            gen_helper_cefbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        case 0x95:
-            gen_helper_cdfbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        case 0x96:
-            gen_helper_cxfbr(cpu_env, tmp32_1, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xa4: /* CEGBR       R1,R2             [RRE] */
-    case 0xa5: /* CDGBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp = load_reg(r2);
-        switch (op) {
-        case 0xa4:
-            gen_helper_cegbr(cpu_env, tmp32_1, tmp);
-            break;
-        case 0xa5:
-            gen_helper_cdgbr(cpu_env, tmp32_1, tmp);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xa6: /* CXGBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp = load_reg(r2);
-        gen_helper_cxgbr(cpu_env, tmp32_1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal b3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2144,6 +2098,31 @@ static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cegb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
 {
     int l = get_field(s->fields, l1);
commit 68c8bd93ccb0ee441d62b5b8b8911cf5c38663f8
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 15:17:35 2012 -0700

    target-s390: Convert CONVERT TO FIXED
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b735c2c..ff3b435 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -387,8 +387,9 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return float_comp_to_cc(env, cmp);
 }
 
-static void set_round_mode(CPUS390XState *env, int m3)
+static int swap_round_mode(CPUS390XState *env, int m3)
 {
+    int ret = env->fpu_status.float_rounding_mode;
     switch (m3) {
     case 0:
         /* current mode */
@@ -412,86 +413,69 @@ static void set_round_mode(CPUS390XState *env, int m3)
         set_float_rounding_mode(float_round_down, &env->fpu_status);
         break;
     }
+    return ret;
 }
 
 /* convert 32-bit float to 64-bit int */
-uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    float32 v2 = env->fregs[f2].l.upper;
-
-    set_round_mode(env, m3);
-    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
-    return set_cc_nz_f32(v2);
+    int hold = swap_round_mode(env, m3);
+    int64_t ret = float32_to_int64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 64-bit float to 64-bit int */
-uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    float64 v2 = env->fregs[f2].d;
-
-    set_round_mode(env, m3);
-    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
-    return set_cc_nz_f64(v2);
+    int hold = swap_round_mode(env, m3);
+    int64_t ret = float64_to_int64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 128-bit float to 64-bit int */
-uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    set_round_mode(env, m3);
-    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
-    if (float128_is_any_nan(v2.q)) {
-        return 3;
-    } else if (float128_is_zero(v2.q)) {
-        return 0;
-    } else if (float128_is_neg(v2.q)) {
-        return 1;
-    } else {
-        return 2;
-    }
+    int hold = swap_round_mode(env, m3);
+    float128 v2 = make_float128(h, l);
+    int64_t ret = float128_to_int64(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 32-bit float to 32-bit int */
-uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    float32 v2 = env->fregs[f2].l.upper;
-
-    set_round_mode(env, m3);
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float32_to_int32(v2, &env->fpu_status);
-    return set_cc_nz_f32(v2);
+    int hold = swap_round_mode(env, m3);
+    int32_t ret = float32_to_int32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 64-bit float to 32-bit int */
-uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
 {
-    float64 v2 = env->fregs[f2].d;
-
-    set_round_mode(env, m3);
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float64_to_int32(v2, &env->fpu_status);
-    return set_cc_nz_f64(v2);
+    int hold = swap_round_mode(env, m3);
+    int32_t ret = float64_to_int32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 128-bit float to 32-bit int */
-uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
-                       uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
 {
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-        float128_to_int32(v2.q, &env->fpu_status);
-    return set_cc_nz_f128(v2.q);
+    int hold = swap_round_mode(env, m3);
+    float128 v2 = make_float128(h, l);
+    int32_t ret = float128_to_int32(v2, &env->fpu_status);
+    set_float_rounding_mode(hold, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* 32-bit FP multiply and add */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 89a3218..1439b5e 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -59,12 +59,12 @@ DEF_HELPER_3(lexb, i64, env, i64, i64)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
-DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
+DEF_HELPER_3(cgeb, i64, env, i64, i32)
+DEF_HELPER_3(cgdb, i64, env, i64, i32)
+DEF_HELPER_4(cgxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(cfeb, i64, env, i64, i32)
+DEF_HELPER_3(cfdb, i64, env, i64, i32)
+DEF_HELPER_4(cfxb, i64, env, i64, i64, i32)
 DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
 DEF_HELPER_4(madb, i64, env, i64, i64, i64)
 DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e6b9a5a..2d88b70 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -163,6 +163,13 @@
 /* CONVERT TO DECIMAL */
     C(0x4e00, CVD,     RX_a,  Z,   r1_o, a2, 0, 0, cvd, 0)
     C(0xe326, CVDY,    RXY_a, LD,  r1_o, a2, 0, 0, cvd, 0)
+/* CONVERT TO FIXED */
+    C(0xb398, CFEBR,   RRF_e, Z,   0, e2, new, r1_32, cfeb, 0)
+    C(0xb399, CFDBR,   RRF_e, Z,   0, f2_o, new, r1_32, cfdb, 0)
+    C(0xb39a, CFXBR,   RRF_e, Z,   0, x2_o, new, r1_32, cfxb, 0)
+    C(0xb3a8, CGEBR,   RRF_e, Z,   0, e2, r1, 0, cgeb, 0)
+    C(0xb3a9, CGDBR,   RRF_e, Z,   0, f2_o, r1, 0, cgdb, 0)
+    C(0xb3aa, CGXBR,   RRF_e, Z,   0, x2_o, r1, 0, cgxb, 0)
 
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b1bcfd3..03fae68 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -485,6 +485,21 @@ static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_NZ, val);
 }
 
+static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
+}
+
+static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
+}
+
+static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
+{
+    gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
+}
+
 static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
                           enum cc_op cond)
 {
@@ -1367,7 +1382,7 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
                      int r1, int r2)
 {
     TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i32 tmp32_1, tmp32_2;
     LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
 #define FP_HELPER(i) \
     tmp32_1 = tcg_const_i32(r1); \
@@ -1411,30 +1426,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x98: /* CFEBR       R1,R2             [RRE] */
-    case 0x99: /* CFDBR              R1,R2             [RRE] */
-    case 0x9a: /* CFXBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        switch (op) {
-        case 0x98:
-            gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x99:
-            gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x9a:
-            gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        default:
-            tcg_abort();
-        }
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0xa4: /* CEGBR       R1,R2             [RRE] */
     case 0xa5: /* CDGBR       R1,R2             [RRE] */
         tmp32_1 = tcg_const_i32(r1);
@@ -1459,36 +1450,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-    case 0xa8: /* CGEBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xa9: /* CGDBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xaa: /* CGXBR       R1,R2             [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(m3);
-        gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     default:
         LOG_DISAS("illegal b3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2129,6 +2090,60 @@ static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f32(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f64(s, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
+    tcg_temp_free_i32(m3);
+    gen_set_cc_nz_f128(s, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
 {
     int l = get_field(s->fields, l1);
commit 24db8412ec58a63556fb51fb157497342f1b08b8
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 10:14:24 2012 -0700

    target-s390: Convert LOAD ZERO
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 3b28ccb..b735c2c 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -494,28 +494,6 @@ uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
     return set_cc_nz_f128(v2.q);
 }
 
-/* load 32-bit FP zero */
-void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
-{
-    env->fregs[f1].l.upper = float32_zero;
-}
-
-/* load 64-bit FP zero */
-void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
-{
-    env->fregs[f1].d = float64_zero;
-}
-
-/* load 128-bit FP zero */
-void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
-{
-    CPU_QuadU x;
-
-    x.q = float64_to_float128(float64_zero, &env->fpu_status);
-    env->fregs[f1].ll = x.ll.upper;
-    env->fregs[f1 + 1].ll = x.ll.lower;
-}
-
 /* 32-bit FP multiply and add */
 uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
                       uint64_t f2, uint64_t f3)
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index eb8d663..89a3218 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -62,9 +62,6 @@ DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
 DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
-DEF_HELPER_2(lzer, void, env, i32)
-DEF_HELPER_2(lzdr, void, env, i32)
-DEF_HELPER_2(lzxr, void, env, i32)
 DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 93fd3ca..e6b9a5a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -329,6 +329,10 @@
     C(0xe31f, LRVH,    RXY_a, Z,   0, m2_16u, new, r1_16, rev16, 0)
     C(0xe31e, LRV,     RXY_a, Z,   0, m2_32u, new, r1_32, rev32, 0)
     C(0xe30f, LRVG,    RXY_a, Z,   0, m2_64, r1, 0, rev64, 0)
+/* LOAD ZERO */
+    C(0xb374, LZER,    RRE,   Z,   0, 0, 0, e1, zero, 0)
+    C(0xb375, LZDR,    RRE,   Z,   0, 0, 0, f1, zero, 0)
+    C(0xb376, LZXR,    RRE,   Z,   0, 0, 0, x1, zero2, 0)
 
 /* LOAD LENGTHENED */
     C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dd77998..b1bcfd3 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,21 +1385,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     tcg_temp_free_i32(tmp32_2);
 
     switch (op) {
-    case 0x74: /* LZER        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzer(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x75: /* LZDR        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzdr(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x76: /* LZXR        R1                [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        gen_helper_lzxr(cpu_env, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x84: /* SFPC        R1                [RRE] */
         tmp32_1 = load_reg32(r1);
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
@@ -3310,6 +3295,20 @@ static ExitStatus op_xori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_zero(DisasContext *s, DisasOps *o)
+{
+    o->out = tcg_const_i64(0);
+    return NO_EXIT;
+}
+
+static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
+{
+    o->out = tcg_const_i64(0);
+    o->out2 = o->out;
+    o->g_out2 = true;
+    return NO_EXIT;
+}
+
 /* ====================================================================== */
 /* The "Cc OUTput" generators.  Given the generated output (and in some cases
    the original inputs), update the various cc data structures in order to
commit 16d7b2a43b3325882d51677d76a0a3f082844f2b
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 14:33:03 2012 -0700

    target-s390: Convert FP SQUARE ROOT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b46dd02..3b28ccb 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -613,8 +613,26 @@ uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
     return cc;
 }
 
-/* square root 64-bit RR */
-void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* square root 32-bit */
+uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2)
 {
-    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
+    float32 ret = float32_sqrt(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* square root 64-bit */
+uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2)
+{
+    float64 ret = float64_sqrt(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* square root 128-bit */
+uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
+{
+    float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 4d2b053..eb8d663 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -76,7 +76,9 @@ DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
 DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
 DEF_HELPER_3(flogr, i32, env, i32, i64)
-DEF_HELPER_3(sqdbr, void, env, i32, i32)
+DEF_HELPER_2(sqeb, i64, env, i64)
+DEF_HELPER_2(sqdb, i64, env, i64)
+DEF_HELPER_3(sqxb, i64, env, i64, i64)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
 DEF_HELPER_4(unpk, void, env, i32, i64, i64)
 DEF_HELPER_4(tr, void, env, i32, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 74bc994..93fd3ca 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -459,6 +459,13 @@
 /* SHIFT RIGHT DOUBLE LOGICAL */
     C(0x8c00, SRDL,    RS_a,  Z,   r1_D32, sh64, new, r1_D32, srl, 0)
 
+/* SQUARE ROOT */
+    C(0xb314, SQEBR,   RRE,   Z,   0, e2, new, e1, sqeb, 0)
+    C(0xb315, SQDBR,   RRE,   Z,   0, f2_o, f1, 0, sqdb, 0)
+    C(0xb316, SQXBR,   RRE,   Z,   0, x2_o, x1, 0, sqxb, 0)
+    C(0xed14, SQEB,    RXE,   Z,   0, m2_32u, new, e1, sqeb, 0)
+    C(0xed15, SQDB,    RXE,   Z,   0, m2_64, f1, 0, sqdb, 0)
+
 /* STORE */
     C(0x5000, ST,      RX_a,  Z,   r1_o, a2, 0, 0, st32, 0)
     C(0xe350, STY,     RXY_a, LD,  r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b6043d6..dd77998 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,9 +1385,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     tcg_temp_free_i32(tmp32_2);
 
     switch (op) {
-    case 0x15: /* SQBDR       R1,R2             [RRE] */
-        FP_HELPER(sqdbr);
-        break;
     case 0x74: /* LZER        R1                [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         gen_helper_lzer(cpu_env, tmp32_1);
@@ -2936,6 +2933,25 @@ static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sqeb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sqdb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
 {
commit 5d7fd045cafeac1831c1999cb9e1251b7906c6b2
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 15:58:27 2012 -0700

    target-s390: Convert FP LOAD COMPLIMENT, NEGATIVE, POSITIVE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 7638a0d..b46dd02 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -360,71 +360,6 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     return ret;
 }
 
-/* absolute value of 32-bit float */
-uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    float32 v1;
-    float32 v2 = env->fregs[f2].d;
-
-    v1 = float32_abs(v2);
-    env->fregs[f1].d = v1;
-    return set_cc_nz_f32(v1);
-}
-
-/* absolute value of 64-bit float */
-uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    float64 v1;
-    float64 v2 = env->fregs[f2].d;
-
-    v1 = float64_abs(v2);
-    env->fregs[f1].d = v1;
-    return set_cc_nz_f64(v1);
-}
-
-/* absolute value of 128-bit float */
-uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    v1.q = float128_abs(v2.q);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-    return set_cc_nz_f128(v1.q);
-}
-
-/* load complement of 32-bit float */
-uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load complement of 64-bit float */
-uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
-
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load complement of 128-bit float */
-uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x1, x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    x1.q = float128_chs(x2.q);
-    env->fregs[f1].ll = x1.ll.upper;
-    env->fregs[f1 + 2].ll = x1.ll.lower;
-    return set_cc_nz_f128(x1.q);
-}
-
 /* 32-bit FP compare */
 uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 71dcdb5..4d2b053 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -56,12 +56,6 @@ DEF_HELPER_2(lxdb, i64, env, i64)
 DEF_HELPER_2(lxeb, i64, env, i64)
 DEF_HELPER_2(ledb, i64, env, i64)
 DEF_HELPER_3(lexb, i64, env, i64, i64)
-DEF_HELPER_3(lpebr, i32, env, i32, i32)
-DEF_HELPER_3(lpdbr, i32, env, i32, i32)
-DEF_HELPER_3(lpxbr, i32, env, i32, i32)
-DEF_HELPER_3(lcebr, i32, env, i32, i32)
-DEF_HELPER_3(lcdbr, i32, env, i32, i32)
-DEF_HELPER_3(lcxbr, i32, env, i32, i32)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 54b75e1..74bc994 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -266,6 +266,9 @@
     C(0x1300, LCR,     RR_a,  Z,   0, r2, new, r1_32, neg, neg32)
     C(0xb903, LCGR,    RRE,   Z,   0, r2, r1, 0, neg, neg64)
     C(0xb913, LCGFR,   RRE,   Z,   0, r2_32s, r1, 0, neg, neg64)
+    C(0xb303, LCEBR,   RRE,   Z,   0, e2, new, e1, negf32, f32)
+    C(0xb313, LCDBR,   RRE,   Z,   0, f2_o, f1, 0, negf64, f64)
+    C(0xb343, LCXBR,   RRE,   Z,   0, x2_o, x1, 0, negf128, f128)
 /* LOAD HALFWORD */
     C(0xb927, LHR,     RRE,   EI,  0, r2_16s, 0, r1_32, mov2, 0)
     C(0xb907, LGHR,    RRE,   EI,  0, r2_16s, 0, r1, mov2, 0)
@@ -310,10 +313,16 @@
     C(0x1100, LNR,     RR_a,  Z,   0, r2_32s, new, r1_32, nabs, nabs32)
     C(0xb901, LNGR,    RRE,   Z,   0, r2, r1, 0, nabs, nabs64)
     C(0xb911, LNGFR,   RRE,   Z,   0, r2_32s, r1, 0, nabs, nabs64)
+    C(0xb301, LNEBR,   RRE,   Z,   0, e2, new, e1, nabsf32, f32)
+    C(0xb311, LNDBR,   RRE,   Z,   0, f2_o, f1, 0, nabsf64, f64)
+    C(0xb341, LNXBR,   RRE,   Z,   0, x2_o, x1, 0, nabsf128, f128)
 /* LOAD POSITIVE */
     C(0x1000, LPR,     RR_a,  Z,   0, r2_32s, new, r1_32, abs, abs32)
     C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
     C(0xb910, LPGFR,   RRE,   Z,   0, r2_32s, r1, 0, abs, abs64)
+    C(0xb300, LPEBR,   RRE,   Z,   0, e2, new, e1, absf32, f32)
+    C(0xb310, LPDBR,   RRE,   Z,   0, f2_o, f1, 0, absf64, f64)
+    C(0xb340, LPXBR,   RRE,   Z,   0, x2_o, x1, 0, absf128, f128)
 /* LOAD REVERSED */
     C(0xb91f, LRVR,    RRE,   Z,   0, r2_32u, new, r1_32, rev32, 0)
     C(0xb90f, LRVGR,   RRE,   Z,   0, r2_o, r1, 0, rev64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6593d88..b6043d6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1385,35 +1385,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     tcg_temp_free_i32(tmp32_2);
 
     switch (op) {
-    case 0x0: /* LPEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpebr);
-        break;
-    case 0x3: /* LCEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcebr);
-        break;
-    case 0x10: /* LPDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpdbr);
-        break;
-    case 0x13: /* LCDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcdbr);
-        break;
     case 0x15: /* SQBDR       R1,R2             [RRE] */
         FP_HELPER(sqdbr);
         break;
-    case 0x40: /* LPXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lpxbr);
-        break;
-    case 0x43: /* LCXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(lcxbr);
-        break;
-    case 0x65: /* LXR         R1,R2             [RRE] */
-        tmp = load_freg(r2);
-        store_freg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        tmp = load_freg(r2 + 2);
-        store_freg(r1 + 2, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x74: /* LZER        R1                [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         gen_helper_lzer(cpu_env, tmp32_1);
@@ -1997,6 +1971,25 @@ static ExitStatus op_abs(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_add(DisasContext *s, DisasOps *o)
 {
     tcg_gen_add_i64(o->out, o->in1, o->in2);
@@ -2799,6 +2792,25 @@ static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_nc(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
@@ -2815,6 +2827,25 @@ static ExitStatus op_neg(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
+    return NO_EXIT;
+}
+
+static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
+    tcg_gen_mov_i64(o->out2, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_oc(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
commit 31aa97d1ed87853835a2df4ea9db1566f85c57a2
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 12:40:09 2012 -0700

    target-s390: Convert TEST DATA CLASS
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 8f2c504..7638a0d 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -620,13 +620,12 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
 }
 
 /* test data class 32-bit */
-uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
 {
-    float32 v1 = env->fregs[f1].l.upper;
+    float32 v1 = f1;
     int neg = float32_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -636,19 +635,16 @@ uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
         /* assume normalized number */
         cc = 1;
     }
-
     /* FIXME: denormalized? */
     return cc;
 }
 
 /* test data class 64-bit */
-uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
 {
-    float64 v1 = env->fregs[f1].d;
     int neg = float64_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -663,20 +659,16 @@ uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
 {
-    CPU_QuadU v1;
+    float128 v1 = make_float128(ah, al);
+    int neg = float128_is_neg(v1);
     uint32_t cc = 0;
-    int neg;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
 
-    neg = float128_is_neg(v1.q);
-    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
-        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
-        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
+    if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
+        (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
+        (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
+        (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
         cc = 1;
     } else if (m2 & (1 << (9-neg))) {
         /* assume normalized number */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 2115849..71dcdb5 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -78,9 +78,9 @@ DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
 DEF_HELPER_4(madb, i64, env, i64, i64, i64)
 DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
 DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
+DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
+DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
 DEF_HELPER_3(flogr, i32, env, i32, i64)
 DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a924a93..54b75e1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -531,6 +531,11 @@
 /* SUPERVISOR CALL */
     C(0x0a00, SVC,     I,     Z,   0, 0, 0, 0, svc, 0)
 
+/* TEST DATA CLASS */
+    C(0xed10, TCEB,    RXE,   Z,   e1, a2, 0, 0, tceb, 0)
+    C(0xed11, TCDB,    RXE,   Z,   f1_o, a2, 0, 0, tcdb, 0)
+    C(0xed12, TCXB,    RXE,   Z,   x1_o, a2, 0, 0, tcxb, 0)
+
 /* TEST UNDER MASK */
     C(0x9100, TM,      SI,    Z,   m1_8u, i2_8u, 0, 0, 0, tm32)
     C(0xeb51, TMY,     SIY,   LD,  m1_8u, i2_8u, 0, 0, 0, tm32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index faf979f..6593d88 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -987,38 +987,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int x2, int b2, int d2, int r1b)
-{
-    TCGv_i32 tmp_r1;
-    TCGv_i64 addr;
-    addr = get_address(s, x2, b2, d2);
-    tmp_r1 = tcg_const_i32(r1);
-    switch (op) {
-    case 0x10: /* TCEB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x11: /* TCDB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x12: /* TCXB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    default:
-        LOG_DISAS("illegal ed operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        return;
-    }
-    tcg_temp_free_i32(tmp_r1);
-    tcg_temp_free_i64(addr);
-}
-
 static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
                      uint32_t insn)
 {
@@ -1602,7 +1570,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3, d2, x2, b2, r1b;
+    int op, r1, r2, r3;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -1628,17 +1596,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(env, s, op, r1, r2);
         break;
-    case 0xed:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        x2 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = (short)((insn >> 16) & 0xfff);
-        r1b = (insn >> 12) & 0xf;
-        disas_ed(env, s, op, r1, x2, b2, d2, r1b);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -3224,6 +3181,27 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     return EXIT_NORETURN;
 }
 
+static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tceb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcdb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
 {
commit 722bfec331504bf873a5e4ec4f232c4ed116dda2
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 12:30:12 2012 -0700

    target-s390: Convert MULTIPLY AND ADD, SUBTRACT
    
    Use the new float*_muladd interface to softfloat.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 9805026..8f2c504 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -581,47 +581,42 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
     env->fregs[f1 + 1].ll = x.ll.lower;
 }
 
-/* 64-bit FP multiply and add RM */
-void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
+/* 32-bit FP multiply and add */
+uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
+                      uint64_t f2, uint64_t f3)
 {
-    CPU_DoubleU v2;
-
-    HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
-    v2.ll = cpu_ldq_data(env, a2);
-    env->fregs[f1].d = float64_add(env->fregs[f1].d,
-                                   float64_mul(v2.d, env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   &env->fpu_status);
+    float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 64-bit FP multiply and add RR */
-void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 64-bit FP multiply and add */
+uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
+                      uint64_t f2, uint64_t f3)
 {
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
-    env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
-                                               env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   env->fregs[f1].d, &env->fpu_status);
+    float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 64-bit FP multiply and subtract RR */
-void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 32-bit FP multiply and subtract */
+uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
+                      uint64_t f2, uint64_t f3)
 {
-    HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
-    env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
-                                               env->fregs[f3].d,
-                                               &env->fpu_status),
-                                   env->fregs[f1].d, &env->fpu_status);
+    float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
+                                 &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 32-bit FP multiply and add RR */
-void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
+/* 64-bit FP multiply and subtract */
+uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
+                      uint64_t f2, uint64_t f3)
 {
-    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
-                                         float32_mul(env->fregs[f2].l.upper,
-                                                     env->fregs[f3].l.upper,
-                                                     &env->fpu_status),
-                                         &env->fpu_status);
+    float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
+                                 &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* test data class 32-bit */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 36316c3..2115849 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -74,10 +74,10 @@ DEF_HELPER_2(lzxr, void, env, i32)
 DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(madb, void, env, i32, i64, i32)
-DEF_HELPER_4(maebr, void, env, i32, i32, i32)
-DEF_HELPER_4(madbr, void, env, i32, i32, i32)
-DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
+DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
+DEF_HELPER_4(madb, i64, env, i64, i64, i64)
+DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
+DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
 DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
 DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 89f71ac..a924a93 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -391,6 +391,17 @@
     C(0xc201, MSFI,    RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
     C(0xc200, MSGFI,   RIL_a, GIE, r1_o, i2, r1, 0, mul, 0)
 
+/* MULTIPLY AND ADD */
+    C(0xb30e, MAEBR,   RRD,   Z,   e1, e2, new, e1, maeb, 0)
+    C(0xb31e, MADBR,   RRD,   Z,   f1_o, f2_o, f1, 0, madb, 0)
+    C(0xed0e, MAEB,    RXF,   Z,   e1, m2_32u, new, e1, maeb, 0)
+    C(0xed1e, MADB,    RXF,   Z,   f1_o, m2_64, f1, 0, madb, 0)
+/* MULTIPLY AND SUBTRACT */
+    C(0xb30f, MSEBR,   RRD,   Z,   e1, e2, new, e1, mseb, 0)
+    C(0xb31f, MSDBR,   RRD,   Z,   f1_o, f2_o, f1, 0, msdb, 0)
+    C(0xed0f, MSEB,    RXF,   Z,   e1, m2_32u, new, e1, mseb, 0)
+    C(0xed1f, MSDB,    RXF,   Z,   f1_o, m2_64, f1, 0, msdb, 0)
+
 /* OR */
     C(0x1600, OR,      RR_a,  Z,   r1, r2, new, r1_32, or, nz32)
     C(0xb9f6, ORK,     RRF_a, DO,  r2, r3, new, r1_32, or, nz32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 10bf3a0..faf979f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -990,7 +990,7 @@ static void free_compare(DisasCompare *c)
 static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int x2, int b2, int d2, int r1b)
 {
-    TCGv_i32 tmp_r1, tmp32;
+    TCGv_i32 tmp_r1;
     TCGv_i64 addr;
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
@@ -1010,13 +1010,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
-    case 0x1e: /* MADB  R1,R3,D2(X2,B2) [RXF] */
-        /* for RXF insns, r1 is R3 and r1b is R1 */
-        tmp32 = tcg_const_i32(r1b);
-        potential_page_fault(s);
-        gen_helper_madb(cpu_env, tmp32, addr, tmp_r1);
-        tcg_temp_free_i32(tmp32);
-        break;
     default:
         LOG_DISAS("illegal ed operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -1439,30 +1432,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x15: /* SQBDR       R1,R2             [RRE] */
         FP_HELPER(sqdbr);
         break;
-    case 0xe: /* MAEBR  R1,R3,R2 [RRF] */
-    case 0x1e: /* MADBR R1,R3,R2 [RRF] */
-    case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
-        /* for RRF insns, m3 is R1, r1 is R3, and r2 is R2 */
-        tmp32_1 = tcg_const_i32(m3);
-        tmp32_2 = tcg_const_i32(r2);
-        tmp32_3 = tcg_const_i32(r1);
-        switch (op) {
-        case 0xe:
-            gen_helper_maebr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        case 0x1e:
-            gen_helper_madbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        case 0x1f:
-            gen_helper_msdbr(cpu_env, tmp32_1, tmp32_3, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0x40: /* LPXBR       R1,R2             [RRE] */
         FP_HELPER_CC(lpxbr);
         break;
@@ -2837,6 +2806,36 @@ static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+    gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
+    tcg_temp_free_i64(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_madb(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
+    gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
+    tcg_temp_free_i64(r3);
+    return NO_EXIT;
+}
+
+static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
+    return NO_EXIT;
+}
+
 static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
 {
     gen_helper_nabs_i64(o->out, o->in2);
commit 83b00736f3d8033861c27b80c9d3fc7c44bbec99
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 12:02:38 2012 -0700

    target-s390: Convert FP MULTIPLY
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b0c18ee..9805026 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -266,27 +266,50 @@ uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return RET128(ret);
 }
 
-/* 64-bit FP multiplication RR */
-void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP multiplication */
+uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
+    float32 ret = float32_mul(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 128-bit FP multiplication RR */
-void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP multiplication */
+uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
+    float64 ret = float64_mul(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
 
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
+/* 64/32-bit FP multiplication */
+uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
+{
+    float64 ret = float32_to_float64(f2, &env->fpu_status);
+    ret = float64_mul(f1, ret, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
+
+/* 128-bit FP multiplication */
+uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                     uint64_t bh, uint64_t bl)
+{
+    float128 ret = float128_mul(make_float128(ah, al),
+                                make_float128(bh, bl),
+                                &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
+}
+
+/* 128/64-bit FP multiplication */
+uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                      uint64_t f2)
+{
+    float128 ret = float64_to_float128(f2, &env->fpu_status);
+    ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
 
 /* convert 32-bit float to 64-bit float */
@@ -402,18 +425,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
     return set_cc_nz_f128(x1.q);
 }
 
-/* 32-bit FP multiplication RM */
-void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
-}
-
 /* 32-bit FP compare */
 uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
@@ -441,18 +452,6 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return float_comp_to_cc(env, cmp);
 }
 
-/* 64-bit FP multiplication RM */
-void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
-}
-
 static void set_round_mode(CPUS390XState *env, int m3)
 {
     switch (m3) {
@@ -582,14 +581,6 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
     env->fregs[f1 + 1].ll = x.ll.lower;
 }
 
-/* 32-bit FP multiplication RR */
-void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-}
-
 /* 64-bit FP multiply and add RM */
 void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index bb094c0..36316c3 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -45,8 +45,11 @@ DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
 DEF_HELPER_3(deb, i64, env, i64, i64)
 DEF_HELPER_3(ddb, i64, env, i64, i64)
 DEF_HELPER_5(dxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(mdbr, void, env, i32, i32)
-DEF_HELPER_3(mxbr, void, env, i32, i32)
+DEF_HELPER_3(meeb, i64, env, i64, i64)
+DEF_HELPER_3(mdeb, i64, env, i64, i64)
+DEF_HELPER_3(mdb, i64, env, i64, i64)
+DEF_HELPER_5(mxb, i64, env, i64, i64, i64, i64)
+DEF_HELPER_4(mxdb, i64, env, i64, i64, i64)
 DEF_HELPER_2(ldeb, i64, env, i64)
 DEF_HELPER_3(ldxb, i64, env, i64, i64)
 DEF_HELPER_2(lxdb, i64, env, i64)
@@ -59,8 +62,6 @@ DEF_HELPER_3(lpxbr, i32, env, i32, i32)
 DEF_HELPER_3(lcebr, i32, env, i32, i32)
 DEF_HELPER_3(lcdbr, i32, env, i32, i32)
 DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(mdb, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
@@ -73,7 +74,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
 DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(meebr, void, env, i32, i32)
 DEF_HELPER_4(madb, void, env, i32, i64, i32)
 DEF_HELPER_4(maebr, void, env, i32, i32, i32)
 DEF_HELPER_4(madbr, void, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 14dcd12..89f71ac 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -359,6 +359,15 @@
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
     C(0x5c00, M,       RX_a,  Z,   r1p1_32s, m2_32s, new, r1_D32, mul, 0)
     C(0xe35c, MFY,     RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
+    C(0xb317, MEEBR,   RRE,   Z,   e1, e2, new, e1, meeb, 0)
+    C(0xb31c, MDBR,    RRE,   Z,   f1_o, f2_o, f1, 0, mdb, 0)
+    C(0xb34c, MXBR,    RRE,   Z,   0, x2_o, x1, 0, mxb, 0)
+    C(0xb30c, MDEBR,   RRE,   Z,   f1_o, e2, f1, 0, mdeb, 0)
+    C(0xb307, MXDBR,   RRE,   Z,   0, f2_o, x1, 0, mxdb, 0)
+    C(0xed17, MEEB,    RXE,   Z,   e1, m2_32u, new, e1, meeb, 0)
+    C(0xed1c, MDB,     RXE,   Z,   f1_o, m2_64, f1, 0, mdb, 0)
+    C(0xed0c, MDEB,    RXE,   Z,   f1_o, m2_32u, f1, 0, mdeb, 0)
+    C(0xed07, MXDB,    RXE,   Z,   0, m2_64, x1, 0, mxdb, 0)
 /* MULTIPLY HALFWORD */
     C(0x4c00, MH,      RX_a,  Z,   r1_o, m2_16s, new, r1_32, mul, 0)
     C(0xe37c, MHY,     RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c00992d..10bf3a0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -991,7 +991,7 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int x2, int b2, int d2, int r1b)
 {
     TCGv_i32 tmp_r1, tmp32;
-    TCGv_i64 addr, tmp;
+    TCGv_i64 addr;
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
     switch (op) {
@@ -1010,19 +1010,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
         set_cc_static(s);
         break;
-    case 0x17: /* MEEB   R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_meeb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0x1c: /* MDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_mdb(cpu_env, tmp_r1, addr);
-        break;
     case 0x1e: /* MADB  R1,R3,D2(X2,B2) [RXF] */
         /* for RXF insns, r1 is R3 and r1b is R1 */
         tmp32 = tcg_const_i32(r1b);
@@ -1452,12 +1439,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x15: /* SQBDR       R1,R2             [RRE] */
         FP_HELPER(sqdbr);
         break;
-    case 0x17: /* MEEBR       R1,R2             [RRE] */
-        FP_HELPER(meebr);
-        break;
-    case 0x1c: /* MDBR        R1,R2             [RRE] */
-        FP_HELPER(mdbr);
-        break;
     case 0xe: /* MAEBR  R1,R3,R2 [RRF] */
     case 0x1e: /* MADBR R1,R3,R2 [RRF] */
     case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
@@ -1488,9 +1469,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x43: /* LCXBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcxbr);
         break;
-    case 0x4c: /* MXBR        R1,R2             [RRE] */
-        FP_HELPER(mxbr);
-        break;
     case 0x65: /* LXR         R1,R2             [RRE] */
         tmp = load_freg(r2);
         store_freg(r1, tmp);
@@ -2827,6 +2805,38 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
 {
     gen_helper_nabs_i64(o->out, o->in2);
commit f08a5c311d3047f2cafe72e3e377674e7f8acdcb
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Sep 7 11:41:12 2012 -0700

    target-s390: Convert FP DIVIDE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index ea61936..b0c18ee 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -239,28 +239,31 @@ uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return RET128(ret);
 }
 
-/* 32-bit FP division RR */
-void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP division */
+uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
+    float32 ret = float32_div(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 128-bit FP division RR */
-void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP division */
+uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
+    float64 ret = float64_div(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
 
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_div(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
+/* 128-bit FP division */
+uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                     uint64_t bh, uint64_t bl)
+{
+    float128 ret = float128_div(make_float128(ah, al),
+                                make_float128(bh, bl),
+                                &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
 
 /* 64-bit FP multiplication RR */
@@ -399,18 +402,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
     return set_cc_nz_f128(x1.q);
 }
 
-/* 32-bit FP division RM */
-void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
-}
-
 /* 32-bit FP multiplication RM */
 void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
@@ -462,18 +453,6 @@ void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
     env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
 }
 
-/* 64-bit FP division RM */
-void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
-}
-
 static void set_round_mode(CPUS390XState *env, int m3)
 {
     switch (m3) {
@@ -611,13 +590,6 @@ void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
                                          &env->fpu_status);
 }
 
-/* 64-bit FP division RR */
-void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-}
-
 /* 64-bit FP multiply and add RM */
 void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 4fca4c5..bb094c0 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -42,8 +42,9 @@ DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
 DEF_HELPER_3(seb, i64, env, i64, i64)
 DEF_HELPER_3(sdb, i64, env, i64, i64)
 DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(debr, void, env, i32, i32)
-DEF_HELPER_3(dxbr, void, env, i32, i32)
+DEF_HELPER_3(deb, i64, env, i64, i64)
+DEF_HELPER_3(ddb, i64, env, i64, i64)
+DEF_HELPER_5(dxb, i64, env, i64, i64, i64, i64)
 DEF_HELPER_3(mdbr, void, env, i32, i32)
 DEF_HELPER_3(mxbr, void, env, i32, i32)
 DEF_HELPER_2(ldeb, i64, env, i64)
@@ -58,10 +59,8 @@ DEF_HELPER_3(lpxbr, i32, env, i32, i32)
 DEF_HELPER_3(lcebr, i32, env, i32, i32)
 DEF_HELPER_3(lcdbr, i32, env, i32, i32)
 DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(deb, void, env, i32, i32)
 DEF_HELPER_3(meeb, void, env, i32, i32)
 DEF_HELPER_3(mdb, void, env, i32, i64)
-DEF_HELPER_3(ddb, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
 DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
@@ -75,7 +74,6 @@ DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
 DEF_HELPER_3(meebr, void, env, i32, i32)
-DEF_HELPER_3(ddbr, void, env, i32, i32)
 DEF_HELPER_4(madb, void, env, i32, i64, i32)
 DEF_HELPER_4(maebr, void, env, i32, i32, i32)
 DEF_HELPER_4(madbr, void, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index fdfcffc..14dcd12 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -167,6 +167,11 @@
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
     C(0x5d00, D,       RX_a,  Z,   r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
+    C(0xb30d, DEBR,    RRE,   Z,   e1, e2, new, e1, deb, 0)
+    C(0xb31d, DDBR,    RRE,   Z,   f1_o, f2_o, f1, 0, ddb, 0)
+    C(0xb34d, DXBR,    RRE,   Z,   0, x2_o, x1, 0, dxb, 0)
+    C(0xed0d, DEB,     RXE,   Z,   e1, m2_32u, new, e1, deb, 0)
+    C(0xed1d, DDB,     RXE,   Z,   f1_o, m2_64, f1, 0, ddb, 0)
 /* DIVIDE LOGICAL */
     C(0xb997, DLR,     RRE,   Z,   r1_D32, r2_32u, new_P, r1_P32, divu32, 0)
     C(0xe397, DL,      RXY_a, Z,   r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2b3b0fc..c00992d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -995,15 +995,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
     switch (op) {
-    case 0xd: /* DEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_deb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
     case 0x10: /* TCEB   R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
         gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
@@ -1032,10 +1023,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         potential_page_fault(s);
         gen_helper_mdb(cpu_env, tmp_r1, addr);
         break;
-    case 0x1d: /* DDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_ddb(cpu_env, tmp_r1, addr);
-        break;
     case 0x1e: /* MADB  R1,R3,D2(X2,B2) [RXF] */
         /* for RXF insns, r1 is R3 and r1b is R1 */
         tmp32 = tcg_const_i32(r1b);
@@ -1456,9 +1443,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x3: /* LCEBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcebr);
         break;
-    case 0xd: /* DEBR        R1,R2             [RRE] */
-        FP_HELPER(debr);
-        break;
     case 0x10: /* LPDBR       R1,R2             [RRE] */
         FP_HELPER_CC(lpdbr);
         break;
@@ -1474,9 +1458,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x1c: /* MDBR        R1,R2             [RRE] */
         FP_HELPER(mdbr);
         break;
-    case 0x1d: /* DDBR        R1,R2             [RRE] */
-        FP_HELPER(ddbr);
-        break;
     case 0xe: /* MAEBR  R1,R3,R2 [RRF] */
     case 0x1e: /* MADBR R1,R3,R2 [RRF] */
     case 0x1f: /* MSDBR R1,R3,R2 [RRF] */
@@ -1510,9 +1491,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x4c: /* MXBR        R1,R2             [RRE] */
         FP_HELPER(mxbr);
         break;
-    case 0x4d: /* DXBR        R1,R2             [RRE] */
-        FP_HELPER(dxbr);
-        break;
     case 0x65: /* LXR         R1,R2             [RRE] */
         tmp = load_freg(r2);
         store_freg(r1, tmp);
@@ -2428,6 +2406,25 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_deb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
 {
     tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
commit 1a800a2dcee541dee4f51aed5110ca9d5811c5e8
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 11:05:03 2012 -0700

    target-s390: Convert FP SUBTRACT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 92458ce..ea61936 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -212,27 +212,31 @@ uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return RET128(ret);
 }
 
-/* 32-bit FP subtraction RR */
-uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP subtraction */
+uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
-               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
+    float32 ret = float32_sub(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 64-bit FP subtraction RR */
-uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP subtraction */
+uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-    HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
-               __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
+    float64 ret = float64_sub(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
 
-    return set_cc_nz_f64(env->fregs[f1].d);
+/* 128-bit FP subtraction */
+uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                     uint64_t bh, uint64_t bl)
+{
+    float128 ret = float128_sub(make_float128(ah, al),
+                                make_float128(bh, bl),
+                                &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
 
 /* 32-bit FP division RR */
@@ -446,27 +450,6 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
     return float_comp_to_cc(env, cmp);
 }
 
-/* 32-bit FP subtraction RM */
-void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
-}
-
-/* 64-bit FP subtraction RM */
-uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
-    return set_cc_nz_f64(v1);
-}
-
 /* 64-bit FP multiplication RM */
 void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
 {
@@ -620,23 +603,6 @@ void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
     env->fregs[f1 + 1].ll = x.ll.lower;
 }
 
-/* 128-bit FP subtraction RR */
-uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-    return set_cc_nz_f128(res.q);
-}
-
 /* 32-bit FP multiplication RR */
 void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 2e64433..4fca4c5 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -39,8 +39,9 @@ DEF_HELPER_3(cxgbr, void, env, i32, s64)
 DEF_HELPER_3(aeb, i64, env, i64, i64)
 DEF_HELPER_3(adb, i64, env, i64, i64)
 DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
-DEF_HELPER_3(sebr, i32, env, i32, i32)
-DEF_HELPER_3(sdbr, i32, env, i32, i32)
+DEF_HELPER_3(seb, i64, env, i64, i64)
+DEF_HELPER_3(sdb, i64, env, i64, i64)
+DEF_HELPER_5(sxb, i64, env, i64, i64, i64, i64)
 DEF_HELPER_3(debr, void, env, i32, i32)
 DEF_HELPER_3(dxbr, void, env, i32, i32)
 DEF_HELPER_3(mdbr, void, env, i32, i32)
@@ -59,8 +60,6 @@ DEF_HELPER_3(lcdbr, i32, env, i32, i32)
 DEF_HELPER_3(lcxbr, i32, env, i32, i32)
 DEF_HELPER_3(deb, void, env, i32, i32)
 DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(seb, void, env, i32, i32)
-DEF_HELPER_3(sdb, i32, env, i32, i64)
 DEF_HELPER_3(mdb, void, env, i32, i64)
 DEF_HELPER_3(ddb, void, env, i32, i64)
 DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
@@ -75,7 +74,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
 DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(sxbr, i32, env, i32, i32)
 DEF_HELPER_3(meebr, void, env, i32, i32)
 DEF_HELPER_3(ddbr, void, env, i32, i32)
 DEF_HELPER_4(madb, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f1c37e8..fdfcffc 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -476,6 +476,11 @@
     C(0xb9e9, SGRK,    RRF_a, DO,  r2, r3, r1, 0, sub, subs64)
     C(0xe309, SG,      RXY_a, Z,   r1, m2_64, r1, 0, sub, subs64)
     C(0xe319, SGF,     RXY_a, Z,   r1, m2_32s, r1, 0, sub, subs64)
+    C(0xb30b, SEBR,    RRE,   Z,   e1, e2, new, e1, seb, f32)
+    C(0xb31b, SDBR,    RRE,   Z,   f1_o, f2_o, f1, 0, sdb, f64)
+    C(0xb34b, SXBR,    RRE,   Z,   0, x2_o, x1, 0, sxb, f128)
+    C(0xed0b, SEB,     RXE,   Z,   e1, m2_32u, new, e1, seb, f32)
+    C(0xed1b, SDB,     RXE,   Z,   f1_o, m2_64, f1, 0, sdb, f64)
 /* SUBTRACT HALFWORD */
     C(0x4b00, SH,      RX_a,  Z,   r1, m2_16s, new, r1_32, sub, subs32)
     C(0xe37b, SHY,     RXY_a, LD,  r1, m2_16s, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f62e4f0..2b3b0fc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -556,11 +556,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
-{
-    gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
-}
-
 /* CC value is in env->cc_op */
 static inline void set_cc_static(DisasContext *s)
 {
@@ -1000,19 +995,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
     switch (op) {
-    case 0xb: /* SEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_seb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-
-        tmp32 = load_freg32(r1);
-        gen_set_cc_nz_f32(s, tmp32);
-        tcg_temp_free_i32(tmp32);
-        break;
     case 0xd: /* DEB    R1,D2(X2,B2)       [RXE] */
         tmp = tcg_temp_new_i64();
         tmp32 = tcg_temp_new_i32();
@@ -1046,11 +1028,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
         break;
-    case 0x1b: /* SDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
     case 0x1c: /* MDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
         gen_helper_mdb(cpu_env, tmp_r1, addr);
@@ -1479,9 +1456,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x3: /* LCEBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcebr);
         break;
-    case 0xb: /* SEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sebr);
-        break;
     case 0xd: /* DEBR        R1,R2             [RRE] */
         FP_HELPER(debr);
         break;
@@ -1497,9 +1471,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x17: /* MEEBR       R1,R2             [RRE] */
         FP_HELPER(meebr);
         break;
-    case 0x1b: /* SDBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sdbr);
-        break;
     case 0x1c: /* MDBR        R1,R2             [RRE] */
         FP_HELPER(mdbr);
         break;
@@ -1536,9 +1507,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x43: /* LCXBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcxbr);
         break;
-    case 0x4b: /* SXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(sxbr);
-        break;
     case 0x4c: /* MXBR        R1,R2             [RRE] */
         FP_HELPER(mxbr);
         break;
@@ -2955,6 +2923,25 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_seb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
 {
commit 587626f8da5e2ee15bbf9f636c78991d6c953387
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 10:48:20 2012 -0700

    target-s390: Convert FP ADD, COMPARE, LOAD TEST/ROUND/LENGTHENED
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index be4202a..f1038be 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -505,18 +505,15 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
         r =  cc_calc_sla_64(src, dst);
         break;
 
-    case CC_OP_LTGT_F32:
-        r = set_cc_f32(env, src, dst);
-        break;
-    case CC_OP_LTGT_F64:
-        r = set_cc_f64(env, src, dst);
-        break;
     case CC_OP_NZ_F32:
         r = set_cc_nz_f32(dst);
         break;
     case CC_OP_NZ_F64:
         r = set_cc_nz_f64(dst);
         break;
+    case CC_OP_NZ_F128:
+        r = set_cc_nz_f128(make_float128(src, dst));
+        break;
 
     default:
         cpu_abort(env, "Unknown CC operation: %s\n", cc_name(cc_op));
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index b8e9037..f1d4dc6 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -471,11 +471,9 @@ enum cc_op {
     CC_OP_TM_32,                /* test under mask (32bit) */
     CC_OP_TM_64,                /* test under mask (64bit) */
 
-    CC_OP_LTGT_F32,             /* FP compare (32bit) */
-    CC_OP_LTGT_F64,             /* FP compare (64bit) */
-
     CC_OP_NZ_F32,               /* FP dst != 0 (32bit) */
     CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
+    CC_OP_NZ_F128,              /* FP dst != 0 (128bit) */
 
     CC_OP_ICM,                  /* insert characters under mask */
     CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
@@ -517,10 +515,9 @@ static const char *cc_names[] = {
     [CC_OP_COMP_64]   = "CC_OP_COMP_64",
     [CC_OP_TM_32]     = "CC_OP_TM_32",
     [CC_OP_TM_64]     = "CC_OP_TM_64",
-    [CC_OP_LTGT_F32]  = "CC_OP_LTGT_F32",
-    [CC_OP_LTGT_F64]  = "CC_OP_LTGT_F64",
     [CC_OP_NZ_F32]    = "CC_OP_NZ_F32",
     [CC_OP_NZ_F64]    = "CC_OP_NZ_F64",
+    [CC_OP_NZ_F128]   = "CC_OP_NZ_F128",
     [CC_OP_ICM]       = "CC_OP_ICM",
     [CC_OP_SLA_32]    = "CC_OP_SLA_32",
     [CC_OP_SLA_64]    = "CC_OP_SLA_64",
@@ -926,10 +923,9 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
 }
 
 /* fpu_helper.c */
-uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2);
-uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2);
 uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
+uint32_t set_cc_nz_f128(float128 v);
 
 /* misc_helper.c */
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 173f820..92458ce 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -32,6 +32,52 @@
 #define HELPER_LOG(x...)
 #endif
 
+#define RET128(F) (env->retxl = F.low, F.high)
+
+#define convert_bit(mask, from, to) \
+    (to < from                      \
+     ? (mask / (from / to)) & to    \
+     : (mask & from) * (to / from))
+
+static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
+{
+    /* Install the DXC code.  */
+    env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
+    /* Trap.  */
+    runtime_exception(env, PGM_DATA, retaddr);
+}
+
+/* Should be called after any operation that may raise IEEE exceptions.  */
+static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
+{
+    unsigned s390_exc, qemu_exc;
+
+    /* Get the exceptions raised by the current operation.  Reset the
+       fpu_status contents so that the next operation has a clean slate.  */
+    qemu_exc = env->fpu_status.float_exception_flags;
+    if (qemu_exc == 0) {
+        return;
+    }
+    env->fpu_status.float_exception_flags = 0;
+
+    /* Convert softfloat exception bits to s390 exception bits.  */
+    s390_exc = 0;
+    s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
+    s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
+    s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
+    s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
+    s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
+
+    /* Install the exceptions that we raised.  */
+    env->fpc |= s390_exc << 16;
+
+    /* Send signals for enabled exceptions.  */
+    s390_exc &= env->fpc >> 24;
+    if (s390_exc) {
+        ieee_exception(env, s390_exc, retaddr);
+    }
+}
+
 static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
 {
     switch (float_compare) {
@@ -48,19 +94,6 @@ static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
     }
 }
 
-/* condition codes for binary FP ops */
-uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
-{
-    return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
-                                                       &env->fpu_status));
-}
-
-uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
-{
-    return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
-                                                       &env->fpu_status));
-}
-
 /* condition codes for unary FP ops */
 uint32_t set_cc_nz_f32(float32 v)
 {
@@ -88,7 +121,7 @@ uint32_t set_cc_nz_f64(float64 v)
     }
 }
 
-static uint32_t set_cc_nz_f128(float128 v)
+uint32_t set_cc_nz_f128(float128 v)
 {
     if (float128_is_any_nan(v)) {
         return 3;
@@ -152,27 +185,31 @@ void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
                env->fregs[f1].l.upper, f1);
 }
 
-/* 32-bit FP addition RR */
-uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP addition */
+uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
-                                         env->fregs[f2].l.upper,
-                                         &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
-               env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
-
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
+    float32 ret = float32_add(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
-/* 64-bit FP addition RR */
-uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 64-bit FP addition */
+uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
-                                   &env->fpu_status);
-    HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
-               env->fregs[f2].d, env->fregs[f1].d, f1);
+    float64 ret = float64_add(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
+}
 
-    return set_cc_nz_f64(env->fregs[f1].d);
+/* 128-bit FP addition */
+uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                     uint64_t bh, uint64_t bl)
+{
+    float128 ret = float128_add(make_float128(ah, al),
+                                make_float128(bh, bl),
+                                &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
 
 /* 32-bit FP subtraction RR */
@@ -246,50 +283,51 @@ void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 }
 
 /* convert 32-bit float to 64-bit float */
-void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
+uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 {
-    env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
-                                          &env->fpu_status);
+    float64 ret = float32_to_float64(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 128-bit float to 64-bit float */
-void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
-    CPU_QuadU x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
+    float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 64-bit float to 128-bit float */
-void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 {
-    CPU_QuadU res;
+    float128 ret = float64_to_float128(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
+}
 
-    res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
+/* convert 32-bit float to 128-bit float */
+uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
+{
+    float128 ret = float32_to_float128(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return RET128(ret);
 }
 
 /* convert 64-bit float to 32-bit float */
-void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
 {
-    float64 d2 = env->fregs[f2].d;
-
-    env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
+    float32 ret = float64_to_float32(f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* convert 128-bit float to 32-bit float */
-void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
 {
-    CPU_QuadU x2;
-
-    x2.ll.upper = env->fregs[f2].ll;
-    x2.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
-    HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
+    float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return ret;
 }
 
 /* absolute value of 32-bit float */
@@ -328,32 +366,6 @@ uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
     return set_cc_nz_f128(v1.q);
 }
 
-/* load and test 64-bit float */
-uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].d = env->fregs[f2].d;
-    return set_cc_nz_f64(env->fregs[f1].d);
-}
-
-/* load and test 32-bit float */
-uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    env->fregs[f1].l.upper = env->fregs[f2].l.upper;
-    return set_cc_nz_f32(env->fregs[f1].l.upper);
-}
-
-/* load and test 128-bit float */
-uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU x;
-
-    x.ll.upper = env->fregs[f2].ll;
-    x.ll.lower = env->fregs[f2 + 2].ll;
-    env->fregs[f1].ll = x.ll.upper;
-    env->fregs[f1 + 2].ll = x.ll.lower;
-    return set_cc_nz_f128(x.q);
-}
-
 /* load complement of 32-bit float */
 uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
@@ -383,18 +395,6 @@ uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
     return set_cc_nz_f128(x1.q);
 }
 
-/* 32-bit FP addition RM */
-void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    CPU_FloatU v2;
-
-    v2.l = val;
-    HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2.f);
-    env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
-}
-
 /* 32-bit FP division RM */
 void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
 {
@@ -419,66 +419,31 @@ void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
     env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
 }
 
-/* 32-bit FP compare RR */
-uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    float32 v1 = env->fregs[f1].l.upper;
-    float32 v2 = env->fregs[f2].l.upper;
-
-    HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
-               v1, f1, v2);
-    return set_cc_f32(env, v1, v2);
-}
-
-/* 64-bit FP compare RR */
-uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
+/* 32-bit FP compare */
+uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    float64 v1 = env->fregs[f1].d;
-    float64 v2 = env->fregs[f2].d;
-
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
-               v1, f1, v2);
-    return set_cc_f64(env, v1, v2);
-}
-
-/* 128-bit FP compare RR */
-uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-
-    return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
-                                                   &env->fpu_status));
+    int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return float_comp_to_cc(env, cmp);
 }
 
-/* 64-bit FP compare RM */
-uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+/* 64-bit FP compare */
+uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
 {
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
-               f1, v2.d);
-    return set_cc_f64(env, v1, v2.d);
+    int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return float_comp_to_cc(env, cmp);
 }
 
-/* 64-bit FP addition RM */
-uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
+/* 128-bit FP compare */
+uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                     uint64_t bh, uint64_t bl)
 {
-    float64 v1 = env->fregs[f1].d;
-    CPU_DoubleU v2;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
-               v1, f1, v2.d);
-    env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
-    return set_cc_nz_f64(v1);
+    int cmp = float128_compare_quiet(make_float128(ah, al),
+                                     make_float128(bh, bl),
+                                     &env->fpu_status);
+    handle_exceptions(env, GETPC());
+    return float_comp_to_cc(env, cmp);
 }
 
 /* 32-bit FP subtraction RM */
@@ -672,23 +637,6 @@ uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
     return set_cc_nz_f128(res.q);
 }
 
-/* 128-bit FP addition RR */
-uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
-{
-    CPU_QuadU v1;
-    CPU_QuadU v2;
-    CPU_QuadU res;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
-    v2.ll.upper = env->fregs[f2].ll;
-    v2.ll.lower = env->fregs[f2 + 2].ll;
-    res.q = float128_add(v1.q, v2.q, &env->fpu_status);
-    env->fregs[f1].ll = res.ll.upper;
-    env->fregs[f1 + 2].ll = res.ll.lower;
-    return set_cc_nz_f128(res.q);
-}
-
 /* 32-bit FP multiplication RR */
 void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
 {
@@ -747,28 +695,6 @@ void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
                                          &env->fpu_status);
 }
 
-/* convert 32-bit float to 64-bit float */
-void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
-    uint32_t v2;
-
-    v2 = cpu_ldl_data(env, a2);
-    env->fregs[f1].d = float32_to_float64(v2,
-                                          &env->fpu_status);
-}
-
-/* convert 64-bit float to 128-bit float */
-void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
-{
-    CPU_DoubleU v2;
-    CPU_QuadU v1;
-
-    v2.ll = cpu_ldq_data(env, a2);
-    v1.q = float64_to_float128(v2.d, &env->fpu_status);
-    env->fregs[f1].ll = v1.ll.upper;
-    env->fregs[f1 + 2].ll = v1.ll.lower;
-}
-
 /* test data class 32-bit */
 uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 {
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 8cf9186..2e64433 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -36,40 +36,36 @@ DEF_HELPER_3(cxfbr, void, env, i32, s32)
 DEF_HELPER_3(cegbr, void, env, i32, s64)
 DEF_HELPER_3(cdgbr, void, env, i32, s64)
 DEF_HELPER_3(cxgbr, void, env, i32, s64)
-DEF_HELPER_3(adbr, i32, env, i32, i32)
-DEF_HELPER_3(aebr, i32, env, i32, i32)
+DEF_HELPER_3(aeb, i64, env, i64, i64)
+DEF_HELPER_3(adb, i64, env, i64, i64)
+DEF_HELPER_5(axb, i64, env, i64, i64, i64, i64)
 DEF_HELPER_3(sebr, i32, env, i32, i32)
 DEF_HELPER_3(sdbr, i32, env, i32, i32)
 DEF_HELPER_3(debr, void, env, i32, i32)
 DEF_HELPER_3(dxbr, void, env, i32, i32)
 DEF_HELPER_3(mdbr, void, env, i32, i32)
 DEF_HELPER_3(mxbr, void, env, i32, i32)
-DEF_HELPER_3(ldebr, void, env, i32, i32)
-DEF_HELPER_3(ldxbr, void, env, i32, i32)
-DEF_HELPER_3(lxdbr, void, env, i32, i32)
-DEF_HELPER_3(ledbr, void, env, i32, i32)
-DEF_HELPER_3(lexbr, void, env, i32, i32)
+DEF_HELPER_2(ldeb, i64, env, i64)
+DEF_HELPER_3(ldxb, i64, env, i64, i64)
+DEF_HELPER_2(lxdb, i64, env, i64)
+DEF_HELPER_2(lxeb, i64, env, i64)
+DEF_HELPER_2(ledb, i64, env, i64)
+DEF_HELPER_3(lexb, i64, env, i64, i64)
 DEF_HELPER_3(lpebr, i32, env, i32, i32)
 DEF_HELPER_3(lpdbr, i32, env, i32, i32)
 DEF_HELPER_3(lpxbr, i32, env, i32, i32)
-DEF_HELPER_3(ltebr, i32, env, i32, i32)
-DEF_HELPER_3(ltdbr, i32, env, i32, i32)
-DEF_HELPER_3(ltxbr, i32, env, i32, i32)
 DEF_HELPER_3(lcebr, i32, env, i32, i32)
 DEF_HELPER_3(lcdbr, i32, env, i32, i32)
 DEF_HELPER_3(lcxbr, i32, env, i32, i32)
-DEF_HELPER_3(aeb, void, env, i32, i32)
 DEF_HELPER_3(deb, void, env, i32, i32)
 DEF_HELPER_3(meeb, void, env, i32, i32)
-DEF_HELPER_3(cdb, i32, env, i32, i64)
-DEF_HELPER_3(adb, i32, env, i32, i64)
 DEF_HELPER_3(seb, void, env, i32, i32)
 DEF_HELPER_3(sdb, i32, env, i32, i64)
 DEF_HELPER_3(mdb, void, env, i32, i64)
 DEF_HELPER_3(ddb, void, env, i32, i64)
-DEF_HELPER_FLAGS_3(cebr, TCG_CALL_NO_SE, i32, env, i32, i32)
-DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_NO_SE, i32, env, i32, i32)
-DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_NO_SE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
 DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
@@ -79,7 +75,6 @@ DEF_HELPER_2(lzxr, void, env, i32)
 DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
 DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
-DEF_HELPER_3(axbr, i32, env, i32, i32)
 DEF_HELPER_3(sxbr, i32, env, i32, i32)
 DEF_HELPER_3(meebr, void, env, i32, i32)
 DEF_HELPER_3(ddbr, void, env, i32, i32)
@@ -87,11 +82,9 @@ DEF_HELPER_4(madb, void, env, i32, i64, i32)
 DEF_HELPER_4(maebr, void, env, i32, i32, i32)
 DEF_HELPER_4(madbr, void, env, i32, i32, i32)
 DEF_HELPER_4(msdbr, void, env, i32, i32, i32)
-DEF_HELPER_3(ldeb, void, env, i32, i64)
-DEF_HELPER_3(lxdb, void, env, i32, i64)
-DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_SE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_SE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_SE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_WG_SE, i32, env, i32, i64)
 DEF_HELPER_3(flogr, i32, env, i32, i64)
 DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8914d34..f1c37e8 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -8,6 +8,11 @@
     C(0xb9e8, AGRK,    RRF_a, DO,  r2, r3, r1, 0, add, adds64)
     C(0xe308, AG,      RXY_a, Z,   r1, m2_64, r1, 0, add, adds64)
     C(0xe318, AGF,     RXY_a, Z,   r1, m2_32s, r1, 0, add, adds64)
+    C(0xb30a, AEBR,    RRE,   Z,   e1, e2, new, e1, aeb, f32)
+    C(0xb31a, ADBR,    RRE,   Z,   f1_o, f2_o, f1, 0, adb, f64)
+    C(0xb34a, AXBR,    RRE,   Z,   0, x2_o, x1, 0, axb, f128)
+    C(0xed0a, AEB,     RXE,   Z,   e1, m2_32u, new, e1, aeb, f32)
+    C(0xed1a, ADB,     RXE,   Z,   f1_o, m2_64, f1, 0, adb, f64)
 /* ADD IMMEDIATE */
     C(0xc209, AFI,     RIL_a, EI,  r1, i2, new, r1_32, add, adds32)
     C(0xeb6a, ASI,     SIY,   GIE, m1_32s, i2, new, m1_32, add, adds32)
@@ -94,6 +99,11 @@
     C(0xb930, CGFR,    RRE,   Z,   r1_o, r2_32s, 0, 0, 0, cmps64)
     C(0xe320, CG,      RXY_a, Z,   r1_o, m2_64, 0, 0, 0, cmps64)
     C(0xe330, CGF,     RXY_a, Z,   r1_o, m2_32s, 0, 0, 0, cmps64)
+    C(0xb309, CEBR,    RRE,   Z,   e1, e2, 0, 0, ceb, 0)
+    C(0xb319, CDBR,    RRE,   Z,   f1_o, f2_o, 0, 0, cdb, 0)
+    C(0xb349, CXBR,    RRE,   Z,   x1_o, x2_o, 0, 0, cxb, 0)
+    C(0xed09, CEB,     RXE,   Z,   e1, m2_32u, 0, 0, ceb, 0)
+    C(0xed19, CDB,     RXE,   Z,   f1_o, m2_64, 0, 0, cdb, 0)
 /* COMPARE IMMEDIATE */
     C(0xc20d, CFI,     RIL_a, EI,  r1, i2, 0, 0, 0, cmps32)
     C(0xc20c, CGFI,    RIL_a, EI,  r1, i2, 0, 0, 0, cmps64)
@@ -239,6 +249,9 @@
     C(0xe312, LT,      RXY_a, EI,  0, a2, new, r1_32, ld32s, s64)
     C(0xe302, LTG,     RXY_a, EI,  0, a2, r1, 0, ld64, s64)
     C(0xe332, LTGF,    RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
+    C(0xb302, LTEBR,   RRE,   Z,   0, e2, 0, cond_e1e2, mov2, f32)
+    C(0xb312, LTDBR,   RRE,   Z,   0, f2_o, 0, f1, mov2, f64)
+    C(0xb342, LTXBR,   RRE,   Z,   0, x2_o, 0, x1, movx, f128)
 /* LOAD BYTE */
     C(0xb926, LBR,     RRE,   EI,  0, r2_8s, 0, r1_32, mov2, 0)
     C(0xb906, LGBR,    RRE,   EI,  0, r2_8s, 0, r1, mov2, 0)
@@ -303,6 +316,18 @@
     C(0xe31e, LRV,     RXY_a, Z,   0, m2_32u, new, r1_32, rev32, 0)
     C(0xe30f, LRVG,    RXY_a, Z,   0, m2_64, r1, 0, rev64, 0)
 
+/* LOAD LENGTHENED */
+    C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
+    C(0xb305, LXDBR,   RRE,   Z,   0, f2_o, x1, 0, lxdb, 0)
+    C(0xb306, LXEBR,   RRE,   Z,   0, e2, x1, 0, lxeb, 0)
+    C(0xed04, LDEB,    RXE,   Z,   0, m2_32u, f1, 0, ldeb, 0)
+    C(0xed05, LXDB,    RXE,   Z,   0, m2_64, x1, 0, lxdb, 0)
+    C(0xed06, LXEB,    RXE,   Z,   0, m2_32u, x1, 0, lxeb, 0)
+/* LOAD ROUNDED */
+    C(0xb344, LEDBR,   RRE,   Z,   0, f2_o, new, e1, ledb, 0)
+    C(0xb345, LDXBR,   RRE,   Z,   0, x2_o, f1, 0, ldxb, 0)
+    C(0xb346, LEXBR,   RRE,   Z,   0, x2_o, new, e1, lexb, 0)
+
 /* LOAD MULTIPLE */
     C(0x9800, LM,      RS_a,  Z,   0, a2, 0, 0, lm32, 0)
     C(0xeb98, LMY,     RSY_a, LD,  0, a2, 0, 0, lm32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 033f93e..f62e4f0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -556,14 +556,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
-{
-    tcg_gen_extu_i32_i64(cc_src, v1);
-    tcg_gen_mov_i64(cc_dst, v2);
-    tcg_gen_discard_i64(cc_vr);
-    s->cc_op = CC_OP_LTGT_F32;
-}
-
 static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i32 v1)
 {
     gen_op_update1_cc_i32(s, CC_OP_NZ_F32, v1);
@@ -628,10 +620,9 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_LTUGTU_64:
     case CC_OP_TM_32:
     case CC_OP_TM_64:
-    case CC_OP_LTGT_F32:
-    case CC_OP_LTGT_F64:
     case CC_OP_SLA_32:
     case CC_OP_SLA_64:
+    case CC_OP_NZ_F128:
         /* 2 arguments */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
         break;
@@ -1009,35 +1000,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
     addr = get_address(s, x2, b2, d2);
     tmp_r1 = tcg_const_i32(r1);
     switch (op) {
-    case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
-        potential_page_fault(s);
-        gen_helper_ldeb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
-        potential_page_fault(s);
-        gen_helper_lxdb(cpu_env, tmp_r1, addr);
-        break;
-    case 0x9: /* CEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = load_freg32(r1);
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        set_cc_cmp_f32_i64(s, tmp32, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-        break;
-    case 0xa: /* AEB    R1,D2(X2,B2)       [RXE] */
-        tmp = tcg_temp_new_i64();
-        tmp32 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        gen_helper_aeb(cpu_env, tmp_r1, tmp32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32);
-
-        tmp32 = load_freg32(r1);
-        gen_set_cc_nz_f32(s, tmp32);
-        tcg_temp_free_i32(tmp32);
-        break;
     case 0xb: /* SEB    R1,D2(X2,B2)       [RXE] */
         tmp = tcg_temp_new_i64();
         tmp32 = tcg_temp_new_i32();
@@ -1084,16 +1046,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32);
         break;
-    case 0x19: /* CDB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_cdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x1a: /* ADB    R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_adb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
     case 0x1b: /* SDB    R1,D2(X2,B2)       [RXE] */
         potential_page_fault(s);
         gen_helper_sdb(cc_op, cpu_env, tmp_r1, addr);
@@ -1524,24 +1476,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x0: /* LPEBR       R1,R2             [RRE] */
         FP_HELPER_CC(lpebr);
         break;
-    case 0x2: /* LTEBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltebr);
-        break;
     case 0x3: /* LCEBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcebr);
         break;
-    case 0x4: /* LDEBR       R1,R2             [RRE] */
-        FP_HELPER(ldebr);
-        break;
-    case 0x5: /* LXDBR       R1,R2             [RRE] */
-        FP_HELPER(lxdbr);
-        break;
-    case 0x9: /* CEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cebr);
-        break;
-    case 0xa: /* AEBR        R1,R2             [RRE] */
-        FP_HELPER_CC(aebr);
-        break;
     case 0xb: /* SEBR        R1,R2             [RRE] */
         FP_HELPER_CC(sebr);
         break;
@@ -1551,9 +1488,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x10: /* LPDBR       R1,R2             [RRE] */
         FP_HELPER_CC(lpdbr);
         break;
-    case 0x12: /* LTDBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltdbr);
-        break;
     case 0x13: /* LCDBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcdbr);
         break;
@@ -1563,12 +1497,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x17: /* MEEBR       R1,R2             [RRE] */
         FP_HELPER(meebr);
         break;
-    case 0x19: /* CDBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cdbr);
-        break;
-    case 0x1a: /* ADBR        R1,R2             [RRE] */
-        FP_HELPER_CC(adbr);
-        break;
     case 0x1b: /* SDBR        R1,R2             [RRE] */
         FP_HELPER_CC(sdbr);
         break;
@@ -1605,27 +1533,9 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
     case 0x40: /* LPXBR       R1,R2             [RRE] */
         FP_HELPER_CC(lpxbr);
         break;
-    case 0x42: /* LTXBR       R1,R2             [RRE] */
-        FP_HELPER_CC(ltxbr);
-        break;
     case 0x43: /* LCXBR       R1,R2             [RRE] */
         FP_HELPER_CC(lcxbr);
         break;
-    case 0x44: /* LEDBR       R1,R2             [RRE] */
-        FP_HELPER(ledbr);
-        break;
-    case 0x45: /* LDXBR       R1,R2             [RRE] */
-        FP_HELPER(ldxbr);
-        break;
-    case 0x46: /* LEXBR       R1,R2             [RRE] */
-        FP_HELPER(lexbr);
-        break;
-    case 0x49: /* CXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(cxbr);
-        break;
-    case 0x4a: /* AXBR        R1,R2             [RRE] */
-        FP_HELPER_CC(axbr);
-        break;
     case 0x4b: /* SXBR        R1,R2             [RRE] */
         FP_HELPER_CC(sxbr);
         break;
@@ -2260,6 +2170,25 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_adb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_axb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_and(DisasContext *s, DisasOps *o)
 {
     tcg_gen_and_i64(o->out, o->in1, o->in2);
@@ -2354,6 +2283,27 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
 {
     int l = get_field(s->fields, l1);
@@ -2610,6 +2560,44 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ldeb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ledb(o->out, cpu_env, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lxdb(o->out, cpu_env, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_lxeb(o->out, cpu_env, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
 {
     tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
@@ -3369,6 +3357,21 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
     gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
 }
 
+static void cout_f32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
+}
+
+static void cout_f64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
+}
+
+static void cout_f128(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
+}
+
 static void cout_nabs32(DisasContext *s, DisasOps *o)
 {
     gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
@@ -3482,6 +3485,21 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_out = o->g_out2 = true;
 }
 
+static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->out = fregs[get_field(f, r1)];
+    o->g_out = true;
+}
+
+static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r1 = get_field(f, r1);
+    o->out = fregs[r1];
+    o->out2 = fregs[(r1 + 2) & 15];
+    o->g_out = o->g_out2 = true;
+}
+
 /* ====================================================================== */
 /* The "Write OUTput" generators.  These generally perform some non-trivial
    copy of data to TCG globals, or to main memory.  The trivial cases are
@@ -3539,6 +3557,7 @@ static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
 
 static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
+    /* ??? Specification exception: r1 must be < 14.  */
     int f1 = get_field(s->fields, r1);
     store_freg(f1, o->out);
     store_freg((f1 + 2) & 15, o->out2);
@@ -3685,6 +3704,15 @@ static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = true;
 }
 
+static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r1 = get_field(f, r1);
+    o->out = fregs[r1];
+    o->out2 = fregs[(r1 + 2) & 15];
+    o->g_out = o->g_out2 = true;
+}
+
 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
@@ -3832,9 +3860,10 @@ static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 
 static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
 {
-    int f2 = get_field(f, r2);
-    o->in1 = fregs[f2];
-    o->in2 = fregs[(f2 + 2) & 15];
+    /* ??? Specification exception: r1 must be < 14.  */
+    int r2 = get_field(f, r2);
+    o->in1 = fregs[r2];
+    o->in2 = fregs[(r2 + 2) & 15];
     o->g_in1 = o->g_in2 = true;
 }
 
commit 7691c23b1f7b508f3f5391e8f362579544be6980
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 15:59:19 2012 -0700

    target-s390: Convert LLGT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index fa3ee00..8914d34 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -285,6 +285,9 @@
     D(0xa50d, LLIHL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 32)
     D(0xa50e, LLILH,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 16)
     D(0xa50f, LLILL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 0)
+/* LOAD LOGICAL THIRTY ONE BITS */
+    C(0xb917, LLGTR,   RRE,   Z,  0, r2_o, r1, 0, llgt, 0)
+    C(0xe317, LLGT,    RXY_a, Z,  0, m2_32u, r1, 0, llgt, 0)
 /* LOAD NEGATIVE */
     C(0x1100, LNR,     RR_a,  Z,   0, r2_32s, new, r1_32, nabs, nabs32)
     C(0xb901, LNGR,    RRE,   Z,   0, r2, r1, 0, nabs, nabs64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f8c1ea7..033f93e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1001,30 +1001,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
-                     int x2, int b2, int d2)
-{
-    TCGv_i64 addr, tmp2;
-
-    LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
-              op, r1, x2, b2, d2);
-    addr = get_address(s, x2, b2, d2);
-    switch (op) {
-    case 0x17: /* LLGT      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_andi_i64(tmp2, tmp2, 0x7fffffffULL);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
-    default:
-        LOG_DISAS("illegal e3 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-    tcg_temp_free_i64(addr);
-}
-
 static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int x2, int b2, int d2, int r1b)
 {
@@ -1804,15 +1780,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
     LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
     switch (op) {
-    case 0x17: /* LLGTR      R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp = tcg_temp_new_i64();
-        tcg_gen_andi_i32(tmp32_1, tmp32_1, 0x7fffffffUL);
-        tcg_gen_extu_i32_i64(tmp, tmp32_1);
-        store_reg(r1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x83: /* FLOGR R1,R2 [RRE] */
         tmp = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
@@ -1858,17 +1825,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(env, s, op, r1, r2);
         break;
-    case 0xe3:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        x2 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = ((int)((((insn >> 16) & 0xfff)
-           | ((insn << 4) & 0xff000)) << 12)) >> 12;
-        disas_e3(env, s, op,  r1, x2, b2, d2 );
-        break;
     case 0xed:
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
@@ -2654,6 +2610,12 @@ static ExitStatus op_insi(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
 {
     tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
commit e025e52aba7063c8137b7812e10d69500efb1fbb
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 15:52:55 2012 -0700

    target-s390: Convert STORE REVERSED
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 1ee0d42..fa3ee00 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -420,6 +420,10 @@
     C(0xe370, STHY,    RXY_a, LD,  r1_o, a2, 0, 0, st16, 0)
 /* STORE HALFWORD RELATIVE LONG */
     C(0xc407, STHRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+/* STORE REVERSED */
+    C(0xe33f, STRVH,   RXY_a, Z,   la2, r1_16u, new, m1_16, rev16, 0)
+    C(0xe33e, STRV,    RXY_a, Z,   la2, r1_32u, new, m1_32, rev32, 0)
+    C(0xe32f, STRVG,   RXY_a, Z,   la2, r1_o, new, m1_64, rev64, 0)
 
 /* STORE FPC */
     C(0xb29c, STFPC,   S,     Z,   0, a2, new, m2_32, efpc, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 397511c..f8c1ea7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1005,7 +1005,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
                      int x2, int b2, int d2)
 {
     TCGv_i64 addr, tmp2;
-    TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
               op, r1, x2, b2, d2);
@@ -1018,15 +1017,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
-        tcg_temp_free_i64(tmp2);
-        break;
     default:
         LOG_DISAS("illegal e3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -3738,6 +3728,12 @@ static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
 }
 
+static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+    o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
 static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in1_la1(s, f, o);
@@ -3783,6 +3779,24 @@ static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 /* ====================================================================== */
 /* The "INput 2" generators.  These load the second operand to an insn.  */
 
+static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = regs[get_field(f, r1)];
+    o->g_in2 = true;
+}
+
+static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
+static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
+}
+
 static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r2));
commit d54f58654187f8bafb4523a286a9baf46c531d06
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 15:35:40 2012 -0700

    target-s390: Convert LOAD REVERSED
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a8dffcd..1ee0d42 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -293,6 +293,12 @@
     C(0x1000, LPR,     RR_a,  Z,   0, r2_32s, new, r1_32, abs, abs32)
     C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
     C(0xb910, LPGFR,   RRE,   Z,   0, r2_32s, r1, 0, abs, abs64)
+/* LOAD REVERSED */
+    C(0xb91f, LRVR,    RRE,   Z,   0, r2_32u, new, r1_32, rev32, 0)
+    C(0xb90f, LRVGR,   RRE,   Z,   0, r2_o, r1, 0, rev64, 0)
+    C(0xe31f, LRVH,    RXY_a, Z,   0, m2_16u, new, r1_16, rev16, 0)
+    C(0xe31e, LRV,     RXY_a, Z,   0, m2_32u, new, r1_32, rev32, 0)
+    C(0xe30f, LRVG,    RXY_a, Z,   0, m2_64, r1, 0, rev64, 0)
 
 /* LOAD MULTIPLE */
     C(0x9800, LM,      RS_a,  Z,   0, a2, 0, 0, lm32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0afc25f..397511c 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -278,17 +278,6 @@ static inline void store_reg32h_i64(int reg, TCGv_i64 v)
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
 }
 
-static inline void store_reg16(int reg, TCGv_i32 v)
-{
-    /* 16 bit register writes keep the upper bytes */
-#if HOST_LONG_BITS == 32
-    tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
-#else
-    tcg_gen_deposit_i64(regs[reg], regs[reg],
-                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
-#endif
-}
-
 static inline void store_freg32(int reg, TCGv_i32 v)
 {
     /* 32 bit register writes keep the lower half */
@@ -1022,13 +1011,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
               op, r1, x2, b2, d2);
     addr = get_address(s, x2, b2, d2);
     switch (op) {
-    case 0xf: /* LRVG     R1,D2(X2,B2)     [RXE] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        tcg_gen_bswap64_i64(tmp2, tmp2);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x17: /* LLGT      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
@@ -1036,26 +1018,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x1e: /* LRV R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x1f: /* LRVH R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_gen_bswap16_i32(tmp32_1, tmp32_1);
-        store_reg16(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
         tmp32_1 = load_reg32(r1);
         tmp2 = tcg_temp_new_i64();
@@ -1861,15 +1823,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-    case 0x0f: /* LRVGR    R1,R2     [RRE] */
-        tcg_gen_bswap64_i64(regs[r1], regs[r2]);
-        break;
-    case 0x1f: /* LRVR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_bswap32_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x83: /* FLOGR R1,R2 [RRE] */
         tmp = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
@@ -3023,6 +2976,24 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap16_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap32_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_bswap64_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 t1 = tcg_temp_new_i32();
@@ -3576,6 +3547,12 @@ static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
 }
 
+static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r1 = get_field(f, r1);
+    tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
+}
+
 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg32_i64(get_field(f, r1), o->out);
@@ -3918,6 +3895,12 @@ static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
 }
 
+static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
+}
+
 static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
commit 3e398cf9c2ffdee0c8f61d3bc8966357d0b8e095
Author: Richard Henderson <rth at twiddle.net>
Date:   Sun Sep 2 10:12:48 2012 -0700

    target-s390: Convert LOAD CONTROL, part 2
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8bfc6f9..a8dffcd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -484,6 +484,7 @@
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
 /* LOAD CONTROL */
     C(0xb700, LCTL,    RS_a,  Z,   0, a2, 0, 0, lctl, 0)
+    C(0xeb2f, LCTLG,   RSY_a, Z,   0, a2, 0, 0, lctlg, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
 /* LOAD REAL ADDRESS */
@@ -504,6 +505,7 @@
     C(0xae00, SIGP,    RS_a,  Z,   r3_o, a2, 0, 0, sigp, 0)
 /* STORE CONTROL */
     C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
+    C(0xeb25, STCTG,   RSY_a, Z,   0, a2, 0, 0, stctg, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 274c5e7..0afc25f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1073,48 +1073,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
     tcg_temp_free_i64(addr);
 }
 
-static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int r3, int b2, int d2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2;
-
-    LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
-              op, r1, r3, b2, d2);
-    switch (op) {
-#ifndef CONFIG_USER_ONLY
-    case 0x2f: /* LCTLG     R1,R3,D2(B2)     [RSE] */
-        /* Load Control */
-        check_privileged(s);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_lctlg(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x25: /* STCTG     R1,R3,D2(B2)     [RSE] */
-        /* Store Control */
-        check_privileged(s);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stctg(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-#endif
-    default:
-        LOG_DISAS("illegal eb operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
 static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int x2, int b2, int d2, int r1b)
 {
@@ -1968,17 +1926,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
            | ((insn << 4) & 0xff000)) << 12)) >> 12;
         disas_e3(env, s, op,  r1, x2, b2, d2 );
         break;
-    case 0xeb:
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        r3 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = ((int)((((insn >> 16) & 0xfff)
-           | ((insn << 4) & 0xff000)) << 12)) >> 12;
-        disas_eb(env, s, op, r1, r3, b2, d2);
-        break;
     case 0xed:
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
@@ -2819,6 +2766,17 @@ static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_lctlg(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
 static ExitStatus op_lra(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
@@ -3138,6 +3096,18 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stctg(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit 112bf0791d615060ff9235318e13fd4725146ff8
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 15:15:59 2012 -0700

    target-s390: Convert TPROT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6c2f455..8bfc6f9 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -508,4 +508,6 @@
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
     C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
+/* TEST PROTECTION */
+    C(0xe501, TPROT,   SSE,   Z,   la1, a2, 0, 0, tprot, 0)
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9f20955..274c5e7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1073,34 +1073,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
     tcg_temp_free_i64(addr);
 }
 
-#ifndef CONFIG_USER_ONLY
-static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
-{
-    TCGv_i64 tmp, tmp2;
-    int op = (insn >> 32) & 0xff;
-
-    tmp = get_address(s, 0, (insn >> 28) & 0xf, (insn >> 16) & 0xfff);
-    tmp2 = get_address(s, 0, (insn >> 12) & 0xf, insn & 0xfff);
-
-    LOG_DISAS("disas_e5: insn %" PRIx64 "\n", insn);
-    switch (op) {
-    case 0x01: /* TPROT    D1(B1),D2(B2)  [SSE] */
-        /* Test Protection */
-        potential_page_fault(s);
-        gen_helper_tprot(cc_op, tmp, tmp2);
-        set_cc_static(s);
-        break;
-    default:
-        LOG_DISAS("illegal e5 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-
-    tcg_temp_free_i64(tmp);
-    tcg_temp_free_i64(tmp2);
-}
-#endif
-
 static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int r3, int b2, int d2)
 {
@@ -1996,15 +1968,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
            | ((insn << 4) & 0xff000)) << 12)) >> 12;
         disas_e3(env, s, op,  r1, x2, b2, d2 );
         break;
-#ifndef CONFIG_USER_ONLY
-    case 0xe5:
-        /* Test Protection */
-        check_privileged(s);
-        insn = ld_code6(env, s->pc);
-        debug_insn(insn);
-        disas_e5(env, s, insn);
-        break;
-#endif
     case 0xeb:
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
@@ -3387,6 +3350,16 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     return EXIT_NORETURN;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
+{
+    potential_page_fault(s);
+    gen_helper_tprot(cc_op, o->addr1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_tr(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
commit 2ae680590667b5a8e4eb667a726b5d16d6553cb9
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 15:11:53 2012 -0700

    target-s390: Convert STCM
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c653c11..8cf9186 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -8,7 +8,6 @@ DEF_HELPER_4(mvc, void, env, i32, i64, i64)
 DEF_HELPER_4(clc, i32, env, i32, i64, i64)
 DEF_HELPER_3(mvcl, i32, env, i32, i32)
 DEF_HELPER_4(clm, i32, env, i32, i32, i64)
-DEF_HELPER_4(stcm, void, env, i32, i32, i64)
 DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_3(divs32, s64, env, s64, s64)
 DEF_HELPER_3(divu32, i64, env, i64, i64)
@@ -26,7 +25,6 @@ DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
 DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
-DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
 DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 15ded97..6c2f455 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -405,6 +405,10 @@
 /* STORE CHARACTER */
     C(0x4200, STC,     RX_a,  Z,   r1_o, a2, 0, 0, st8, 0)
     C(0xe372, STCY,    RXY_a, LD,  r1_o, a2, 0, 0, st8, 0)
+/* STORE CHARACTERS UNDER MASK */
+    D(0xbe00, STCM,    RS_b,  Z,   r1_o, a2, 0, 0, stcm, 0, 0)
+    D(0xeb2d, STCMY,   RSY_b, LD,  r1_o, a2, 0, 0, stcm, 0, 0)
+    D(0xeb2c, STCMH,   RSY_b, LD,  r1_o, a2, 0, 0, stcm, 0, 32)
 /* STORE HALFWORD */
     C(0x4000, STH,     RX_a,  Z,   r1_o, a2, 0, 0, st16, 0)
     C(0xe370, STHY,    RXY_a, LD,  r1_o, a2, 0, 0, st16, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 44c740f..9c3ade8 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -304,27 +304,6 @@ uint32_t HELPER(clm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
     return cc;
 }
 
-/* store character under mask */
-void HELPER(stcm)(CPUS390XState *env, uint32_t r1, uint32_t mask,
-                  uint64_t addr)
-{
-    uint8_t r;
-
-    HELPER_LOG("%s: r1 0x%x mask 0x%x addr 0x%lx\n", __func__, r1, mask,
-               addr);
-    while (mask) {
-        if (mask & 8) {
-            r = (r1 & 0xff000000UL) >> 24;
-            cpu_stb_data(env, addr, r);
-            HELPER_LOG("mask 0x%x %02x (0x%lx) ", mask, r, addr);
-            addr++;
-        }
-        mask = (mask << 1) & 0xf;
-        r1 <<= 8;
-    }
-    HELPER_LOG("\n");
-}
-
 static inline uint64_t get_address(CPUS390XState *env, int x2, int b2, int d2)
 {
     uint64_t r = d2;
@@ -608,22 +587,6 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
     return cc;
 }
 
-/* store character under mask high operates on the upper half of r1 */
-void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
-                   uint32_t mask)
-{
-    int pos = 56; /* top of the upper half of r1 */
-
-    while (mask) {
-        if (mask & 8) {
-            cpu_stb_data(env, address, (env->regs[r1] >> pos) & 0xff);
-            address++;
-        }
-        mask = (mask << 1) & 0xf;
-        pos -= 8;
-    }
-}
-
 /* load access registers r1 to r3 from memory at a2 */
 void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 47576fa..9f20955 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1110,16 +1110,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
     LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
               op, r1, r3, b2, d2);
     switch (op) {
-    case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stcmh(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0x2f: /* LCTLG     R1,R3,D2(B2)     [RSE] */
         /* Load Control */
@@ -1967,8 +1957,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
     int op, r1, r2, r3, d2, x2, b2, r1b;
@@ -1997,18 +1985,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(env, s, op, r1, r2);
         break;
-    case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stcm(cpu_env, tmp32_1, tmp32_2, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xe3:
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
@@ -3271,6 +3247,55 @@ static ExitStatus op_stam(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
+{
+    int m3 = get_field(s->fields, m3);
+    int pos, base = s->insn->data;
+    TCGv_i64 tmp = tcg_temp_new_i64();
+
+    pos = base + ctz32(m3) * 8;
+    switch (m3) {
+    case 0xf:
+        /* Effectively a 32-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
+        break;
+
+    case 0xc:
+    case 0x6:
+    case 0x3:
+        /* Effectively a 16-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
+        break;
+
+    case 0x8:
+    case 0x4:
+    case 0x2:
+    case 0x1:
+        /* Effectively an 8-bit store.  */
+        tcg_gen_shri_i64(tmp, o->in1, pos);
+        tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+        break;
+
+    default:
+        /* This is going to be a sequence of shifts and stores.  */
+        pos = base + 32 - 8;
+        while (m3) {
+            if (m3 & 0x8) {
+                tcg_gen_shri_i64(tmp, o->in1, pos);
+                tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
+                tcg_gen_addi_i64(o->in2, o->in2, 1);
+            }
+            m3 = (m3 << 1) & 0xf;
+            pos -= 8;
+        }
+        break;
+    }
+    tcg_temp_free_i64(tmp);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stm(DisasContext *s, DisasOps *o)
 {
     int r1 = get_field(s->fields, r1);
commit 32a44d5882ae82364a8e957a5e21cbeaaacc71a3
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 14:59:22 2012 -0700

    target-s390: Convert CLM
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4714095..15ded97 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -136,6 +136,10 @@
     C(0xc606, CLGHRL,  RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
 /* COMPARE LOGICAL LONG EXTENDED */
     C(0xa900, CLCLE,   RS_a,  Z,   0, a2, 0, 0, clcle, 0)
+/* COMPARE LOGICAL CHARACTERS UNDER MASK */
+    C(0xbd00, CLM,     RS_b,  Z,   r1_o, a2, 0, 0, clm, 0)
+    C(0xeb21, CLMY,    RSY_b, LD,  r1_o, a2, 0, 0, clm, 0)
+    C(0xeb20, CLMH,    RSY_b, Z,   r1_sr32, a2, 0, 0, clm, 0)
 
 /* COMPARE AND SWAP */
     C(0xba00, CS,      RS_a,  Z,   r1_o, a2, new, r1_32, cs, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a99d350..47576fa 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1997,19 +1997,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(env, s, op, r1, r2);
         break;
-    case 0xbd: /* CLM    R1,M3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_clm(cc_op, cpu_env, tmp32_1, tmp32_2, tmp);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xbe: /* STCM R1,M3,D2(B2) [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2628,6 +2615,19 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_clm(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+    TCGv_i32 t1 = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(t1, o->in1);
+    potential_page_fault(s);
+    gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
+    set_cc_static(s);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(m3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cs(DisasContext *s, DisasOps *o)
 {
     int r3 = get_field(s->fields, r3);
@@ -3712,6 +3712,12 @@ static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
 }
 
+static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
+}
+
 static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     /* ??? Specification exception: r1 must be even.  */
commit f3de39c485027a6b47bffb741f5209aa44052b71
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 14:46:55 2012 -0700

    target-s390: Convert COMPARE AND SWAP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0bb6d57..c653c11 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -18,9 +18,9 @@ DEF_HELPER_4(srst, i32, env, i32, i32, i32)
 DEF_HELPER_4(clst, i32, env, i32, i32, i32)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
 DEF_HELPER_4(mvst, void, env, i32, i32, i32)
-DEF_HELPER_4(csg, i32, env, i32, i64, i32)
+DEF_HELPER_4(csg, i64, env, i64, i64, i64)
 DEF_HELPER_4(cdsg, i32, env, i32, i64, i32)
-DEF_HELPER_4(cs, i32, env, i32, i64, i32)
+DEF_HELPER_4(cs, i64, env, i64, i64, i64)
 DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32)
 DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6fff22a..4714095 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -137,6 +137,15 @@
 /* COMPARE LOGICAL LONG EXTENDED */
     C(0xa900, CLCLE,   RS_a,  Z,   0, a2, 0, 0, clcle, 0)
 
+/* COMPARE AND SWAP */
+    C(0xba00, CS,      RS_a,  Z,   r1_o, a2, new, r1_32, cs, 0)
+    C(0xeb14, CSY,     RSY_a, LD,  r1_o, a2, new, r1_32, cs, 0)
+    C(0xeb30, CSG,     RSY_a, Z,   r1_o, a2, r1, 0, csg, 0)
+/* COMPARE DOUBLE AND SWAP */
+    C(0xbb00, CDS,     RS_a,  Z,   r1_D32, a2, new, r1_D32, cds, 0)
+    C(0xeb31, CDSY,    RSY_a, LD,  r1_D32, a2, new, r1_D32, cds, 0)
+    C(0xeb3e, CDSG,    RSY_a, Z,   0, a2, 0, 0, cdsg, 0)
+
 /* CONVERT TO DECIMAL */
     C(0x4e00, CVD,     RX_a,  Z,   r1_o, a2, 0, 0, cvd, 0)
     C(0xe326, CVDY,    RXY_a, LD,  r1_o, a2, 0, 0, cvd, 0)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index dcaa5a5..44c740f 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -457,20 +457,18 @@ void HELPER(mvst)(CPUS390XState *env, uint32_t c, uint32_t r1, uint32_t r2)
 }
 
 /* compare and swap 64-bit */
-uint32_t HELPER(csg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+uint64_t HELPER(csg)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
 {
     /* FIXME: locking? */
-    uint32_t cc;
     uint64_t v2 = cpu_ldq_data(env, a2);
-
-    if (env->regs[r1] == v2) {
-        cc = 0;
-        cpu_stq_data(env, a2, env->regs[r3]);
+    if (r1 == v2) {
+        cpu_stq_data(env, a2, r3);
+        env->cc_op = 0;
+        return r1;
     } else {
-        cc = 1;
-        env->regs[r1] = v2;
+        env->cc_op = 1;
+        return v2;
     }
-    return cc;
 }
 
 /* compare double and swap 64-bit */
@@ -497,21 +495,18 @@ uint32_t HELPER(cdsg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 }
 
 /* compare and swap 32-bit */
-uint32_t HELPER(cs)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
+uint64_t HELPER(cs)(CPUS390XState *env, uint64_t r1, uint64_t a2, uint64_t r3)
 {
     /* FIXME: locking? */
-    uint32_t cc;
     uint32_t v2 = cpu_ldl_data(env, a2);
-
-    HELPER_LOG("%s: r1 %d a2 0x%lx r3 %d\n", __func__, r1, a2, r3);
-    if (((uint32_t)env->regs[r1]) == v2) {
-        cc = 0;
-        cpu_stl_data(env, a2, (uint32_t)env->regs[r3]);
+    if ((uint32_t)r1 == v2) {
+        cpu_stl_data(env, a2, (uint32_t)r3);
+        env->cc_op = 0;
+        return r1;
     } else {
-        cc = 1;
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | v2;
+        env->cc_op = 1;
+        return v2;
     }
-    return cc;
 }
 
 static uint32_t helper_icm(CPUS390XState *env, uint32_t r1, uint64_t address,
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 265fc26..a99d350 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1146,30 +1146,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i32(tmp32_2);
         break;
 #endif
-    case 0x30: /* CSG     R1,R3,D2(B2)     [RSY] */
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        /* XXX rewrite in tcg */
-        gen_helper_csg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x3e: /* CDSG R1,R3,D2(B2) [RSY] */
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        /* XXX rewrite in tcg */
-        gen_helper_cdsg(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     default:
         LOG_DISAS("illegal eb operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2021,19 +1997,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(env, s, op, r1, r2);
         break;
-    case 0xba: /* CS     R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_cs(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xbd: /* CLM    R1,M3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -2665,6 +2628,47 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_cs(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    potential_page_fault(s);
+    gen_helper_cs(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_csg(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    potential_page_fault(s);
+    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, regs[r3]);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cds(DisasContext *s, DisasOps *o)
+{
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 in3 = tcg_temp_new_i64();
+    tcg_gen_deposit_i64(in3, regs[r3 + 1], regs[r3], 32, 32);
+    potential_page_fault(s);
+    gen_helper_csg(o->out, cpu_env, o->in1, o->in2, in3);
+    tcg_temp_free_i64(in3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    /* XXX rewrite in tcg */
+    gen_helper_cdsg(cc_op, cpu_env, r1, o->in2, r3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
commit 504488b82770e053aa31861fd7ef31afdb874f27
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 14:17:58 2012 -0700

    target-s390: Convert LCTL, STCTL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 819c3f5..6fff22a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -465,6 +465,8 @@
 #ifndef CONFIG_USER_ONLY
 /* DIAGNOSE (KVM hypercall) */
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
+/* LOAD CONTROL */
+    C(0xb700, LCTL,    RS_a,  Z,   0, a2, 0, 0, lctl, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
 /* LOAD REAL ADDRESS */
@@ -483,6 +485,8 @@
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 /* SIGNAL PROCESSOR */
     C(0xae00, SIGP,    RS_a,  Z,   r3_o, a2, 0, 0, sigp, 0)
+/* STORE CONTROL */
+    C(0xb600, STCTL,   RS_a,  Z,   0, a2, 0, 0, stctl, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9e648d6..265fc26 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2014,36 +2014,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         r2 = insn & 0xf;
         disas_b3(env, s, op, r3, r1, r2);
         break;
-#ifndef CONFIG_USER_ONLY
-    case 0xb6: /* STCTL     R1,R3,D2(B2)     [RS] */
-        /* Store Control */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stctl(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xb7: /* LCTL      R1,R3,D2(B2)     [RS] */
-        /* Load Control */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_lctl(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-#endif
     case 0xb9:
         insn = ld_code4(env, s->pc);
         r1 = (insn >> 4) & 0xf;
@@ -2894,6 +2864,18 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
 }
 
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_lctl(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_lra(DisasContext *s, DisasOps *o)
 {
     check_privileged(s);
@@ -3213,6 +3195,18 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_stctl(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
 {
     uint64_t i2 = get_field(s->fields, i2);
commit ea20490fdd9faacf9768363edcda3c76fed703ab
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 14:09:05 2012 -0700

    target-s390: Convert EFPC, STFPC
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 899c6a5..819c3f5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -175,6 +175,9 @@
 /* EXECUTE RELATIVE LONG */
     C(0xc600, EXRL,    RIL_b, EE,  r1_o, ri2, 0, 0, ex, 0)
 
+/* EXTRACT FPC */
+    C(0xb38c, EFPC,    RRE,   Z,   0, 0, new, r1_32, efpc, 0)
+
 /* INSERT CHARACTER */
     C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
     C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
@@ -395,6 +398,9 @@
 /* STORE HALFWORD RELATIVE LONG */
     C(0xc407, STHRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
 
+/* STORE FPC */
+    C(0xb29c, STFPC,   S,     Z,   0, a2, new, m2_32, efpc, 0)
+
 /* STORE MULTIPLE */
     D(0x9000, STM,     RS_a,  Z,   0, a2, 0, 0, stm, 0, 4)
     D(0xeb90, STMY,    RSY_a, LD,  0, a2, 0, 0, stm, 0, 4)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e087941..9e648d6 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1839,12 +1839,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x8c: /* EFPC        R1                [RRE] */
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x94: /* CEFBR       R1,R2             [RRE] */
     case 0x95: /* CDFBR       R1,R2             [RRE] */
     case 0x96: /* CXFBR       R1,R2             [RRE] */
@@ -1997,7 +1991,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
-    TCGv_i64 tmp, tmp2;
+    TCGv_i64 tmp;
     TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
@@ -2010,24 +2004,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     case 0xb2:
         insn = ld_code4(env, s->pc);
         op = (insn >> 16) & 0xff;
-        switch (op) {
-        case 0x9c: /* STFPC    D2(B2) [S] */
-            d2 = insn & 0xfff;
-            b2 = (insn >> 12) & 0xf;
-            tmp32_1 = tcg_temp_new_i32();
-            tmp = tcg_temp_new_i64();
-            tmp2 = get_address(s, 0, b2, d2);
-            tcg_gen_ld_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-            tcg_gen_extu_i32_i64(tmp, tmp32_1);
-            tcg_gen_qemu_st32(tmp, tmp2, get_mem_index(s));
-            tcg_temp_free_i32(tmp32_1);
-            tcg_temp_free_i64(tmp);
-            tcg_temp_free_i64(tmp2);
-            break;
-        default:
-            disas_b2(env, s, op, insn);
-            break;
-        }
+        disas_b2(env, s, op, insn);
         break;
     case 0xb3:
         insn = ld_code4(env, s->pc);
@@ -2774,6 +2751,12 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
+    return NO_EXIT;
+}
+
 static ExitStatus op_ex(DisasContext *s, DisasOps *o)
 {
     /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
@@ -3700,6 +3683,11 @@ static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
 }
 
+static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
+}
+
 /* ====================================================================== */
 /* The "INput 1" generators.  These load the first operand to an insn.  */
 
commit 0c2400155bc47dcfb7216f586457940a9f342462
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 13:52:23 2012 -0700

    target-s390: Convert SIGP
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a83ce95..899c6a5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -475,6 +475,8 @@
     C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
+/* SIGNAL PROCESSOR */
+    C(0xae00, SIGP,    RS_a,  Z,   r3_o, a2, 0, 0, sigp, 0)
 /* STORE THEN AND SYSTEM MASK */
     C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 /* STORE THEN OR SYSTEM MASK */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 227b77d..e087941 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2007,22 +2007,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-#ifndef CONFIG_USER_ONLY
-    case 0xae: /* SIGP   R1,R3,D2(B2)     [RS] */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = load_reg(r3);
-        tmp32_1 = tcg_const_i32(r1);
-        potential_page_fault(s);
-        gen_helper_sigp(cc_op, cpu_env, tmp, tmp32_1, tmp2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-#endif
     case 0xb2:
         insn = ld_code4(env, s->pc);
         op = (insn >> 16) & 0xff;
@@ -3194,6 +3178,18 @@ static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
+    tcg_temp_free_i32(r1);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_sla(DisasContext *s, DisasOps *o)
 {
     uint64_t sign = 1ull << s->insn->data;
commit d8fe4a9c284f244679ab251637bff81126d91dfe
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 13:15:10 2012 -0700

    target-s390: Convert LRA
    
    Note that truncating the store to r1 based on PSW_MASK_64
    is incorrect.  We always modify the entire register.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5a0f696..0bb6d57 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -131,7 +131,7 @@ DEF_HELPER_4(sigp, i32, env, i64, i32, i64)
 DEF_HELPER_2(sacf, void, env, i64)
 DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
-DEF_HELPER_3(lra, i32, env, i64, i32)
+DEF_HELPER_2(lra, i64, env, i64)
 DEF_HELPER_3(stura, void, env, i64, i32)
 #endif
 
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 65f0bfd..a83ce95 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -461,6 +461,10 @@
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
+/* LOAD REAL ADDRESS */
+    C(0xb100, LRA,     RX_a,  Z,   0, a2, r1, 0, lra, 0)
+    C(0xe313, LRAY,    RXY_a, LD,  0, a2, r1, 0, lra, 0)
+    C(0xe303, LRAG,    RXY_a, Z,   0, a2, r1, 0, lra, 0)
 /* MOVE TO PRIMARY */
     C(0xda00, MVCP,    SS_d,  Z,   la1, a2, 0, 0, mvcp, 0)
 /* MOVE TO SECONDARY */
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 1b63259..dcaa5a5 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -1127,7 +1127,7 @@ void HELPER(stura)(CPUS390XState *env, uint64_t addr, uint32_t v1)
 }
 
 /* load real address */
-uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1)
+uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
 {
     uint32_t cc = 0;
     int old_exc = env->exception_index;
@@ -1151,14 +1151,7 @@ uint32_t HELPER(lra)(CPUS390XState *env, uint64_t addr, uint32_t r1)
     }
     env->exception_index = old_exc;
 
-    if (!(env->psw.mask & PSW_MASK_64)) {
-        env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
-            (ret & 0xffffffffULL);
-    } else {
-        env->regs[r1] = ret;
-    }
-
-    return cc;
+    env->cc_op = cc;
+    return ret;
 }
-
 #endif
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 070da1e..227b77d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2022,17 +2022,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0xb1: /* LRA    R1,D2(X2, B2)     [RX] */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp32_1 = tcg_const_i32(r1);
-        potential_page_fault(s);
-        gen_helper_lra(cc_op, cpu_env, tmp, tmp32_1);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        break;
 #endif
     case 0xb2:
         insn = ld_code4(env, s->pc);
@@ -2938,6 +2927,15 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
 }
 
 #ifndef CONFIG_USER_ONLY
+static ExitStatus op_lra(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_lra(o->out, cpu_env, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 t1, t2;
commit 97c3ab61c46c1c0194657b8bead3d499600d8aab
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 13:00:27 2012 -0700

    target-s390: Convert MVCP, MVCS
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ff8f57f..65f0bfd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -461,6 +461,10 @@
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
+/* MOVE TO PRIMARY */
+    C(0xda00, MVCP,    SS_d,  Z,   la1, a2, 0, 0, mvcp, 0)
+/* MOVE TO SECONDARY */
+    C(0xdb00, MVCS,    SS_d,  Z,   la1, a2, 0, 0, mvcs, 0)
 /* SET ADDRESSING MODE */
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8a7cfaf..070da1e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2001,7 +2001,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
+    int op, r1, r2, r3, d2, x2, b2, r1b;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -2139,31 +2139,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-#ifndef CONFIG_USER_ONLY
-    case 0xda: /* MVCP     D1(R1,B1),D2(B2),R3   [SS] */
-    case 0xdb: /* MVCS     D1(R1,B1),D2(B2),R3   [SS] */
-        check_privileged(s);
-        potential_page_fault(s);
-        insn = ld_code6(env, s->pc);
-        r1 = (insn >> 36) & 0xf;
-        r3 = (insn >> 32) & 0xf;
-        b1 = (insn >> 28) & 0xf;
-        d1 = (insn >> 16) & 0xfff;
-        b2 = (insn >> 12) & 0xf;
-        d2 = insn & 0xfff;
-        /* XXX key in r3 */
-        tmp = get_address(s, 0, b1, d1);
-        tmp2 = get_address(s, 0, b2, d2);
-        if (opc == 0xda) {
-            gen_helper_mvcp(cc_op, cpu_env, regs[r1], tmp, tmp2);
-        } else {
-            gen_helper_mvcs(cc_op, cpu_env, regs[r1], tmp, tmp2);
-        }
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-#endif
     case 0xe3:
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
@@ -3111,6 +3086,28 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, l1);
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, l1);
+    check_privileged(s);
+    potential_page_fault(s);
+    gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
commit 4f7403d52b1c682df15c862f5e7ca0712b66089f
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 12:54:07 2012 -0700

    target-s390: Convert CLC
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 015a7f5..ff8f57f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -119,6 +119,7 @@
     C(0xb931, CLGFR,   RRE,   Z,   r1, r2_32u, 0, 0, 0, cmpu64)
     C(0xe321, CLG,     RXY_a, Z,   r1, m2_64, 0, 0, 0, cmpu64)
     C(0xe331, CLGF,    RXY_a, Z,   r1, m2_32u, 0, 0, 0, cmpu64)
+    C(0xd500, CLC,     SS_a,  Z,   la1, a2, 0, 0, clc, 0)
 /* COMPARE LOGICAL IMMEDIATE */
     C(0xc20f, CLFI,    RIL_a, EI,  r1, i2, 0, 0, 0, cmpu32)
     C(0xc20e, CLGFI,   RIL_a, EI,  r1, i2_32u, 0, 0, 0, cmpu64)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 36705a2..8a7cfaf 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1012,67 +1012,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
-{
-    TCGv_i64 tmp;
-    TCGv_i64 tmp2;
-    TCGv_i32 vl;
-
-    /* check for simple 32bit or 64bit match */
-    switch (l) {
-    case 0:
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld8u(tmp, s1, get_mem_index(s));
-        tcg_gen_qemu_ld8u(tmp2, s2, get_mem_index(s));
-        cmp_u64(s, tmp, tmp2);
-
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        return;
-    case 1:
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld16u(tmp, s1, get_mem_index(s));
-        tcg_gen_qemu_ld16u(tmp2, s2, get_mem_index(s));
-        cmp_u64(s, tmp, tmp2);
-
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        return;
-    case 3:
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld32u(tmp, s1, get_mem_index(s));
-        tcg_gen_qemu_ld32u(tmp2, s2, get_mem_index(s));
-        cmp_u64(s, tmp, tmp2);
-
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        return;
-    case 7:
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld64(tmp, s1, get_mem_index(s));
-        tcg_gen_qemu_ld64(tmp2, s2, get_mem_index(s));
-        cmp_u64(s, tmp, tmp2);
-
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        return;
-    }
-
-    potential_page_fault(s);
-    vl = tcg_const_i32(l);
-    gen_helper_clc(cc_op, cpu_env, vl, s1, s2);
-    tcg_temp_free_i32(vl);
-    set_cc_static(s);
-}
-
 static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
                      int x2, int b2, int d2)
 {
@@ -2200,18 +2139,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
-        insn = ld_code6(env, s->pc);
-        b1 = (insn >> 28) & 0xf;
-        b2 = (insn >> 12) & 0xf;
-        d1 = (insn >> 16) & 0xfff;
-        d2 = insn & 0xfff;
-        tmp = get_address(s, 0, b1, d1);
-        tmp2 = get_address(s, 0, b2, d2);
-        gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0xda: /* MVCP     D1(R1,B1),D2(B2),R3   [SS] */
     case 0xdb: /* MVCS     D1(R1,B1),D2(B2),R3   [SS] */
@@ -2797,6 +2724,40 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_clc(DisasContext *s, DisasOps *o)
+{
+    int l = get_field(s->fields, l1);
+    TCGv_i32 vl;
+
+    switch (l + 1) {
+    case 1:
+        tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s));
+        tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s));
+        break;
+    case 2:
+        tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s));
+        tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s));
+        break;
+    case 4:
+        tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s));
+        tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s));
+        break;
+    case 8:
+        tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s));
+        tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s));
+        break;
+    default:
+        potential_page_fault(s);
+        vl = tcg_const_i32(l);
+        gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2);
+        tcg_temp_free_i32(vl);
+        set_cc_static(s);
+        return NO_EXIT;
+    }
+    gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst);
+    return NO_EXIT;
+}
+
 static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit 0a949039596edf43e5e32dc7cb0cb4e994497e4b
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 11:54:19 2012 -0700

    target-s390: Convert NC, XC, OC, TR, UNPK
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index a8056a8..015a7f5 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -54,6 +54,7 @@
     C(0xb980, NGR,     RRE,   Z,   r1, r2, r1, 0, and, nz64)
     C(0xb9e4, NGRK,    RRF_a, DO,  r2, r3, r1, 0, and, nz64)
     C(0xe380, NG,      RXY_a, Z,   r1, m2_64, r1, 0, and, nz64)
+    C(0xd400, NC,      SS_a,  Z,   la1, a2, 0, 0, nc, 0)
 /* AND IMMEDIATE */
     D(0xc00a, NIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, andi, 0, 0x2020)
     D(0xc00b, NILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, andi, 0, 0x2000)
@@ -161,6 +162,7 @@
     C(0xb982, XGR,     RRE,   Z,   r1, r2, r1, 0, xor, nz64)
     C(0xb9e7, XGRK,    RRF_a, DO,  r2, r3, r1, 0, xor, nz64)
     C(0xe382, XG,      RXY_a, Z,   r1, m2_64, r1, 0, xor, nz64)
+    C(0xd700, XC,      SS_a,  Z,   la1, a2, 0, 0, xc, 0)
 /* EXCLUSIVE OR IMMEDIATE */
     D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
     D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
@@ -332,6 +334,7 @@
     C(0xb981, OGR,     RRE,   Z,   r1, r2, r1, 0, or, nz64)
     C(0xb9e6, OGRK,    RRF_a, DO,  r2, r3, r1, 0, or, nz64)
     C(0xe381, OG,      RXY_a, Z,   r1, m2_64, r1, 0, or, nz64)
+    C(0xd600, OC,      SS_a,  Z,   la1, a2, 0, 0, oc, 0)
 /* OR IMMEDIATE */
     D(0xc00c, OIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, ori, 0, 0x2020)
     D(0xc00d, OILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, ori, 0, 0x2000)
@@ -444,6 +447,14 @@
     D(0xa700, TMLH,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
     D(0xa701, TMLL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
 
+/* TRANSLATE */
+    C(0xdc00, TR,      SS_a,  Z,   la1, a2, 0, 0, tr, 0)
+
+/* UNPACK */
+    /* Really format SS_b, but we pack both lengths into one argument
+       for the helper call, so we might as well leave one 8-bit field.  */
+    C(0xf300, UNPK,    SS_a,  Z,   la1, a2, 0, 0, unpk, 0)
+
 #ifndef CONFIG_USER_ONLY
 /* DIAGNOSE (KVM hypercall) */
     C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 294cb92..36705a2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2063,7 +2063,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     unsigned char opc;
     uint64_t insn;
     int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
-    TCGv_i32 vl;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -2201,51 +2200,15 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
     case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
-    case 0xd6: /* OC     D1(L,B1),D2(B2)         [SS] */
-    case 0xd7: /* XC     D1(L,B1),D2(B2)         [SS] */
-    case 0xdc: /* TR     D1(L,B1),D2(B2)         [SS] */
-    case 0xf3: /* UNPK   D1(L1,B1),D2(L2,B2)     [SS] */
         insn = ld_code6(env, s->pc);
-        vl = tcg_const_i32((insn >> 32) & 0xff);
         b1 = (insn >> 28) & 0xf;
         b2 = (insn >> 12) & 0xf;
         d1 = (insn >> 16) & 0xfff;
         d2 = insn & 0xfff;
         tmp = get_address(s, 0, b1, d1);
         tmp2 = get_address(s, 0, b2, d2);
-        switch (opc) {
-        case 0xd4:
-            potential_page_fault(s);
-            gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
-            set_cc_static(s);
-            break;
-        case 0xd5:
-            gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
-            break;
-        case 0xd6:
-            potential_page_fault(s);
-            gen_helper_oc(cc_op, cpu_env, vl, tmp, tmp2);
-            set_cc_static(s);
-            break;
-        case 0xd7:
-            potential_page_fault(s);
-            gen_helper_xc(cc_op, cpu_env, vl, tmp, tmp2);
-            set_cc_static(s);
-            break;
-        case 0xdc:
-            potential_page_fault(s);
-            gen_helper_tr(cpu_env, vl, tmp, tmp2);
-            set_cc_static(s);
-            break;
-        case 0xf3:
-            potential_page_fault(s);
-            gen_helper_unpk(cpu_env, vl, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
+        gen_op_clc(s, (insn >> 32) & 0xff, tmp, tmp2);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
@@ -3206,12 +3169,32 @@ static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_nc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_neg(DisasContext *s, DisasOps *o)
 {
     tcg_gen_neg_i64(o->out, o->in2);
     return NO_EXIT;
 }
 
+static ExitStatus op_oc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_or(DisasContext *s, DisasOps *o)
 {
     tcg_gen_or_i64(o->out, o->in1, o->in2);
@@ -3446,6 +3429,35 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     return EXIT_NORETURN;
 }
 
+static ExitStatus op_tr(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_tr(cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    return NO_EXIT;
+}
+
+static ExitStatus op_xc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_xc(cc_op, cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_xor(DisasContext *s, DisasOps *o)
 {
     tcg_gen_xor_i64(o->out, o->in1, o->in2);
commit af9e5a04ea63b7ebbe7af2bb3553dc0e8a158d12
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 11:43:06 2012 -0700

    target-s390: Convert MVC
    
    The code that was in gen_op_mvc was a bit confused wrt what lengths
    it wanted to handle.  I also disbelieve that the inline memset is
    worthwhile.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 4d7f862..a8056a8 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -286,6 +286,7 @@
     C(0xeb9a, LAMY,    RSY_a, LD,  0, a2, 0, 0, lam, 0)
 
 /* MOVE */
+    C(0xd200, MVC,     SS_a,  Z,   la1, a2, 0, 0, mvc, 0)
     C(0xe544, MVHHI,   SIL,   GIE, la1, i2, 0, m1_16, mov2, 0)
     C(0xe54c, MVHI,    SIL,   GIE, la1, i2, 0, m1_32, mov2, 0)
     C(0xe548, MVGHI,   SIL,   GIE, la1, i2, 0, m1_64, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 38eeead..294cb92 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1012,170 +1012,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
-{
-    TCGv_i64 tmp, tmp2;
-    int i;
-    int l_memset = gen_new_label();
-    int l_out = gen_new_label();
-    TCGv_i64 dest = tcg_temp_local_new_i64();
-    TCGv_i64 src = tcg_temp_local_new_i64();
-    TCGv_i32 vl;
-
-    /* Find out if we should use the inline version of mvc */
-    switch (l) {
-    case 0:
-    case 1:
-    case 2:
-    case 3:
-    case 4:
-    case 5:
-    case 6:
-    case 7:
-    case 11:
-    case 15:
-        /* use inline */
-        break;
-    default:
-        /* Fall back to helper */
-        vl = tcg_const_i32(l);
-        potential_page_fault(s);
-        gen_helper_mvc(cpu_env, vl, s1, s2);
-        tcg_temp_free_i32(vl);
-        return;
-    }
-
-    tcg_gen_mov_i64(dest, s1);
-    tcg_gen_mov_i64(src, s2);
-
-    if (!(s->tb->flags & FLAG_MASK_64)) {
-        /* XXX what if we overflow while moving? */
-        tcg_gen_andi_i64(dest, dest, 0x7fffffffUL);
-        tcg_gen_andi_i64(src, src, 0x7fffffffUL);
-    }
-
-    tmp = tcg_temp_new_i64();
-    tcg_gen_addi_i64(tmp, src, 1);
-    tcg_gen_brcond_i64(TCG_COND_EQ, dest, tmp, l_memset);
-    tcg_temp_free_i64(tmp);
-
-    switch (l) {
-    case 0:
-        tmp = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
-        tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
-        tcg_temp_free_i64(tmp);
-        break;
-    case 1:
-        tmp = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld16u(tmp, src, get_mem_index(s));
-        tcg_gen_qemu_st16(tmp, dest, get_mem_index(s));
-
-        tcg_temp_free_i64(tmp);
-        break;
-    case 3:
-        tmp = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
-        tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
-
-        tcg_temp_free_i64(tmp);
-        break;
-    case 4:
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld32u(tmp, src, get_mem_index(s));
-        tcg_gen_addi_i64(src, src, 4);
-        tcg_gen_qemu_ld8u(tmp2, src, get_mem_index(s));
-        tcg_gen_qemu_st32(tmp, dest, get_mem_index(s));
-        tcg_gen_addi_i64(dest, dest, 4);
-        tcg_gen_qemu_st8(tmp2, dest, get_mem_index(s));
-
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 7:
-        tmp = tcg_temp_new_i64();
-
-        tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
-        tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
-        tcg_temp_free_i64(tmp);
-        break;
-    default:
-        /* The inline version can become too big for too uneven numbers, only
-           use it on known good lengths */
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_const_i64(8);
-        for (i = 0; (i + 7) <= l; i += 8) {
-            tcg_gen_qemu_ld64(tmp, src, get_mem_index(s));
-            tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-
-            tcg_gen_add_i64(src, src, tmp2);
-            tcg_gen_add_i64(dest, dest, tmp2);
-        }
-
-        tcg_temp_free_i64(tmp2);
-        tmp2 = tcg_const_i64(1);
-
-        for (; i <= l; i++) {
-            tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
-            tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-
-            tcg_gen_add_i64(src, src, tmp2);
-            tcg_gen_add_i64(dest, dest, tmp2);
-        }
-
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp);
-        break;
-    }
-
-    tcg_gen_br(l_out);
-
-    gen_set_label(l_memset);
-    /* memset case (dest == (src + 1)) */
-
-    tmp = tcg_temp_new_i64();
-    tmp2 = tcg_temp_new_i64();
-    /* fill tmp with the byte */
-    tcg_gen_qemu_ld8u(tmp, src, get_mem_index(s));
-    tcg_gen_shli_i64(tmp2, tmp, 8);
-    tcg_gen_or_i64(tmp, tmp, tmp2);
-    tcg_gen_shli_i64(tmp2, tmp, 16);
-    tcg_gen_or_i64(tmp, tmp, tmp2);
-    tcg_gen_shli_i64(tmp2, tmp, 32);
-    tcg_gen_or_i64(tmp, tmp, tmp2);
-    tcg_temp_free_i64(tmp2);
-
-    tmp2 = tcg_const_i64(8);
-
-    for (i = 0; (i + 7) <= l; i += 8) {
-        tcg_gen_qemu_st64(tmp, dest, get_mem_index(s));
-        tcg_gen_addi_i64(dest, dest, 8);
-    }
-
-    tcg_temp_free_i64(tmp2);
-    tmp2 = tcg_const_i64(1);
-
-    for (; i <= l; i++) {
-        tcg_gen_qemu_st8(tmp, dest, get_mem_index(s));
-        tcg_gen_addi_i64(dest, dest, 1);
-    }
-
-    tcg_temp_free_i64(tmp2);
-    tcg_temp_free_i64(tmp);
-
-    gen_set_label(l_out);
-
-    tcg_temp_free(dest);
-    tcg_temp_free(src);
-}
-
 static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
 {
     TCGv_i64 tmp;
@@ -2365,7 +2201,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xd2: /* MVC    D1(L,B1),D2(B2)         [SS] */
     case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
     case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
     case 0xd6: /* OC     D1(L,B1),D2(B2)         [SS] */
@@ -2381,9 +2216,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tmp = get_address(s, 0, b1, d1);
         tmp2 = get_address(s, 0, b2, d2);
         switch (opc) {
-        case 0xd2:
-            gen_op_mvc(s, (insn >> 32) & 0xff, tmp, tmp2);
-            break;
         case 0xd4:
             potential_page_fault(s);
             gen_helper_nc(cc_op, cpu_env, vl, tmp, tmp2);
@@ -3322,6 +3154,15 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
+    potential_page_fault(s);
+    gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
+    tcg_temp_free_i32(l);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
commit eb66e6a96904e50a9d0d1a76aecfe8675f4d8673
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 11:24:25 2012 -0700

    target-s390: Convert CLCLE, MVCLE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2e09838..4d7f862 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -132,6 +132,8 @@
     C(0xc60e, CLGFRL,  RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64)
     C(0xc607, CLHRL,   RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
     C(0xc606, CLGHRL,  RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL LONG EXTENDED */
+    C(0xa900, CLCLE,   RS_a,  Z,   0, a2, 0, 0, clcle, 0)
 
 /* CONVERT TO DECIMAL */
     C(0x4e00, CVD,     RX_a,  Z,   r1_o, a2, 0, 0, cvd, 0)
@@ -291,6 +293,8 @@
     C(0xeb52, MVIY,    SIY,   LD,  la1, i2, 0, m1_8, mov2, 0)
 /* MOVE LONG */
     C(0x0e00, MVCL,    RR_a,  Z,   0, 0, 0, 0, mvcl, 0)
+/* MOVE LONG EXTENDED */
+    C(0xa800, MVCLE,   RS_a,  Z,   0, a2, 0, 0, mvcle, 0)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b2a258f..38eeead 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,32 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0xa8: /* MVCLE   R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_mvcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0xa9: /* CLCLE   R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_clcle(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0xae: /* SIGP   R1,R3,D2(B2)     [RS] */
         check_privileged(s);
@@ -3028,6 +3002,18 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 t1 = tcg_temp_new_i64();
@@ -3348,6 +3334,18 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
commit 7df3e93aa953148841bd8a086cb3230f3d01a14c
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 09:38:22 2012 -0700

    target-s390: Convert LAM, STAM
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9859b3b..2e09838 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -279,6 +279,9 @@
     C(0xeb04, LMG,     RSY_a, Z,   0, a2, 0, 0, lm64, 0)
 /* LOAD MULTIPLE HIGH */
     C(0xeb96, LMH,     RSY_a, Z,   0, a2, 0, 0, lmh, 0)
+/* LOAD ACCESS MULTIPLE */
+    C(0x9a00, LAM,     RS_a,  Z,   0, a2, 0, 0, lam, 0)
+    C(0xeb9a, LAMY,    RSY_a, LD,  0, a2, 0, 0, lam, 0)
 
 /* MOVE */
     C(0xe544, MVHHI,   SIL,   GIE, la1, i2, 0, m1_16, mov2, 0)
@@ -389,6 +392,9 @@
     D(0xeb24, STMG,    RSY_a, Z,   0, a2, 0, 0, stm, 0, 8)
 /* STORE MULTIPLE HIGH */
     C(0xeb26, STMH,    RSY_a, Z,   0, a2, 0, 0, stmh, 0)
+/* STORE ACCESS MULTIPLE */
+    C(0x9b00, STAM,    RS_a,  Z,   0, a2, 0, 0, stam, 0)
+    C(0xeb9b, STAMY,   RSY_a, LD,  0, a2, 0, 0, stam, 0)
 
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8425c51..b2a258f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,30 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x9a: /* LAM      R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_lam(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    case 0x9b: /* STAM     R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        gen_helper_stam(cpu_env, tmp32_1, tmp, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xa8: /* MVCLE   R1,R3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3265,6 +3241,17 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_lam(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    gen_helper_lam(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
 {
     int r1 = get_field(s->fields, r1);
@@ -3518,6 +3505,17 @@ static ExitStatus op_st64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stam(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
+    potential_page_fault(s);
+    gen_helper_stam(cpu_env, r1, o->in2, r3);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r3);
+    return NO_EXIT;
+}
+
 static ExitStatus op_stm(DisasContext *s, DisasOps *o)
 {
     int r1 = get_field(s->fields, r1);
commit 145cdb401995707d1261735da7f6be3d4a91d377
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 11:08:40 2012 -0700

    target-s390: Convert STNSM, STOSM
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2383a36..9859b3b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -444,4 +444,8 @@
     C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
 /* SET SYSTEM MASK */
     C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
+/* STORE THEN AND SYSTEM MASK */
+    C(0xac00, STNSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
+/* STORE THEN OR SYSTEM MASK */
+    C(0xad00, STOSM,   SI,    Z,   la1, 0, 0, 0, stnosm, 0)
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 78c29cf..8425c51 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2226,7 +2226,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3, d1, d2, x2, b1, b2, i2, r1b;
+    int op, r1, r2, r3, d1, d2, x2, b1, b2, r1b;
     TCGv_i32 vl;
 
     opc = cpu_ldub_code(env, s->pc);
@@ -2284,23 +2284,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_2);
         break;
 #ifndef CONFIG_USER_ONLY
-    case 0xac: /* STNSM   D1(B1),I2     [SI] */
-    case 0xad: /* STOSM   D1(B1),I2     [SI] */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        tmp = decode_si(s, insn, &i2, &b1, &d1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_shri_i64(tmp2, psw_mask, 56);
-        tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
-        if (opc == 0xac) {
-            tcg_gen_andi_i64(psw_mask, psw_mask,
-                    ((uint64_t)i2 << 56) | 0x00ffffffffffffffULL);
-        } else {
-            tcg_gen_ori_i64(psw_mask, psw_mask, (uint64_t)i2 << 56);
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0xae: /* SIGP   R1,R3,D2(B2)     [RS] */
         check_privileged(s);
         insn = ld_code4(env, s->pc);
@@ -3485,6 +3468,30 @@ static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
     tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
     return NO_EXIT;
 }
+
+static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
+{
+    uint64_t i2 = get_field(s->fields, i2);
+    TCGv_i64 t;
+
+    check_privileged(s);
+
+    /* It is important to do what the instruction name says: STORE THEN.
+       If we let the output hook perform the store then if we fault and
+       restart, we'll have the wrong SYSTEM MASK in place.  */
+    t = tcg_temp_new_i64();
+    tcg_gen_shri_i64(t, psw_mask, 56);
+    tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
+    tcg_temp_free_i64(t);
+
+    if (s->fields->op == 0xac) {
+        tcg_gen_andi_i64(psw_mask, psw_mask,
+                         (i2 << 56) | 0x00ffffffffffffffull);
+    } else {
+        tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
+    }
+    return NO_EXIT;
+}
 #endif
 
 static ExitStatus op_st8(DisasContext *s, DisasOps *o)
commit a05d2b6b83544dd0ae915112d7a4565e8a3871f1
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 10:57:56 2012 -0700

    target-s390: Convert NI, XI, OI
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c971308..2383a36 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -61,6 +61,8 @@
     D(0xa505, NIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1020)
     D(0xa506, NILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
     D(0xa507, NILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
+    C(0x9400, NI,      SI,    Z,   m1_8u, i2_8u, new, m1_8, and, nz64)
+    C(0xeb54, NIY,     SIY,   LD,  m1_8u, i2_8u, new, m1_8, and, nz64)
 
 /* BRANCH AND SAVE */
     C(0x0d00, BASR,    RR_a,  Z,   0, r2_nz, r1, 0, bas, 0)
@@ -160,6 +162,8 @@
 /* EXCLUSIVE OR IMMEDIATE */
     D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
     D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+    C(0x9700, XI,      SI,    Z,   m1_8u, i2_8u, new, m1_8, xor, nz64)
+    C(0xeb57, XIY,     SIY,   LD,  m1_8u, i2_8u, new, m1_8, xor, nz64)
 
 /* EXECUTE */
     C(0x4400, EX,      RX_a,  Z,   r1_o, a2, 0, 0, ex, 0)
@@ -327,6 +331,8 @@
     D(0xa509, OIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1020)
     D(0xa50a, OILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
     D(0xa50b, OILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
+    C(0x9600, OI,      SI,    Z,   m1_8u, i2_8u, new, m1_8, or, nz64)
+    C(0xeb56, OIY,     SIY,   LD,  m1_8u, i2_8u, new, m1_8, or, nz64)
 
 /* ROTATE LEFT SINGLE LOGICAL */
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0ea5043..78c29cf 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2233,31 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x94: /* NI     D1(B1),I2        [SI] */
-    case 0x96: /* OI     D1(B1),I2        [SI] */
-    case 0x97: /* XI     D1(B1),I2        [SI] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_si(s, insn, &i2, &b1, &d1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
-        switch (opc) {
-        case 0x94:
-            tcg_gen_andi_i64(tmp2, tmp2, i2);
-            break;
-        case 0x96:
-            tcg_gen_ori_i64(tmp2, tmp2, i2);
-            break;
-        case 0x97:
-            tcg_gen_xori_i64(tmp2, tmp2, i2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
-        set_cc_nz_u64(s, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x9a: /* LAM      R1,R3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
commit 6a04d76a815c7daeb9f27b7503ebddce311958fe
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 10:22:28 2012 -0700

    target-s390: Convert MOVE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 393b425..c971308 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -276,6 +276,12 @@
 /* LOAD MULTIPLE HIGH */
     C(0xeb96, LMH,     RSY_a, Z,   0, a2, 0, 0, lmh, 0)
 
+/* MOVE */
+    C(0xe544, MVHHI,   SIL,   GIE, la1, i2, 0, m1_16, mov2, 0)
+    C(0xe54c, MVHI,    SIL,   GIE, la1, i2, 0, m1_32, mov2, 0)
+    C(0xe548, MVGHI,   SIL,   GIE, la1, i2, 0, m1_64, mov2, 0)
+    C(0x9200, MVI,     SI,    Z,   la1, i2, 0, m1_8, mov2, 0)
+    C(0xeb52, MVIY,    SIY,   LD,  la1, i2, 0, m1_8, mov2, 0)
 /* MOVE LONG */
     C(0x0e00, MVCL,    RR_a,  Z,   0, 0, 0, 0, mvcl, 0)
 
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 118f832..0ea5043 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1329,7 +1329,7 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
 static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int r3, int b2, int d2)
 {
-    TCGv_i64 tmp, tmp2;
+    TCGv_i64 tmp;
     TCGv_i32 tmp32_1, tmp32_2;
 
     LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
@@ -1395,13 +1395,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x52: /* MVIY D1(B1),I2 [SIY] */
-        tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
-        tmp2 = tcg_const_i64((r1 << 4) | r3);
-        tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     default:
         LOG_DISAS("illegal eb operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2240,14 +2233,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x92: /* MVI    D1(B1),I2        [SI] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_si(s, insn, &i2, &b1, &d1);
-        tmp2 = tcg_const_i64(i2);
-        tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x94: /* NI     D1(B1),I2        [SI] */
     case 0x96: /* OI     D1(B1),I2        [SI] */
     case 0x97: /* XI     D1(B1),I2        [SI] */
@@ -3912,6 +3897,16 @@ static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
     }
 }
 
+static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
+}
+
+static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
+}
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
commit 77f8d6c3ed89ee02847709da6508cd4dcc1d2f2d
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 09:49:37 2012 -0700

    target-s390: Convert LOAD, STORE MULTIPLE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 50a1764..393b425 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -269,6 +269,13 @@
     C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
     C(0xb910, LPGFR,   RRE,   Z,   0, r2_32s, r1, 0, abs, abs64)
 
+/* LOAD MULTIPLE */
+    C(0x9800, LM,      RS_a,  Z,   0, a2, 0, 0, lm32, 0)
+    C(0xeb98, LMY,     RSY_a, LD,  0, a2, 0, 0, lm32, 0)
+    C(0xeb04, LMG,     RSY_a, Z,   0, a2, 0, 0, lm64, 0)
+/* LOAD MULTIPLE HIGH */
+    C(0xeb96, LMH,     RSY_a, Z,   0, a2, 0, 0, lmh, 0)
+
 /* MOVE LONG */
     C(0x0e00, MVCL,    RR_a,  Z,   0, 0, 0, 0, mvcl, 0)
 
@@ -364,6 +371,13 @@
 /* STORE HALFWORD RELATIVE LONG */
     C(0xc407, STHRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
 
+/* STORE MULTIPLE */
+    D(0x9000, STM,     RS_a,  Z,   0, a2, 0, 0, stm, 0, 4)
+    D(0xeb90, STMY,    RSY_a, LD,  0, a2, 0, 0, stm, 0, 4)
+    D(0xeb24, STMG,    RSY_a, Z,   0, a2, 0, 0, stm, 0, 8)
+/* STORE MULTIPLE HIGH */
+    C(0xeb26, STMH,    RSY_a, Z,   0, a2, 0, 0, stmh, 0)
+
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
     C(0xb9f9, SRK,     RRF_a, DO,  r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 54cd2fa..118f832 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -273,6 +273,11 @@ static inline void store_reg32_i64(int reg, TCGv_i64 v)
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
 }
 
+static inline void store_reg32h_i64(int reg, TCGv_i64 v)
+{
+    tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
+}
+
 static inline void store_reg16(int reg, TCGv_i32 v)
 {
     /* 16 bit register writes keep the upper bytes */
@@ -1324,65 +1329,12 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
 static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int r3, int b2, int d2)
 {
-    TCGv_i64 tmp, tmp2, tmp3, tmp4;
+    TCGv_i64 tmp, tmp2;
     TCGv_i32 tmp32_1, tmp32_2;
-    int i, stm_len;
 
     LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
               op, r1, r3, b2, d2);
     switch (op) {
-    case 0x4:  /* LMG      R1,R3,D2(B2)     [RSE] */
-    case 0x24: /* STMG     R1,R3,D2(B2)     [RSE] */
-        stm_len = 8;
-        goto do_mh;
-    case 0x26: /* STMH     R1,R3,D2(B2)     [RSE] */
-    case 0x96: /* LMH      R1,R3,D2(B2)     [RSE] */
-        stm_len = 4;
-do_mh:
-        /* Apparently, unrolling lmg/stmg of any size gains performance -
-           even for very long ones... */
-        tmp = get_address(s, 0, b2, d2);
-        tmp3 = tcg_const_i64(stm_len);
-        tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4);
-        for (i = r1;; i = (i + 1) % 16) {
-            switch (op) {
-            case 0x4:
-                tcg_gen_qemu_ld64(regs[i], tmp, get_mem_index(s));
-                break;
-            case 0x96:
-                tmp2 = tcg_temp_new_i64();
-#if HOST_LONG_BITS == 32
-                tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-                tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2);
-#else
-                tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-                tcg_gen_shl_i64(tmp2, tmp2, tmp4);
-                tcg_gen_ext32u_i64(regs[i], regs[i]);
-                tcg_gen_or_i64(regs[i], regs[i], tmp2);
-#endif
-                tcg_temp_free_i64(tmp2);
-                break;
-            case 0x24:
-                tcg_gen_qemu_st64(regs[i], tmp, get_mem_index(s));
-                break;
-            case 0x26:
-                tmp2 = tcg_temp_new_i64();
-                tcg_gen_shr_i64(tmp2, regs[i], tmp4);
-                tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-                tcg_temp_free_i64(tmp2);
-                break;
-            default:
-                tcg_abort();
-            }
-            if (i == r3) {
-                break;
-            }
-            tcg_gen_add_i64(tmp, tmp, tmp3);
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i64(tmp4);
-        break;
     case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */
         tmp = get_address(s, 0, b2, d2);
         tmp32_1 = tcg_const_i32(r1);
@@ -2277,44 +2229,17 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
-    TCGv_i64 tmp, tmp2, tmp3, tmp4;
+    TCGv_i64 tmp, tmp2;
     TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
+    int op, r1, r2, r3, d1, d2, x2, b1, b2, i2, r1b;
     TCGv_i32 vl;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x98: /* LM     R1,R3,D2(B2)     [RS] */
-    case 0x90: /* STM    R1,R3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_const_i64(4);
-        tmp4 = tcg_const_i64(0xffffffff00000000ULL);
-        for (i = r1;; i = (i + 1) % 16) {
-            if (opc == 0x98) {
-                tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-                tcg_gen_and_i64(regs[i], regs[i], tmp4);
-                tcg_gen_or_i64(regs[i], regs[i], tmp2);
-            } else {
-                tcg_gen_qemu_st32(regs[i], tmp, get_mem_index(s));
-            }
-            if (i == r3) {
-                break;
-            }
-            tcg_gen_add_i64(tmp, tmp, tmp3);
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i64(tmp4);
-        break;
     case 0x92: /* MVI    D1(B1),I2        [SI] */
         insn = ld_code4(env, s->pc);
         tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2611,19 +2536,17 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         d1 = (insn >> 16) & 0xfff;
         b2 = (insn >> 12) & 0xf;
         d2 = insn & 0xfff;
-        tmp = load_reg(r1);
         /* XXX key in r3 */
-        tmp2 = get_address(s, 0, b1, d1);
-        tmp3 = get_address(s, 0, b2, d2);
+        tmp = get_address(s, 0, b1, d1);
+        tmp2 = get_address(s, 0, b2, d2);
         if (opc == 0xda) {
-            gen_helper_mvcp(cc_op, cpu_env, tmp, tmp2, tmp3);
+            gen_helper_mvcp(cc_op, cpu_env, regs[r1], tmp, tmp2);
         } else {
-            gen_helper_mvcs(cc_op, cpu_env, tmp, tmp2, tmp3);
+            gen_helper_mvcs(cc_op, cpu_env, regs[r1], tmp, tmp2);
         }
         set_cc_static(s);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
         break;
 #endif
     case 0xe3:
@@ -3399,6 +3322,69 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 t = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_const_i64(4);
+
+    while (1) {
+        tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+        store_reg32_i64(r1, t);
+        if (r1 == r3) {
+            break;
+        }
+        tcg_gen_add_i64(o->in2, o->in2, t4);
+        r1 = (r1 + 1) & 15;
+    }
+
+    tcg_temp_free_i64(t);
+    tcg_temp_free_i64(t4);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 t = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_const_i64(4);
+
+    while (1) {
+        tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
+        store_reg32h_i64(r1, t);
+        if (r1 == r3) {
+            break;
+        }
+        tcg_gen_add_i64(o->in2, o->in2, t4);
+        r1 = (r1 + 1) & 15;
+    }
+
+    tcg_temp_free_i64(t);
+    tcg_temp_free_i64(t4);
+    return NO_EXIT;
+}
+
+static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 t8 = tcg_const_i64(8);
+
+    while (1) {
+        tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
+        if (r1 == r3) {
+            break;
+        }
+        tcg_gen_add_i64(o->in2, o->in2, t8);
+        r1 = (r1 + 1) & 15;
+    }
+
+    tcg_temp_free_i64(t8);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
 {
     o->out = o->in2;
@@ -3565,6 +3551,54 @@ static ExitStatus op_st64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_stm(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    int size = s->insn->data;
+    TCGv_i64 tsize = tcg_const_i64(size);
+
+    while (1) {
+        if (size == 8) {
+            tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
+        } else {
+            tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
+        }
+        if (r1 == r3) {
+            break;
+        }
+        tcg_gen_add_i64(o->in2, o->in2, tsize);
+        r1 = (r1 + 1) & 15;
+    }
+
+    tcg_temp_free_i64(tsize);
+    return NO_EXIT;
+}
+
+static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    int r3 = get_field(s->fields, r3);
+    TCGv_i64 t = tcg_temp_new_i64();
+    TCGv_i64 t4 = tcg_const_i64(4);
+    TCGv_i64 t32 = tcg_const_i64(32);
+
+    while (1) {
+        tcg_gen_shl_i64(t, regs[r1], t32);
+        tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
+        if (r1 == r3) {
+            break;
+        }
+        tcg_gen_add_i64(o->in2, o->in2, t4);
+        r1 = (r1 + 1) & 15;
+    }
+
+    tcg_temp_free_i64(t);
+    tcg_temp_free_i64(t4);
+    tcg_temp_free_i64(t32);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
commit a79ba3398a0aa7fdd544ce28d2950b4eeb3c16a5
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 09:22:23 2012 -0700

    target-s390: Convert SHIFT DOUBLE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6020e04..50a1764 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -335,6 +335,14 @@
     C(0x8800, SRL,     RS_a,  Z,   r1_32u, sh32, new, r1_32, srl, 0)
     C(0xebde, SRLK,    RSY_a, DO,  r3_32u, sh32, new, r1_32, srl, 0)
     C(0xeb0c, SRLG,    RSY_a, Z,   r3_o, sh64, r1, 0, srl, 0)
+/* SHIFT LEFT DOUBLE */
+    D(0x8f00, SLDA,    RS_a,  Z,   r1_D32, sh64, new, r1_D32, sla, 0, 31)
+/* SHIFT LEFT DOUBLE LOGICAL */
+    C(0x8d00, SLDL,    RS_a,  Z,   r1_D32, sh64, new, r1_D32, sll, 0)
+/* SHIFT RIGHT DOUBLE */
+    C(0x8e00, SRDA,    RS_a,  Z,   r1_D32, sh64, new, r1_D32, sra, s64)
+/* SHIFT RIGHT DOUBLE LOGICAL */
+    C(0x8c00, SRDL,    RS_a,  Z,   r1_D32, sh64, new, r1_D32, srl, 0)
 
 /* STORE */
     C(0x5000, ST,      RX_a,  Z,   r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bb3721d..54cd2fa 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2288,36 +2288,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x8c: /* SRDL   R1,D2(B2)        [RS] */
-    case 0x8d: /* SLDL   R1,D2(B2)        [RS] */
-    case 0x8e: /* SRDA   R1,D2(B2)        [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2); /* shift */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r1 + 1);
-        tcg_gen_concat_i32_i64(tmp2, tmp32_2, tmp32_1); /* operand */
-        switch (opc) {
-        case 0x8c:
-            tcg_gen_shr_i64(tmp2, tmp2, tmp);
-            break;
-        case 0x8d:
-            tcg_gen_shl_i64(tmp2, tmp2, tmp);
-            break;
-        case 0x8e:
-            tcg_gen_sar_i64(tmp2, tmp2, tmp);
-            set_cc_s64(s, tmp2);
-            break;
-        }
-        tcg_gen_shri_i64(tmp, tmp2, 32);
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        store_reg32(r1, tmp32_1);
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        store_reg32(r1 + 1, tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x98: /* LM     R1,R3,D2(B2)     [RS] */
     case 0x90: /* STM    R1,R3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
commit cbe24bfa91d21766f2953c2da92c1e3dd13d8387
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 22 09:15:19 2012 -0700

    target-s390: Convert SHIFT, ROTATE SINGLE
    
    Note that we were missing the 32-bit SLA.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 575f7c3..be4202a 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -345,34 +345,59 @@ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
     }
 }
 
-static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
+static uint32_t cc_calc_sla_32(uint32_t src, int shift)
 {
-    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
-    uint64_t match, r;
+    uint32_t mask = ((1U << shift) - 1U) << (32 - shift);
+    uint32_t sign = 1U << 31;
+    uint32_t match;
+    int32_t r;
 
-    /* check if the sign bit stays the same */
-    if (src & (1ULL << 63)) {
+    /* Check if the sign bit stays the same.  */
+    if (src & sign) {
         match = mask;
     } else {
         match = 0;
     }
-
     if ((src & mask) != match) {
-        /* overflow */
+        /* Overflow.  */
         return 3;
     }
 
-    r = ((src << shift) & ((1ULL << 63) - 1)) | (src & (1ULL << 63));
-
-    if ((int64_t)r == 0) {
+    r = ((src << shift) & ~sign) | (src & sign);
+    if (r == 0) {
         return 0;
-    } else if ((int64_t)r < 0) {
+    } else if (r < 0) {
         return 1;
     }
-
     return 2;
 }
 
+static uint32_t cc_calc_sla_64(uint64_t src, int shift)
+{
+    uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
+    uint64_t sign = 1ULL << 63;
+    uint64_t match;
+    int64_t r;
+
+    /* Check if the sign bit stays the same.  */
+    if (src & sign) {
+        match = mask;
+    } else {
+        match = 0;
+    }
+    if ((src & mask) != match) {
+        /* Overflow.  */
+        return 3;
+    }
+
+    r = ((src << shift) & ~sign) | (src & sign);
+    if (r == 0) {
+        return 0;
+    } else if (r < 0) {
+        return 1;
+    }
+    return 2;
+}
 
 static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                   uint64_t src, uint64_t dst, uint64_t vr)
@@ -473,8 +498,11 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
     case CC_OP_ICM:
         r =  cc_calc_icm(src, dst);
         break;
-    case CC_OP_SLAG:
-        r =  cc_calc_slag(src, dst);
+    case CC_OP_SLA_32:
+        r =  cc_calc_sla_32(src, dst);
+        break;
+    case CC_OP_SLA_64:
+        r =  cc_calc_sla_64(src, dst);
         break;
 
     case CC_OP_LTGT_F32:
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 69269a1..b8e9037 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -478,7 +478,8 @@ enum cc_op {
     CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
 
     CC_OP_ICM,                  /* insert characters under mask */
-    CC_OP_SLAG,                 /* Calculate shift left signed */
+    CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
+    CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
     CC_OP_MAX
 };
 
@@ -521,7 +522,8 @@ static const char *cc_names[] = {
     [CC_OP_NZ_F32]    = "CC_OP_NZ_F32",
     [CC_OP_NZ_F64]    = "CC_OP_NZ_F64",
     [CC_OP_ICM]       = "CC_OP_ICM",
-    [CC_OP_SLAG]      = "CC_OP_SLAG",
+    [CC_OP_SLA_32]    = "CC_OP_SLA_32",
+    [CC_OP_SLA_64]    = "CC_OP_SLA_64",
 };
 
 static inline const char *cc_name(int cc_op)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0a0ec0a..6020e04 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -315,6 +315,27 @@
     D(0xa50a, OILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
     D(0xa50b, OILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
 
+/* ROTATE LEFT SINGLE LOGICAL */
+    C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
+    C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
+
+/* SHIFT LEFT SINGLE */
+    D(0x8b00, SLA,     RS_a,  Z,   r1, sh32, new, r1_32, sla, 0, 31)
+    D(0xebdd, SLAK,    RSY_a, DO,  r3, sh32, new, r1_32, sla, 0, 31)
+    D(0xeb0b, SLAG,    RSY_a, Z,   r3, sh64, r1, 0, sla, 0, 63)
+/* SHIFT LEFT SINGLE LOGICAL */
+    C(0x8900, SLL,     RS_a,  Z,   r1_o, sh32, new, r1_32, sll, 0)
+    C(0xebdf, SLLK,    RSY_a, DO,  r3_o, sh32, new, r1_32, sll, 0)
+    C(0xeb0d, SLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, sll, 0)
+/* SHIFT RIGHT SINGLE */
+    C(0x8a00, SRA,     RS_a,  Z,   r1_32s, sh32, new, r1_32, sra, s32)
+    C(0xebdc, SRAK,    RSY_a, DO,  r3_32s, sh32, new, r1_32, sra, s32)
+    C(0xeb0a, SRAG,    RSY_a, Z,   r3_o, sh64, r1, 0, sra, s64)
+/* SHIFT RIGHT SINGLE LOGICAL */
+    C(0x8800, SRL,     RS_a,  Z,   r1_32u, sh32, new, r1_32, srl, 0)
+    C(0xebde, SRLK,    RSY_a, DO,  r3_32u, sh32, new, r1_32, srl, 0)
+    C(0xeb0c, SRLG,    RSY_a, Z,   r3_o, sh64, r1, 0, srl, 0)
+
 /* STORE */
     C(0x5000, ST,      RX_a,  Z,   r1_o, a2, 0, 0, st32, 0)
     C(0xe350, STY,     RXY_a, LD,  r1_o, a2, 0, 0, st32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6848e31..bb3721d 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -636,7 +636,8 @@ static void gen_op_calc_cc(DisasContext *s)
     case CC_OP_TM_64:
     case CC_OP_LTGT_F32:
     case CC_OP_LTGT_F64:
-    case CC_OP_SLAG:
+    case CC_OP_SLA_32:
+    case CC_OP_SLA_64:
         /* 2 arguments */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
         break;
@@ -1330,74 +1331,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
     LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
               op, r1, r3, b2, d2);
     switch (op) {
-    case 0xc: /* SRLG     R1,R3,D2(B2)     [RSY] */
-    case 0xd: /* SLLG     R1,R3,D2(B2)     [RSY] */
-    case 0xa: /* SRAG     R1,R3,D2(B2)     [RSY] */
-    case 0xb: /* SLAG     R1,R3,D2(B2)     [RSY] */
-    case 0x1c: /* RLLG     R1,R3,D2(B2)     [RSY] */
-        if (b2) {
-            tmp = get_address(s, 0, b2, d2);
-            tcg_gen_andi_i64(tmp, tmp, 0x3f);
-        } else {
-            tmp = tcg_const_i64(d2 & 0x3f);
-        }
-        switch (op) {
-        case 0xc:
-            tcg_gen_shr_i64(regs[r1], regs[r3], tmp);
-            break;
-        case 0xd:
-            tcg_gen_shl_i64(regs[r1], regs[r3], tmp);
-            break;
-        case 0xa:
-            tcg_gen_sar_i64(regs[r1], regs[r3], tmp);
-            break;
-        case 0xb:
-            tmp2 = tcg_temp_new_i64();
-            tmp3 = tcg_temp_new_i64();
-            gen_op_update2_cc_i64(s, CC_OP_SLAG, regs[r3], tmp);
-            tcg_gen_shl_i64(tmp2, regs[r3], tmp);
-            /* override sign bit with source sign */
-            tcg_gen_andi_i64(tmp2, tmp2, ~0x8000000000000000ULL);
-            tcg_gen_andi_i64(tmp3, regs[r3], 0x8000000000000000ULL);
-            tcg_gen_or_i64(regs[r1], tmp2, tmp3);
-            tcg_temp_free_i64(tmp2);
-            tcg_temp_free_i64(tmp3);
-            break;
-        case 0x1c:
-            tcg_gen_rotl_i64(regs[r1], regs[r3], tmp);
-            break;
-        default:
-            tcg_abort();
-            break;
-        }
-        if (op == 0xa) {
-            set_cc_s64(s, regs[r1]);
-        }
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x1d: /* RLL    R1,R3,D2(B2)        [RSY] */
-        if (b2) {
-            tmp = get_address(s, 0, b2, d2);
-            tcg_gen_andi_i64(tmp, tmp, 0x3f);
-        } else {
-            tmp = tcg_const_i64(d2 & 0x3f);
-        }
-        tmp32_1 = tcg_temp_new_i32();
-        tmp32_2 = load_reg32(r3);
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        switch (op) {
-        case 0x1d:
-            tcg_gen_rotl_i32(tmp32_1, tmp32_2, tmp32_1);
-            break;
-        default:
-            tcg_abort();
-            break;
-        }
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x4:  /* LMG      R1,R3,D2(B2)     [RSE] */
     case 0x24: /* STMG     R1,R3,D2(B2)     [RSE] */
         stm_len = 8;
@@ -2355,35 +2288,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x88: /* SRL    R1,D2(B2)        [RS] */
-    case 0x89: /* SLL    R1,D2(B2)        [RS] */
-    case 0x8a: /* SRA    R1,D2(B2)        [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp);
-        tcg_gen_andi_i32(tmp32_2, tmp32_2, 0x3f);
-        switch (opc) {
-        case 0x88:
-            tcg_gen_shr_i32(tmp32_1, tmp32_1, tmp32_2);
-            break;
-        case 0x89:
-            tcg_gen_shl_i32(tmp32_1, tmp32_1, tmp32_2);
-            break;
-        case 0x8a:
-            tcg_gen_sar_i32(tmp32_1, tmp32_1, tmp32_2);
-            set_cc_s32(s, tmp32_1);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x8c: /* SRDL   R1,D2(B2)        [RS] */
     case 0x8d: /* SLDL   R1,D2(B2)        [RS] */
     case 0x8e: /* SRDA   R1,D2(B2)        [RS] */
@@ -3029,6 +2933,20 @@ struct DisasInsn {
 /* ====================================================================== */
 /* Miscelaneous helpers, used by several operations.  */
 
+static void help_l2_shift(DisasContext *s, DisasFields *f,
+                          DisasOps *o, int mask)
+{
+    int b2 = get_field(f, b2);
+    int d2 = get_field(f, d2);
+
+    if (b2 == 0) {
+        o->in2 = tcg_const_i64(d2 & mask);
+    } else {
+        o->in2 = get_address(s, 0, b2, d2);
+        tcg_gen_andi_i64(o->in2, o->in2, mask);
+    }
+}
+
 static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
 {
     if (dest == s->next_pc) {
@@ -3591,6 +3509,59 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 t1 = tcg_temp_new_i32();
+    TCGv_i32 t2 = tcg_temp_new_i32();
+    TCGv_i32 to = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(t1, o->in1);
+    tcg_gen_trunc_i64_i32(t2, o->in2);
+    tcg_gen_rotl_i32(to, t1, t2);
+    tcg_gen_extu_i32_i64(o->out, to);
+    tcg_temp_free_i32(t1);
+    tcg_temp_free_i32(t2);
+    tcg_temp_free_i32(to);
+    return NO_EXIT;
+}
+
+static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_rotl_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sla(DisasContext *s, DisasOps *o)
+{
+    uint64_t sign = 1ull << s->insn->data;
+    enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
+    gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
+    tcg_gen_shl_i64(o->out, o->in1, o->in2);
+    /* The arithmetic left shift is curious in that it does not affect
+       the sign bit.  Copy that over from the source unchanged.  */
+    tcg_gen_andi_i64(o->out, o->out, ~sign);
+    tcg_gen_andi_i64(o->in1, o->in1, sign);
+    tcg_gen_or_i64(o->out, o->out, o->in1);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sll(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_shl_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sra(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_sar_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_srl(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_shr_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
@@ -3961,6 +3932,18 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = true;
 }
 
+static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
+}
+
+static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
+}
+
 static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     /* ??? Specification exception: r1 must be even.  */
@@ -4002,6 +3985,24 @@ static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = load_reg(get_field(f, r3));
 }
 
+static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = regs[get_field(f, r3)];
+    o->g_in1 = true;
+}
+
+static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
+}
+
+static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
+}
+
 static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_freg32_i64(get_field(f, r1));
@@ -4153,6 +4154,16 @@ static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
 }
 
+static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    help_l2_shift(s, f, o, 31);
+}
+
+static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    help_l2_shift(s, f, o, 63);
+}
+
 static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
commit 972e35b9665db113c3d4df7d394ee8cbbf7446ee
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 14:41:36 2012 -0700

    target-s390: Convert DIAGNOSE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index b0bee9b..0a0ec0a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -379,6 +379,8 @@
     D(0xa701, TMLL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
 
 #ifndef CONFIG_USER_ONLY
+/* DIAGNOSE (KVM hypercall) */
+    C(0x8300, DIAG,    RX_a,  Z,   0, 0, 0, 0, diag, 0)
 /* LOAD PSW */
     C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
 /* SET ADDRESSING MODE */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index cbfcf41..6848e31 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,23 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-#ifndef CONFIG_USER_ONLY
-    case 0x83: /* DIAG     R1,R3,D2     [RS] */
-        /* Diagnose call (KVM hypercall) */
-        check_privileged(s);
-        potential_page_fault(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp32_1 = tcg_const_i32(insn & 0xfff);
-        tmp2 = load_reg(2);
-        tmp3 = load_reg(1);
-        gen_helper_diag(tmp2, cpu_env, tmp32_1, tmp2, tmp3);
-        store_reg(2, tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-#endif
     case 0x88: /* SRL    R1,D2(B2)        [RS] */
     case 0x89: /* SLL    R1,D2(B2)        [RS] */
     case 0x8a: /* SRA    R1,D2(B2)        [RS] */
@@ -3327,6 +3310,22 @@ static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_diag(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 tmp;
+
+    check_privileged(s);
+    potential_page_fault(s);
+
+    /* We pretend the format is RX_a so that D2 is the field we want.  */
+    tmp = tcg_const_i32(get_field(s->fields, d2) & 0xfff);
+    gen_helper_diag(regs[2], cpu_env, tmp, regs[2], regs[1]);
+    tcg_temp_free_i32(tmp);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
 {
     gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
commit 8b5ff57115e60589d772efeaa0c061ad6701e340
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 14:33:36 2012 -0700

    target-s390: Convert LOAD PSW
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 45c36c1..b0bee9b 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -379,6 +379,8 @@
     D(0xa701, TMLL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
 
 #ifndef CONFIG_USER_ONLY
+/* LOAD PSW */
+    C(0x8200, LPSW,    S,     Z,   0, a2, 0, 0, lpsw, 0)
 /* SET ADDRESSING MODE */
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 246d0f0..cbfcf41 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2356,26 +2356,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 
     switch (opc) {
 #ifndef CONFIG_USER_ONLY
-    case 0x82: /* LPSW     D2(B2)       [S] */
-        /* Load PSW */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_addi_i64(tmp, tmp, 4);
-        tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
-        /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK.  */
-        tcg_gen_shli_i64(tmp2, tmp2, 32);
-        gen_helper_load_psw(cpu_env, tmp2, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        /* we need to keep cc_op intact */
-        s->is_jmp = DISAS_JUMP;
-        break;
     case 0x83: /* DIAG     R1,R3,D2     [RS] */
         /* Diagnose call (KVM hypercall) */
         check_privileged(s);
@@ -3511,6 +3491,27 @@ static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t1, t2;
+
+    check_privileged(s);
+
+    t1 = tcg_temp_new_i64();
+    t2 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
+    tcg_gen_addi_i64(o->in2, o->in2, 4);
+    tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
+    /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK.  */
+    tcg_gen_shli_i64(t1, t1, 32);
+    gen_helper_load_psw(cpu_env, t1, t2);
+    tcg_temp_free_i64(t1);
+    tcg_temp_free_i64(t2);
+    return EXIT_NORETURN;
+}
+#endif
+
 static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
 {
     o->out = o->in2;
commit 7d30bb73db3a2fa38a33556430754917d5d70c91
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 14:12:50 2012 -0700

    target-s390: Convert SET SYSTEM MASK
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c5c5614..45c36c1 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -383,4 +383,6 @@
     /* We only do 64-bit, so accept this as a no-op.
        Let SAM24 and SAM31 signal illegal instruction.  */
     C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
+/* SET SYSTEM MASK */
+    C(0x8000, SSM,     S,     Z,   0, m2_8u, 0, 0, ssm, 0)
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9f92954..246d0f0 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2356,22 +2356,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 
     switch (opc) {
 #ifndef CONFIG_USER_ONLY
-    case 0x80: /* SSM      D2(B2)       [S] */
-        /* Set System Mask */
-        check_privileged(s);
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, b2, d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_andi_i64(tmp3, psw_mask, ~0xff00000000000000ULL);
-        tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_shli_i64(tmp2, tmp2, 56);
-        tcg_gen_or_i64(psw_mask, tmp3, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x82: /* LPSW     D2(B2)       [S] */
         /* Load PSW */
         check_privileged(s);
@@ -3607,6 +3591,15 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+#ifndef CONFIG_USER_ONLY
+static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
+{
+    check_privileged(s);
+    tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
+    return NO_EXIT;
+}
+#endif
+
 static ExitStatus op_st8(DisasContext *s, DisasOps *o)
 {
     tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
commit c49daa51a8e19694a611971206e75bd245768e3c
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 14:05:11 2012 -0700

    target-s390: Convert CONVERT TO DECIMAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6b81f69..c5c5614 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -131,6 +131,10 @@
     C(0xc607, CLHRL,   RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
     C(0xc606, CLGHRL,  RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
 
+/* CONVERT TO DECIMAL */
+    C(0x4e00, CVD,     RX_a,  Z,   r1_o, a2, 0, 0, cvd, 0)
+    C(0xe326, CVDY,    RXY_a, LD,  r1_o, a2, 0, 0, cvd, 0)
+
 /* DIVIDE */
     C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
     C(0x5d00, D,       RX_a,  Z,   r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 8728b36..9f92954 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,18 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x4e: /* CVD    R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_trunc_i64_i32(tmp32_1, regs[r1]);
-        gen_helper_cvd(tmp2, tmp32_1);
-        tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0x80: /* SSM      D2(B2)       [S] */
         /* Set System Mask */
@@ -3363,6 +3351,18 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 t1 = tcg_temp_new_i64();
+    TCGv_i32 t2 = tcg_temp_new_i32();
+    tcg_gen_trunc_i64_i32(t2, o->in1);
+    gen_helper_cvd(t1, t2);
+    tcg_temp_free_i32(t2);
+    tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s));
+    tcg_temp_free_i64(t1);
+    return NO_EXIT;
+}
+
 static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
 {
     gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
commit 00574261e1fcb318fdd4cc1293238fc1f50de341
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 12:26:53 2012 -0700

    target-s390: Convert FP STORE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0768849..6b81f69 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -315,6 +315,10 @@
     C(0x5000, ST,      RX_a,  Z,   r1_o, a2, 0, 0, st32, 0)
     C(0xe350, STY,     RXY_a, LD,  r1_o, a2, 0, 0, st32, 0)
     C(0xe324, STG,     RXY_a, Z,   r1_o, a2, 0, 0, st64, 0)
+    C(0x6000, STD,     RX_a,  Z,   f1_o, a2, 0, 0, st64, 0)
+    C(0xed67, STDY,    RXY_a, LD,  f1_o, a2, 0, 0, st64, 0)
+    C(0x7000, STE,     RX_a,  Z,   e1, a2, 0, 0, st32, 0)
+    C(0xed66, STEY,    RXY_a, LD,  e1, a2, 0, 0, st32, 0)
 /* STORE RELATIVE LONG */
     C(0xc40f, STRL,    RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0)
     C(0xc40b, STGRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index bece7c5..8728b36 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2367,25 +2367,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x60: /* STD    R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = load_freg(r1);
-        tcg_gen_qemu_st64(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x70: /* STE R1,D2(X2,B2) [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_freg32(r1);
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0x80: /* SSM      D2(B2)       [S] */
         /* Set System Mask */
@@ -4028,6 +4009,17 @@ static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = load_reg(get_field(f, r3));
 }
 
+static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = load_freg32_i64(get_field(f, r1));
+}
+
+static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = fregs[get_field(f, r1)];
+    o->g_in1 = true;
+}
+
 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
commit 6e764e97ca4050f2105b10e158f4fcb2801470be
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 13:48:38 2012 -0700

    target-s390: Convert EXECUTE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 38a93e3..0768849 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -157,6 +157,11 @@
     D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
     D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
 
+/* EXECUTE */
+    C(0x4400, EX,      RX_a,  Z,   r1_o, a2, 0, 0, ex, 0)
+/* EXECUTE RELATIVE LONG */
+    C(0xc600, EXRL,    RIL_b, EE,  r1_o, ri2, 0, 0, ex, 0)
+
 /* INSERT CHARACTER */
     C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
     C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 36d8cdd..bece7c5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2355,19 +2355,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x44: /* EX     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = load_reg(r1);
-        tmp3 = tcg_const_i64(s->pc + 4);
-        update_psw_addr(s);
-        gen_op_calc_cc(s);
-        gen_helper_ex(cc_op, cpu_env, cc_op, tmp2, tmp, tmp3);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x4e: /* CVD    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3423,6 +3410,32 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ex(DisasContext *s, DisasOps *o)
+{
+    /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
+       tb->flags, (ab)use the tb->cs_base field as the address of
+       the template in memory, and grab 8 bits of tb->flags/cflags for
+       the contents of the register.  We would then recognize all this
+       in gen_intermediate_code_internal, generating code for exactly
+       one instruction.  This new TB then gets executed normally.
+
+       On the other hand, this seems to be mostly used for modifying
+       MVC inside of memcpy, which needs a helper call anyway.  So
+       perhaps this doesn't bear thinking about any further.  */
+
+    TCGv_i64 tmp;
+
+    update_psw_addr(s);
+    gen_op_calc_cc(s);
+
+    tmp = tcg_const_i64(s->next_pc);
+    gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
+    tcg_temp_free_i64(tmp);
+
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_icm(DisasContext *s, DisasOps *o)
 {
     int m3 = get_field(s->fields, m3);
commit 58a9e35bcc23d44142a2a58ddf3fae51749f3f01
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 13:13:09 2012 -0700

    target-s390: Convert INSERT CHARACTERS UNDER MASK
    
    Change the CC handling to be more like TEST UNDER MASK, with val & mask.
    This lets us handle ICMH much more like ICM.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 3d89fb9..575f7c3 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -331,35 +331,18 @@ static uint32_t cc_calc_comp_32(int32_t dst)
 }
 
 /* calculate condition code for insert character under mask insn */
-static uint32_t cc_calc_icm_32(uint32_t mask, uint32_t val)
+static uint32_t cc_calc_icm(uint64_t mask, uint64_t val)
 {
-    uint32_t cc;
-
-    HELPER_LOG("%s: mask 0x%x val %d\n", __func__, mask, val);
-    if (mask == 0xf) {
-        if (!val) {
-            return 0;
-        } else if (val & 0x80000000) {
+    if ((val & mask) == 0) {
+        return 0;
+    } else {
+        int top = clz64(mask);
+        if ((int64_t)(val << top) < 0) {
             return 1;
         } else {
             return 2;
         }
     }
-
-    if (!val || !mask) {
-        cc = 0;
-    } else {
-        while (mask != 1) {
-            mask >>= 1;
-            val >>= 8;
-        }
-        if (val & 0x80) {
-            cc = 1;
-        } else {
-            cc = 2;
-        }
-    }
-    return cc;
 }
 
 static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
@@ -488,7 +471,7 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
         break;
 
     case CC_OP_ICM:
-        r =  cc_calc_icm_32(src, dst);
+        r =  cc_calc_icm(src, dst);
         break;
     case CC_OP_SLAG:
         r =  cc_calc_slag(src, dst);
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index dcc3fce..5a0f696 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -27,7 +27,6 @@ DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32)
 DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64)
 DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
 DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
-DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
 DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f37e69a..38a93e3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -160,6 +160,10 @@
 /* INSERT CHARACTER */
     C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
     C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
+/* INSERT CHARACTERS UNDER MASK */
+    D(0xbf00, ICM,     RS_b,  Z,   0, a2, r1, 0, icm, 0, 0)
+    D(0xeb81, ICMY,    RSY_b, LD,  0, a2, r1, 0, icm, 0, 0)
+    D(0xeb80, ICMH,    RSY_b, Z,   0, a2, r1, 0, icm, 0, 32)
 /* INSERT IMMEDIATE */
     D(0xc008, IIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
     D(0xc009, IILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index 7eb3790..1b63259 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -629,39 +629,6 @@ void HELPER(stcmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
     }
 }
 
-/* insert character under mask high; same as icm, but operates on the
-   upper half of r1 */
-uint32_t HELPER(icmh)(CPUS390XState *env, uint32_t r1, uint64_t address,
-                      uint32_t mask)
-{
-    int pos = 56; /* top of the upper half of r1 */
-    uint64_t rmask = 0xff00000000000000ULL;
-    uint8_t val = 0;
-    int ccd = 0;
-    uint32_t cc = 0;
-
-    while (mask) {
-        if (mask & 8) {
-            env->regs[r1] &= ~rmask;
-            val = cpu_ldub_data(env, address);
-            if ((val & 0x80) && !ccd) {
-                cc = 1;
-            }
-            ccd = 1;
-            if (val && cc == 0) {
-                cc = 2;
-            }
-            env->regs[r1] |= (uint64_t)val << pos;
-            address++;
-        }
-        mask = (mask << 1) & 0xf;
-        pos -= 8;
-        rmask >>= 8;
-    }
-
-    return cc;
-}
-
 /* load access registers r1 to r3 from memory at a2 */
 void HELPER(lam)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 25bbf45..36d8cdd 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -32,6 +32,7 @@
 #include "disas/disas.h"
 #include "tcg-op.h"
 #include "qemu/log.h"
+#include "qemu/host-utils.h"
 
 /* global register indexes */
 static TCGv_ptr cpu_env;
@@ -561,11 +562,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
-{
-    gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
-}
-
 static void set_cc_cmp_f32_i64(DisasContext *s, TCGv_i32 v1, TCGv_i64 v2)
 {
     tcg_gen_extu_i32_i64(cc_src, v1);
@@ -896,7 +892,6 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
 
     case CC_OP_LTGT0_64:
     case CC_OP_NZ:
-    case CC_OP_ICM:
         c->u.s64.a = cc_dst;
         c->u.s64.b = tcg_const_i64(0);
         c->g1 = true;
@@ -910,6 +905,7 @@ static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
 
     case CC_OP_TM_32:
     case CC_OP_TM_64:
+    case CC_OP_ICM:
         c->u.s64.a = tcg_temp_new_i64();
         c->u.s64.b = tcg_const_i64(0);
         tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
@@ -1521,18 +1517,6 @@ do_mh:
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x80: /* ICMH      R1,M3,D2(B2)     [RSY] */
-        tmp = get_address(s, 0, b2, d2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r3);
-        potential_page_fault(s);
-        /* XXX split CC calculation out */
-        gen_helper_icmh(cc_op, cpu_env, tmp32_1, tmp, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     default:
         LOG_DISAS("illegal eb operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2361,7 +2345,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     TCGv_i64 tmp, tmp2, tmp3, tmp4;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3, tmp32_4;
+    TCGv_i32 tmp32_1, tmp32_2;
     unsigned char opc;
     uint64_t insn;
     int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
@@ -2786,60 +2770,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xbf: /* ICM    R1,M3,D2(B2)     [RS] */
-        insn = ld_code4(env, s->pc);
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        if (r3 == 15) {
-            /* effectively a 32-bit load */
-            tmp = get_address(s, 0, b2, d2);
-            tmp32_1 = tcg_temp_new_i32();
-            tmp32_2 = tcg_const_i32(r3);
-            tcg_gen_qemu_ld32u(tmp, tmp, get_mem_index(s));
-            store_reg32_i64(r1, tmp);
-            tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-            set_cc_icm(s, tmp32_2, tmp32_1);
-            tcg_temp_free_i64(tmp);
-            tcg_temp_free_i32(tmp32_1);
-            tcg_temp_free_i32(tmp32_2);
-        } else if (r3) {
-            uint32_t mask = 0x00ffffffUL;
-            uint32_t shift = 24;
-            int m3 = r3;
-            tmp = get_address(s, 0, b2, d2);
-            tmp2 = tcg_temp_new_i64();
-            tmp32_1 = load_reg32(r1);
-            tmp32_2 = tcg_temp_new_i32();
-            tmp32_3 = tcg_const_i32(r3);
-            tmp32_4 = tcg_const_i32(0);
-            while (m3) {
-                if (m3 & 8) {
-                    tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
-                    tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-                    if (shift) {
-                        tcg_gen_shli_i32(tmp32_2, tmp32_2, shift);
-                    }
-                    tcg_gen_andi_i32(tmp32_1, tmp32_1, mask);
-                    tcg_gen_or_i32(tmp32_1, tmp32_1, tmp32_2);
-                    tcg_gen_or_i32(tmp32_4, tmp32_4, tmp32_2);
-                    tcg_gen_addi_i64(tmp, tmp, 1);
-                }
-                m3 = (m3 << 1) & 0xf;
-                mask = (mask >> 8) | 0xff000000UL;
-                shift -= 8;
-            }
-            store_reg32(r1, tmp32_1);
-            set_cc_icm(s, tmp32_3, tmp32_4);
-            tcg_temp_free_i64(tmp);
-            tcg_temp_free_i64(tmp2);
-            tcg_temp_free_i32(tmp32_1);
-            tcg_temp_free_i32(tmp32_2);
-            tcg_temp_free_i32(tmp32_3);
-            tcg_temp_free_i32(tmp32_4);
-        } else {
-            /* i.e. env->cc = 0 */
-            gen_op_movi_cc(s, 0);
-        }
-        break;
     case 0xd2: /* MVC    D1(L,B1),D2(B2)         [SS] */
     case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
     case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
@@ -3493,6 +3423,66 @@ static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_icm(DisasContext *s, DisasOps *o)
+{
+    int m3 = get_field(s->fields, m3);
+    int pos, len, base = s->insn->data;
+    TCGv_i64 tmp = tcg_temp_new_i64();
+    uint64_t ccm;
+
+    switch (m3) {
+    case 0xf:
+        /* Effectively a 32-bit load.  */
+        tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
+        len = 32;
+        goto one_insert;
+
+    case 0xc:
+    case 0x6:
+    case 0x3:
+        /* Effectively a 16-bit load.  */
+        tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
+        len = 16;
+        goto one_insert;
+
+    case 0x8:
+    case 0x4:
+    case 0x2:
+    case 0x1:
+        /* Effectively an 8-bit load.  */
+        tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
+        len = 8;
+        goto one_insert;
+
+    one_insert:
+        pos = base + ctz32(m3) * 8;
+        tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
+        ccm = ((1ull << len) - 1) << pos;
+        break;
+
+    default:
+        /* This is going to be a sequence of loads and inserts.  */
+        pos = base + 32 - 8;
+        ccm = 0;
+        while (m3) {
+            if (m3 & 0x8) {
+                tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
+                tcg_gen_addi_i64(o->in2, o->in2, 1);
+                tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
+                ccm |= 0xff << pos;
+            }
+            m3 = (m3 << 1) & 0xf;
+            pos -= 8;
+        }
+        break;
+    }
+
+    tcg_gen_movi_i64(tmp, ccm);
+    gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
+    tcg_temp_free_i64(tmp);
+    return NO_EXIT;
+}
+
 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
 {
     int shift = s->insn->data & 0xff;
commit 443aaeb8991022f3eadd2b65e14e805093e2a0e6
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 12:36:10 2012 -0700

    target-s390: Cleanup cc computation helpers
    
    The inline markers hid the fact that {n}abs_32 were unused
    because of typos in the main do_calc_cc function.  Let the
    compiler handle auto-inlining here.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index d20342c..3d89fb9 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -29,8 +29,7 @@
 #define HELPER_LOG(x...)
 #endif
 
-static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
-                                       int32_t dst)
+static uint32_t cc_calc_ltgt_32(int32_t src, int32_t dst)
 {
     if (src == dst) {
         return 0;
@@ -41,13 +40,12 @@ static inline uint32_t cc_calc_ltgt_32(CPUS390XState *env, int32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_ltgt0_32(int32_t dst)
 {
-    return cc_calc_ltgt_32(env, dst, 0);
+    return cc_calc_ltgt_32(dst, 0);
 }
 
-static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
-                                       int64_t dst)
+static uint32_t cc_calc_ltgt_64(int64_t src, int64_t dst)
 {
     if (src == dst) {
         return 0;
@@ -58,13 +56,12 @@ static inline uint32_t cc_calc_ltgt_64(CPUS390XState *env, int64_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltgt0_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_ltgt0_64(int64_t dst)
 {
-    return cc_calc_ltgt_64(env, dst, 0);
+    return cc_calc_ltgt_64(dst, 0);
 }
 
-static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
-                                         uint32_t dst)
+static uint32_t cc_calc_ltugtu_32(uint32_t src, uint32_t dst)
 {
     if (src == dst) {
         return 0;
@@ -75,8 +72,7 @@ static inline uint32_t cc_calc_ltugtu_32(CPUS390XState *env, uint32_t src,
     }
 }
 
-static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
-                                         uint64_t dst)
+static uint32_t cc_calc_ltugtu_64(uint64_t src, uint64_t dst)
 {
     if (src == dst) {
         return 0;
@@ -87,7 +83,7 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
     }
 }
 
-static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
+static uint32_t cc_calc_tm_32(uint32_t val, uint32_t mask)
 {
     uint32_t r = val & mask;
 
@@ -100,7 +96,7 @@ static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
     }
 }
 
-static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
+static uint32_t cc_calc_tm_64(uint64_t val, uint64_t mask)
 {
     uint64_t r = val & mask;
 
@@ -118,13 +114,12 @@ static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
     }
 }
 
-static inline uint32_t cc_calc_nz(CPUS390XState *env, uint64_t dst)
+static uint32_t cc_calc_nz(uint64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
+static uint32_t cc_calc_add_64(int64_t a1, int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -139,14 +134,12 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
     }
 }
 
-static uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addu_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     return (ar != 0) + 2 * (ar < a1);
 }
 
-static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addc_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     /* Recover a2 + carry_in.  */
     uint64_t a2c = ar - a1;
@@ -156,8 +149,7 @@ static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
     return (ar != 0) + 2 * carry_out;
 }
 
-static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
-                                      int64_t a2, int64_t ar)
+static uint32_t cc_calc_sub_64(int64_t a1, int64_t a2, int64_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -172,8 +164,7 @@ static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
     }
 }
 
-static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
-                                       uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subu_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -186,8 +177,7 @@ static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
     }
 }
 
-static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
-                                uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_subb_64(uint64_t a1, uint64_t a2, uint64_t ar)
 {
     /* We had borrow-in if normal subtraction isn't equal.  */
     int borrow_in = ar - (a1 - a2);
@@ -205,7 +195,7 @@ static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
     return (ar != 0) + 2 * !borrow_out;
 }
 
-static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_abs_64(int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -216,12 +206,12 @@ static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_nabs_64(int64_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
+static uint32_t cc_calc_comp_64(int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
         return 3;
@@ -235,8 +225,7 @@ static inline uint32_t cc_calc_comp_64(CPUS390XState *env, int64_t dst)
 }
 
 
-static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
+static uint32_t cc_calc_add_32(int32_t a1, int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 > 0 && ar < 0) || (a1 < 0 && a2 < 0 && ar > 0)) {
         return 3; /* overflow */
@@ -251,14 +240,12 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
     }
 }
 
-static uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addu_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     return (ar != 0) + 2 * (ar < a1);
 }
 
-static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addc_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     /* Recover a2 + carry_in.  */
     uint32_t a2c = ar - a1;
@@ -268,8 +255,7 @@ static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
     return (ar != 0) + 2 * carry_out;
 }
 
-static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
-                                      int32_t a2, int32_t ar)
+static uint32_t cc_calc_sub_32(int32_t a1, int32_t a2, int32_t ar)
 {
     if ((a1 > 0 && a2 < 0 && ar < 0) || (a1 < 0 && a2 > 0 && ar > 0)) {
         return 3; /* overflow */
@@ -284,8 +270,7 @@ static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
     }
 }
 
-static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
-                                       uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subu_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     if (ar == 0) {
         return 2;
@@ -298,8 +283,7 @@ static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
     }
 }
 
-static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
-                                uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_subb_32(uint32_t a1, uint32_t a2, uint32_t ar)
 {
     /* We had borrow-in if normal subtraction isn't equal.  */
     int borrow_in = ar - (a1 - a2);
@@ -317,7 +301,7 @@ static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
     return (ar != 0) + 2 * !borrow_out;
 }
 
-static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_abs_32(int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -328,12 +312,12 @@ static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
     }
 }
 
-static inline uint32_t cc_calc_nabs_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_nabs_32(int32_t dst)
 {
     return !!dst;
 }
 
-static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
+static uint32_t cc_calc_comp_32(int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
         return 3;
@@ -347,8 +331,7 @@ static inline uint32_t cc_calc_comp_32(CPUS390XState *env, int32_t dst)
 }
 
 /* calculate condition code for insert character under mask insn */
-static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
-                                      uint32_t val)
+static uint32_t cc_calc_icm_32(uint32_t mask, uint32_t val)
 {
     uint32_t cc;
 
@@ -379,8 +362,7 @@ static inline uint32_t cc_calc_icm_32(CPUS390XState *env, uint32_t mask,
     return cc;
 }
 
-static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
-                                    uint64_t shift)
+static uint32_t cc_calc_slag(uint64_t src, uint64_t shift)
 {
     uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift);
     uint64_t match, r;
@@ -409,7 +391,7 @@ static inline uint32_t cc_calc_slag(CPUS390XState *env, uint64_t src,
 }
 
 
-static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
+static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
                                   uint64_t src, uint64_t dst, uint64_t vr)
 {
     uint32_t r = 0;
@@ -423,93 +405,93 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
         r = cc_op;
         break;
     case CC_OP_LTGT0_32:
-        r = cc_calc_ltgt0_32(env, dst);
+        r = cc_calc_ltgt0_32(dst);
         break;
     case CC_OP_LTGT0_64:
-        r =  cc_calc_ltgt0_64(env, dst);
+        r =  cc_calc_ltgt0_64(dst);
         break;
     case CC_OP_LTGT_32:
-        r =  cc_calc_ltgt_32(env, src, dst);
+        r =  cc_calc_ltgt_32(src, dst);
         break;
     case CC_OP_LTGT_64:
-        r =  cc_calc_ltgt_64(env, src, dst);
+        r =  cc_calc_ltgt_64(src, dst);
         break;
     case CC_OP_LTUGTU_32:
-        r =  cc_calc_ltugtu_32(env, src, dst);
+        r =  cc_calc_ltugtu_32(src, dst);
         break;
     case CC_OP_LTUGTU_64:
-        r =  cc_calc_ltugtu_64(env, src, dst);
+        r =  cc_calc_ltugtu_64(src, dst);
         break;
     case CC_OP_TM_32:
-        r =  cc_calc_tm_32(env, src, dst);
+        r =  cc_calc_tm_32(src, dst);
         break;
     case CC_OP_TM_64:
-        r =  cc_calc_tm_64(env, src, dst);
+        r =  cc_calc_tm_64(src, dst);
         break;
     case CC_OP_NZ:
-        r =  cc_calc_nz(env, dst);
+        r =  cc_calc_nz(dst);
         break;
     case CC_OP_ADD_64:
-        r =  cc_calc_add_64(env, src, dst, vr);
+        r =  cc_calc_add_64(src, dst, vr);
         break;
     case CC_OP_ADDU_64:
-        r =  cc_calc_addu_64(env, src, dst, vr);
+        r =  cc_calc_addu_64(src, dst, vr);
         break;
     case CC_OP_ADDC_64:
-        r =  cc_calc_addc_64(env, src, dst, vr);
+        r =  cc_calc_addc_64(src, dst, vr);
         break;
     case CC_OP_SUB_64:
-        r =  cc_calc_sub_64(env, src, dst, vr);
+        r =  cc_calc_sub_64(src, dst, vr);
         break;
     case CC_OP_SUBU_64:
-        r =  cc_calc_subu_64(env, src, dst, vr);
+        r =  cc_calc_subu_64(src, dst, vr);
         break;
     case CC_OP_SUBB_64:
-        r =  cc_calc_subb_64(env, src, dst, vr);
+        r =  cc_calc_subb_64(src, dst, vr);
         break;
     case CC_OP_ABS_64:
-        r =  cc_calc_abs_64(env, dst);
+        r =  cc_calc_abs_64(dst);
         break;
     case CC_OP_NABS_64:
-        r =  cc_calc_nabs_64(env, dst);
+        r =  cc_calc_nabs_64(dst);
         break;
     case CC_OP_COMP_64:
-        r =  cc_calc_comp_64(env, dst);
+        r =  cc_calc_comp_64(dst);
         break;
 
     case CC_OP_ADD_32:
-        r =  cc_calc_add_32(env, src, dst, vr);
+        r =  cc_calc_add_32(src, dst, vr);
         break;
     case CC_OP_ADDU_32:
-        r =  cc_calc_addu_32(env, src, dst, vr);
+        r =  cc_calc_addu_32(src, dst, vr);
         break;
     case CC_OP_ADDC_32:
-        r =  cc_calc_addc_32(env, src, dst, vr);
+        r =  cc_calc_addc_32(src, dst, vr);
         break;
     case CC_OP_SUB_32:
-        r =  cc_calc_sub_32(env, src, dst, vr);
+        r =  cc_calc_sub_32(src, dst, vr);
         break;
     case CC_OP_SUBU_32:
-        r =  cc_calc_subu_32(env, src, dst, vr);
+        r =  cc_calc_subu_32(src, dst, vr);
         break;
     case CC_OP_SUBB_32:
-        r =  cc_calc_subb_32(env, src, dst, vr);
+        r =  cc_calc_subb_32(src, dst, vr);
         break;
     case CC_OP_ABS_32:
-        r =  cc_calc_abs_64(env, dst);
+        r =  cc_calc_abs_32(dst);
         break;
     case CC_OP_NABS_32:
-        r =  cc_calc_nabs_64(env, dst);
+        r =  cc_calc_nabs_32(dst);
         break;
     case CC_OP_COMP_32:
-        r =  cc_calc_comp_32(env, dst);
+        r =  cc_calc_comp_32(dst);
         break;
 
     case CC_OP_ICM:
-        r =  cc_calc_icm_32(env, src, dst);
+        r =  cc_calc_icm_32(src, dst);
         break;
     case CC_OP_SLAG:
-        r =  cc_calc_slag(env, src, dst);
+        r =  cc_calc_slag(src, dst);
         break;
 
     case CC_OP_LTGT_F32:
commit afdc70bea01452367e372db7e2168b71bb3aa9b3
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Aug 21 07:12:29 2012 -0700

    target-s390: Convert INSERT CHARACTER
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index c3b1f6f..f37e69a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -157,6 +157,9 @@
     D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
     D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
 
+/* INSERT CHARACTER */
+    C(0x4300, IC,      RX_a,  Z,   0, m2_8u, 0, r1_8, mov2, 0)
+    C(0xe373, ICY,     RXY_a, LD,  0, m2_8u, 0, r1_8, mov2, 0)
 /* INSERT IMMEDIATE */
     D(0xc008, IIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
     D(0xc009, IILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index d459b25..25bbf45 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -283,12 +283,6 @@ static inline void store_reg16(int reg, TCGv_i32 v)
 #endif
 }
 
-static inline void store_reg8(int reg, TCGv_i64 v)
-{
-    /* 8 bit register writes keep the upper bytes */
-    tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 8);
-}
-
 static inline void store_freg32(int reg, TCGv_i32 v)
 {
     /* 32 bit register writes keep the lower half */
@@ -1244,7 +1238,7 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
 static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
                      int x2, int b2, int d2)
 {
-    TCGv_i64 addr, tmp2, tmp3;
+    TCGv_i64 addr, tmp2;
     TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
@@ -1294,12 +1288,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
-        store_reg8(r1, tmp3);
-        tcg_temp_free_i64(tmp3);
-        break;
     default:
         LOG_DISAS("illegal e3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2383,15 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x43: /* IC     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
-        store_reg8(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x44: /* EX     R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3922,6 +3901,12 @@ static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg(get_field(f, r1), o->out);
 }
 
+static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r1 = get_field(f, r1);
+    tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
+}
+
 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg32_i64(get_field(f, r1), o->out);
@@ -4180,6 +4165,12 @@ static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
 }
 
+static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
+}
+
 static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
commit d764a8d12b24c8b97fe3ff2193aec04079e8db20
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 12:24:24 2012 -0700

    target-s390: Convert FP LOAD
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 995c0f6..c3b1f6f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -173,6 +173,13 @@
     C(0xb914, LGFR,    RRE,   Z,   0, r2_32s, 0, r1, mov2, 0)
     C(0xe304, LG,      RXY_a, Z,   0, a2, r1, 0, ld64, 0)
     C(0xe314, LGF,     RXY_a, Z,   0, a2, r1, 0, ld32s, 0)
+    C(0x2800, LDR,     RR_a,  Z,   0, f2_o, 0, f1, mov2, 0)
+    C(0x6800, LD,      RX_a,  Z,   0, m2_64, 0, f1, mov2, 0)
+    C(0xed65, LDY,     RXY_a, LD,  0, m2_64, 0, f1, mov2, 0)
+    C(0x3800, LER,     RR_a,  Z,   0, e2, 0, cond_e1e2, mov2, 0)
+    C(0x7800, LE,      RX_a,  Z,   0, m2_32u, 0, e1, mov2, 0)
+    C(0xed64, LEY,     RXY_a, LD,  0, m2_32u, 0, e1, mov2, 0)
+    C(0xb365, LXR,     RRE,   Z,   0, x2_o, 0, x1, movx, 0)
 /* LOAD IMMEDIATE */
     C(0xc001, LGFI,    RIL_a, EI,  0, i2, 0, r1, mov2, 0)
 /* LOAD RELATIVE LONG */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0437f9b..d459b25 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -224,6 +224,13 @@ static inline TCGv_i32 load_freg32(int reg)
     return r;
 }
 
+static inline TCGv_i64 load_freg32_i64(int reg)
+{
+    TCGv_i64 r = tcg_temp_new_i64();
+    tcg_gen_shri_i64(r, fregs[reg], 32);
+    return r;
+}
+
 static inline TCGv_i32 load_reg32(int reg)
 {
     TCGv_i32 r = tcg_temp_new_i32();
@@ -293,6 +300,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
 #endif
 }
 
+static inline void store_freg32_i64(int reg, TCGv_i64 v)
+{
+    tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
+}
+
 static inline void return_low128(TCGv_i64 dest)
 {
     tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
@@ -2371,20 +2383,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x28: /* LDR    R1,R2               [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp = load_freg(r2);
-        store_freg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x38: /* LER    R1,R2               [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_freg32(r2);
-        store_freg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x43: /* IC     R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2427,15 +2425,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x68: /* LD    R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
-        store_freg(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x70: /* STE R1,D2(X2,B2) [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2447,18 +2436,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x78: /* LE     R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        store_freg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0x80: /* SSM      D2(B2)       [S] */
         /* Set System Mask */
@@ -3596,6 +3573,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_movx(DisasContext *s, DisasOps *o)
+{
+    o->out = o->in1;
+    o->out2 = o->in2;
+    o->g_out = o->g_in1;
+    o->g_out2 = o->g_in2;
+    TCGV_UNUSED_I64(o->in1);
+    TCGV_UNUSED_I64(o->in2);
+    o->g_in1 = o->g_in2 = false;
+    return NO_EXIT;
+}
+
 static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
@@ -3955,6 +3944,23 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg32_i64(r1, o->out);
 }
 
+static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_freg32_i64(get_field(f, r1), o->out);
+}
+
+static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_freg(get_field(f, r1), o->out);
+}
+
+static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int f1 = get_field(s->fields, r1);
+    store_freg(f1, o->out);
+    store_freg((f1 + 2) & 15, o->out2);
+}
+
 static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     if (get_field(f, r1) != get_field(f, r2)) {
@@ -3962,6 +3968,13 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
     }
 }
 
+static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    if (get_field(f, r1) != get_field(f, r2)) {
+        store_freg32_i64(get_field(f, r1), o->out);
+    }
+}
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@@ -4137,6 +4150,25 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
 }
 
+static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = load_freg32_i64(get_field(f, r2));
+}
+
+static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = fregs[get_field(f, r2)];
+    o->g_in2 = true;
+}
+
+static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int f2 = get_field(f, r2);
+    o->in1 = fregs[f2];
+    o->in2 = fregs[(f2 + 2) & 15];
+    o->g_in1 = o->g_in2 = true;
+}
+
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
commit e1eaada955aab907b53a091b85421de9e8b8dd9c
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 16:46:49 2012 -0700

    target-s390: Convert MOVE LONG
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7a0c999..995c0f6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -246,6 +246,9 @@
     C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
     C(0xb910, LPGFR,   RRE,   Z,   0, r2_32s, r1, 0, abs, abs64)
 
+/* MOVE LONG */
+    C(0x0e00, MVCL,    RR_a,  Z,   0, 0, 0, 0, mvcl, 0)
+
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
     C(0x5c00, M,       RX_a,  Z,   r1p1_32s, m2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e2b7671..0437f9b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,17 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0xe: /* MVCL   R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_const_i32(r2);
-        potential_page_fault(s);
-        gen_helper_mvcl(cc_op, cpu_env, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x28: /* LDR    R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3607,6 +3596,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
+    TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
+    potential_page_fault(s);
+    gen_helper_mvcl(cc_op, cpu_env, r1, r2);
+    tcg_temp_free_i32(r1);
+    tcg_temp_free_i32(r2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
commit b9836c1acd4ecb286bd1617857cc52df7b75c414
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 16:41:05 2012 -0700

    target-s390: Convert SUPERVISOR CALL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 69af25d..7a0c999 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -337,6 +337,9 @@
     C(0xe399, SLB,     RXY_a, Z,   r1, m2_32u, new, r1_32, subb, subb32)
     C(0xe389, SLBG,    RXY_a, Z,   r1, m2_64, r1, 0, subb, subb64)
 
+/* SUPERVISOR CALL */
+    C(0x0a00, SVC,     I,     Z,   0, 0, 0, 0, svc, 0)
+
 /* TEST UNDER MASK */
     C(0x9100, TM,      SI,    Z,   m1_8u, i2_8u, 0, 0, 0, tm32)
     C(0xeb51, TMY,     SIY,   LD,  m1_8u, i2_8u, 0, 0, 0, tm32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 26ca49b..e2b7671 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,21 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0xa: /* SVC    I         [RR] */
-        insn = ld_code2(env, s->pc);
-        debug_insn(insn);
-        i = insn & 0xff;
-        update_psw_addr(s);
-        gen_op_calc_cc(s);
-        tmp32_1 = tcg_const_i32(i);
-        tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
-        tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
-        gen_exception(EXCP_SVC);
-        s->is_jmp = DISAS_EXCP;
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0xe: /* MVCL   R1,R2     [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3717,6 +3702,25 @@ static ExitStatus op_subb(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_svc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i32 t;
+
+    update_psw_addr(s);
+    gen_op_calc_cc(s);
+
+    t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
+    tcg_temp_free_i32(t);
+
+    t = tcg_const_i32(s->next_pc - s->pc);
+    tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
+    tcg_temp_free_i32(t);
+
+    gen_exception(EXCP_SVC);
+    return EXIT_NORETURN;
+}
+
 static ExitStatus op_xor(DisasContext *s, DisasOps *o)
 {
     tcg_gen_xor_i64(o->out, o->in1, o->in2);
commit d9a39927993a186b039d5be66cc85c0e735a78bc
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 16:28:56 2012 -0700

    target-s390: Convert SET ADDRESSING MODE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f70ede9..69af25d 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -344,3 +344,10 @@
     D(0xa703, TMHL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
     D(0xa700, TMLH,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
     D(0xa701, TMLL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
+
+#ifndef CONFIG_USER_ONLY
+/* SET ADDRESSING MODE */
+    /* We only do 64-bit, so accept this as a no-op.
+       Let SAM24 and SAM31 signal illegal instruction.  */
+    C(0x010e, SAM64,   E,     Z,   0, 0, 0, 0, 0, 0)
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4e34519..26ca49b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2371,12 +2371,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-#ifndef CONFIG_USER_ONLY
-    case 0x01: /* SAM */
-        insn = ld_code2(env, s->pc);
-        /* set addressing mode, but we only do 64bit anyways */
-        break;
-#endif
     case 0xa: /* SVC    I         [RR] */
         insn = ld_code2(env, s->pc);
         debug_insn(insn);
commit 00d2dc192fb866d077935f0dd298472d65d87eb6
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 16:20:58 2012 -0700

    target-s390: Convert TEST UNDER MASK
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 880e3b2..d20342c 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -20,6 +20,7 @@
 
 #include "cpu.h"
 #include "helper.h"
+#include "qemu/host-utils.h"
 
 /* #define DEBUG_HELPER */
 #ifdef DEBUG_HELPER
@@ -86,13 +87,11 @@ static inline uint32_t cc_calc_ltugtu_64(CPUS390XState *env, uint64_t src,
     }
 }
 
-static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
-                                     uint32_t mask)
+static uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val, uint32_t mask)
 {
-    uint16_t r = val & mask;
+    uint32_t r = val & mask;
 
-    HELPER_LOG("%s: val 0x%x mask 0x%x\n", __func__, val, mask);
-    if (r == 0 || mask == 0) {
+    if (r == 0) {
         return 0;
     } else if (r == mask) {
         return 3;
@@ -101,23 +100,17 @@ static inline uint32_t cc_calc_tm_32(CPUS390XState *env, uint32_t val,
     }
 }
 
-/* set condition code for test under mask */
-static inline uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val,
-                                     uint32_t mask)
+static uint32_t cc_calc_tm_64(CPUS390XState *env, uint64_t val, uint64_t mask)
 {
-    uint16_t r = val & mask;
+    uint64_t r = val & mask;
 
-    HELPER_LOG("%s: val 0x%lx mask 0x%x r 0x%x\n", __func__, val, mask, r);
-    if (r == 0 || mask == 0) {
+    if (r == 0) {
         return 0;
     } else if (r == mask) {
         return 3;
     } else {
-        while (!(mask & 0x8000)) {
-            mask <<= 1;
-            val <<= 1;
-        }
-        if (val & 0x8000) {
+        int top = clz64(mask);
+        if ((int64_t)(val << top) < 0) {
             return 2;
         } else {
             return 1;
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 921c216..f70ede9 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -336,3 +336,11 @@
     C(0xb989, SLBGR,   RRE,   Z,   r1, r2, r1, 0, subb, subb64)
     C(0xe399, SLB,     RXY_a, Z,   r1, m2_32u, new, r1_32, subb, subb32)
     C(0xe389, SLBG,    RXY_a, Z,   r1, m2_64, r1, 0, subb, subb64)
+
+/* TEST UNDER MASK */
+    C(0x9100, TM,      SI,    Z,   m1_8u, i2_8u, 0, 0, 0, tm32)
+    C(0xeb51, TMY,     SIY,   LD,  m1_8u, i2_8u, 0, 0, 0, tm32)
+    D(0xa702, TMHH,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 48)
+    D(0xa703, TMHL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 32)
+    D(0xa700, TMLH,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 16)
+    D(0xa701, TMLL,    RI_a,  Z,   r1_o, i2_16u_shl, 0, 0, 0, tm64, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5667155..4e34519 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1514,16 +1514,6 @@ do_mh:
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x51: /* TMY D1(B1),I2 [SIY] */
-        tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
-        tmp2 = tcg_const_i64((r1 << 4) | r3);
-        tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
-        /* yes, this is a 32 bit operation with 64 bit tcg registers, because
-           that incurs less conversions */
-        cmp_64(s, tmp, tmp2, CC_OP_TM_32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x52: /* MVIY D1(B1),I2 [SIY] */
         tmp = get_address(s, 0, b2, d2); /* SIY -> this is the destination */
         tmp2 = tcg_const_i64((r1 << 4) | r3);
@@ -1672,44 +1662,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
     tcg_temp_free_i64(addr);
 }
 
-static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int i2)
-{
-    TCGv_i64 tmp, tmp2;
-
-    LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
-    switch (op) {
-    case 0x0: /* TMLH or TMH     R1,I2     [RI] */
-    case 0x1: /* TMLL or TML     R1,I2     [RI] */
-    case 0x2: /* TMHH     R1,I2     [RI] */
-    case 0x3: /* TMHL     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tmp2 = tcg_const_i64((uint16_t)i2);
-        switch (op) {
-        case 0x0:
-            tcg_gen_shri_i64(tmp, tmp, 16);
-            break;
-        case 0x1:
-            break;
-        case 0x2:
-            tcg_gen_shri_i64(tmp, tmp, 48);
-            break;
-        case 0x3:
-            tcg_gen_shri_i64(tmp, tmp, 32);
-            break;
-        }
-        tcg_gen_andi_i64(tmp, tmp, 0xffff);
-        cmp_64(s, tmp, tmp2, CC_OP_TM_64);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    default:
-        LOG_DISAS("illegal a7 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        return;
-    }
-}
-
 static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
                      uint32_t insn)
 {
@@ -2678,15 +2630,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp3);
         tcg_temp_free_i64(tmp4);
         break;
-    case 0x91: /* TM     D1(B1),I2        [SI] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_si(s, insn, &i2, &b1, &d1);
-        tmp2 = tcg_const_i64(i2);
-        tcg_gen_qemu_ld8u(tmp, tmp, get_mem_index(s));
-        cmp_64(s, tmp, tmp2, CC_OP_TM_32);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x92: /* MVI    D1(B1),I2        [SI] */
         insn = ld_code4(env, s->pc);
         tmp = decode_si(s, insn, &i2, &b1, &d1);
@@ -2744,13 +2687,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xa7:
-        insn = ld_code4(env, s->pc);
-        r1 = (insn >> 20) & 0xf;
-        op = (insn >> 16) & 0xf;
-        i2 = (short)insn;
-        disas_a7(env, s, op, r1, i2);
-        break;
     case 0xa8: /* MVCLE   R1,R3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -3945,6 +3881,16 @@ static void cout_subb64(DisasContext *s, DisasOps *o)
     gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
 }
 
+static void cout_tm32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
+}
+
+static void cout_tm64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
+}
+
 /* ====================================================================== */
 /* The "PREPeration" generators.  These initialize the DisasOps.OUT fields
    with the TCG register to which we will write.  Used in combination with
commit b4e2bd3563af75ba5b9fe809c8cf79d2d34aecf3
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 17:27:40 2012 -0700

    target-s390: Send signals for divide
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index ea1bc86..69269a1 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -931,5 +931,7 @@ uint32_t set_cc_nz_f64(float64 v);
 
 /* misc_helper.c */
 void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
+void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
+                                     uintptr_t retaddr);
 
 #endif
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index 80e17f5..839c0e1 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -38,22 +38,54 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
 }
 
 /* 64/32 -> 32 signed division */
-int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b)
+int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b64)
 {
-    env->retxl = a % (int32_t)b;
-    return a / (int32_t)b;
+    int32_t ret, b = b64;
+    int64_t q;
+
+    if (b == 0) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
+
+    ret = q = a / b;
+    env->retxl = a % b;
+
+    /* Catch non-representable quotient.  */
+    if (ret != q) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
+
+    return ret;
 }
 
 /* 64/32 -> 32 unsigned division */
-uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b)
+uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b64)
 {
-    env->retxl = a % (uint32_t)b;
-    return a / (uint32_t)b;
+    uint32_t ret, b = b64;
+    uint64_t q;
+
+    if (b == 0) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
+
+    ret = q = a / b;
+    env->retxl = a % b;
+
+    /* Catch non-representable quotient.  */
+    if (ret != q) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
+
+    return ret;
 }
 
 /* 64/64 -> 64 signed division */
 int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
 {
+    /* Catch divide by zero, and non-representable quotient (MIN / -1).  */
+    if (b == 0 || (b == -1 && a == (1ll << 63))) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
     env->retxl = a % b;
     return a / b;
 }
@@ -63,6 +95,10 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
                         uint64_t b)
 {
     uint64_t ret;
+    /* Signal divide by zero.  */
+    if (b == 0) {
+        runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+    }
     if (ah == 0) {
         /* 64 -> 64/64 case */
         env->retxl = al % b;
@@ -75,6 +111,9 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
         __uint128_t q = a / b;
         env->retxl = a % b;
         ret = q;
+        if (ret != q) {
+            runtime_exception(env, PGM_FIXPT_DIVIDE, GETPC());
+        }
 #else
         /* 32-bit hosts would need special wrapper functionality - just abort if
            we encounter such a case; it's very unlikely anyways. */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 2aa1ed0..6dca0eb 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -41,6 +41,26 @@
 #define HELPER_LOG(x...)
 #endif
 
+/* Raise an exception dynamically from a helper function.  */
+void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
+                                     uintptr_t retaddr)
+{
+    int t;
+
+    env->exception_index = EXCP_PGM;
+    env->int_pgm_code = excp;
+
+    /* Use the (ultimate) callers address to find the insn that trapped.  */
+    cpu_restore_state(env, retaddr);
+
+    /* Advance past the insn.  */
+    t = cpu_ldub_code(env, env->psw.addr);
+    env->int_pgm_ilen = t = get_ilen(t);
+    env->psw.addr += 2 * t;
+
+    cpu_loop_exit(env);
+}
+
 /* Raise an exception statically from a TB.  */
 void HELPER(exception)(CPUS390XState *env, uint32_t excp)
 {
commit 891452e5e274967ffb87d10791620154f2cdc303
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 14:02:02 2012 -0700

    target-s390: Convert DIVIDE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index a45b1c3..dcc3fce 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -10,7 +10,10 @@ DEF_HELPER_3(mvcl, i32, env, i32, i32)
 DEF_HELPER_4(clm, i32, env, i32, i32, i64)
 DEF_HELPER_4(stcm, void, env, i32, i32, i64)
 DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
-DEF_HELPER_3(dlg, void, env, i32, i64)
+DEF_HELPER_3(divs32, s64, env, s64, s64)
+DEF_HELPER_3(divu32, i64, env, i64, i64)
+DEF_HELPER_3(divs64, s64, env, s64, s64)
+DEF_HELPER_4(divu64, i64, env, i64, i64, i64)
 DEF_HELPER_4(srst, i32, env, i32, i32, i32)
 DEF_HELPER_4(clst, i32, env, i32, i32, i32)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 8ea6630..921c216 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -131,6 +131,20 @@
     C(0xc607, CLHRL,   RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
     C(0xc606, CLGHRL,  RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
 
+/* DIVIDE */
+    C(0x1d00, DR,      RR_a,  Z,   r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
+    C(0x5d00, D,       RX_a,  Z,   r1_D32, m2_32s, new_P, r1_P32, divs32, 0)
+/* DIVIDE LOGICAL */
+    C(0xb997, DLR,     RRE,   Z,   r1_D32, r2_32u, new_P, r1_P32, divu32, 0)
+    C(0xe397, DL,      RXY_a, Z,   r1_D32, m2_32u, new_P, r1_P32, divu32, 0)
+    C(0xb987, DLGR,    RRE,   Z,   0, r2_o, r1_P, 0, divu64, 0)
+    C(0xe387, DLG,     RXY_a, Z,   0, m2_64, r1_P, 0, divu64, 0)
+/* DIVIDE SINGLE */
+    C(0xb90d, DSGR,    RRE,   Z,   r1p1, r2, r1_P, 0, divs64, 0)
+    C(0xb91d, DSGFR,   RRE,   Z,   r1p1, r2_32s, r1_P, 0, divs64, 0)
+    C(0xe30d, DSG,     RXY_a, Z,   r1p1, m2_64, r1_P, 0, divs64, 0)
+    C(0xe31d, DSGF,    RXY_a, Z,   r1p1, m2_32s, r1_P, 0, divs64, 0)
+
 /* EXCLUSIVE OR */
     C(0x1700, XR,      RR_a,  Z,   r1, r2, new, r1_32, xor, nz32)
     C(0xb9f7, XRK,     RRF_a, DO,  r2, r3, new, r1_32, xor, nz32)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index 17c4771..80e17f5 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -37,32 +37,51 @@ uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
     return reth;
 }
 
-/* 128 -> 64/64 unsigned division */
-void HELPER(dlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+/* 64/32 -> 32 signed division */
+int64_t HELPER(divs32)(CPUS390XState *env, int64_t a, int64_t b)
+{
+    env->retxl = a % (int32_t)b;
+    return a / (int32_t)b;
+}
+
+/* 64/32 -> 32 unsigned division */
+uint64_t HELPER(divu32)(CPUS390XState *env, uint64_t a, uint64_t b)
 {
-    uint64_t divisor = v2;
+    env->retxl = a % (uint32_t)b;
+    return a / (uint32_t)b;
+}
 
-    if (!env->regs[r1]) {
+/* 64/64 -> 64 signed division */
+int64_t HELPER(divs64)(CPUS390XState *env, int64_t a, int64_t b)
+{
+    env->retxl = a % b;
+    return a / b;
+}
+
+/* 128 -> 64/64 unsigned division */
+uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al,
+                        uint64_t b)
+{
+    uint64_t ret;
+    if (ah == 0) {
         /* 64 -> 64/64 case */
-        env->regs[r1] = env->regs[r1 + 1] % divisor;
-        env->regs[r1 + 1] = env->regs[r1 + 1] / divisor;
-        return;
+        env->retxl = al % b;
+        ret = al / b;
     } else {
+        /* ??? Move i386 idivq helper to host-utils.  */
 #if HOST_LONG_BITS == 64 && defined(__GNUC__)
         /* assuming 64-bit hosts have __uint128_t */
-        __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) |
-            (env->regs[r1 + 1]);
-        __uint128_t quotient = dividend / divisor;
-        __uint128_t remainder = dividend % divisor;
-
-        env->regs[r1 + 1] = quotient;
-        env->regs[r1] = remainder;
+        __uint128_t a = ((__uint128_t)ah << 64) | al;
+        __uint128_t q = a / b;
+        env->retxl = a % b;
+        ret = q;
 #else
         /* 32-bit hosts would need special wrapper functionality - just abort if
            we encounter such a case; it's very unlikely anyways. */
         cpu_abort(env, "128 -> 64/64 division not implemented\n");
 #endif
     }
+    return ret;
 }
 
 /* absolute value 32-bit */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index fdf0129..5667155 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1232,31 +1232,13 @@ static void gen_op_clc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
 static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
                      int x2, int b2, int d2)
 {
-    TCGv_i64 addr, tmp, tmp2, tmp3, tmp4;
+    TCGv_i64 addr, tmp2, tmp3;
     TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
               op, r1, x2, b2, d2);
     addr = get_address(s, x2, b2, d2);
     switch (op) {
-    case 0xd: /* DSG      R1,D2(X2,B2)     [RXY] */
-    case 0x1d: /* DSGF      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        if (op == 0x1d) {
-            tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        } else {
-            tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        }
-        tmp4 = load_reg(r1 + 1);
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_div_i64(tmp3, tmp4, tmp2);
-        store_reg(r1 + 1, tmp3);
-        tcg_gen_rem_i64(tmp3, tmp4, tmp2);
-        store_reg(r1, tmp3);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i64(tmp4);
-        break;
     case 0xf: /* LRVG     R1,D2(X2,B2)     [RXE] */
         tmp2 = tcg_temp_new_i64();
         tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
@@ -1306,34 +1288,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg8(r1, tmp3);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x87: /* DLG      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_const_i32(r1);
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        gen_helper_dlg(cpu_env, tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x97: /* DL     R1,D2(X2,B2)     [RXY] */
-        /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
-        /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
-        tmp = load_reg(r1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32u_i64(tmp2, tmp2);
-        tcg_gen_ext32u_i64(tmp3, tmp3);
-        tcg_gen_shli_i64(tmp, tmp, 32);
-        tcg_gen_or_i64(tmp, tmp, tmp3);
-
-        tcg_gen_rem_i64(tmp3, tmp, tmp2);
-        tcg_gen_div_i64(tmp, tmp, tmp2);
-        store_reg32_i64((r1 + 1) & 15, tmp);
-        store_reg32_i64(r1, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     default:
         LOG_DISAS("illegal e3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2414,31 +2368,11 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
 static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int r2)
 {
-    TCGv_i64 tmp, tmp2, tmp3;
+    TCGv_i64 tmp;
     TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
     switch (op) {
-    case 0xd: /* DSGR      R1,R2     [RRE] */
-    case 0x1d: /* DSGFR      R1,R2     [RRE] */
-        tmp = load_reg(r1 + 1);
-        if (op == 0xd) {
-            tmp2 = load_reg(r2);
-        } else {
-            tmp32_1 = load_reg32(r2);
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_ext_i32_i64(tmp2, tmp32_1);
-            tcg_temp_free_i32(tmp32_1);
-        }
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_div_i64(tmp3, tmp, tmp2);
-        store_reg(r1 + 1, tmp3);
-        tcg_gen_rem_i64(tmp3, tmp, tmp2);
-        store_reg(r1, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x17: /* LLGTR      R1,R2     [RRE] */
         tmp32_1 = load_reg32(r2);
         tmp = tcg_temp_new_i64();
@@ -2465,32 +2399,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x87: /* DLGR      R1,R2     [RRE] */
-        tmp32_1 = tcg_const_i32(r1);
-        tmp = load_reg(r2);
-        gen_helper_dlg(cpu_env, tmp32_1, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x97: /* DLR     R1,R2     [RRE] */
-        /* reg(r1) = reg(r1, r1+1) % reg(r2) */
-        /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32u_i64(tmp2, tmp2);
-        tcg_gen_ext32u_i64(tmp3, tmp3);
-        tcg_gen_shli_i64(tmp, tmp, 32);
-        tcg_gen_or_i64(tmp, tmp, tmp3);
-
-        tcg_gen_rem_i64(tmp3, tmp, tmp2);
-        tcg_gen_div_i64(tmp, tmp, tmp2);
-        store_reg32_i64((r1 + 1) & 15, tmp);
-        store_reg32_i64(r1, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     default:
         LOG_DISAS("illegal b9 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2543,41 +2451,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x1d: /* DR     R1,R2               [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r1 + 1);
-        tmp32_3 = load_reg32(r2);
-
-        tmp = tcg_temp_new_i64(); /* dividend */
-        tmp2 = tcg_temp_new_i64(); /* divisor */
-        tmp3 = tcg_temp_new_i64();
-
-        /* dividend is r(r1 << 32) | r(r1 + 1) */
-        tcg_gen_extu_i32_i64(tmp, tmp32_1);
-        tcg_gen_extu_i32_i64(tmp2, tmp32_2);
-        tcg_gen_shli_i64(tmp, tmp, 32);
-        tcg_gen_or_i64(tmp, tmp, tmp2);
-
-        /* divisor is r(r2) */
-        tcg_gen_ext_i32_i64(tmp2, tmp32_3);
-
-        tcg_gen_div_i64(tmp3, tmp, tmp2);
-        tcg_gen_rem_i64(tmp, tmp, tmp2);
-
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
-
-        store_reg32(r1, tmp32_1); /* remainder */
-        store_reg32(r1 + 1, tmp32_2); /* quotient */
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x28: /* LDR    R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -2626,40 +2499,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x5d: /* D      R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r1 + 1);
-
-        tmp = tcg_temp_new_i64();
-        tmp2 = tcg_temp_new_i64();
-
-        /* dividend is r(r1 << 32) | r(r1 + 1) */
-        tcg_gen_extu_i32_i64(tmp, tmp32_1);
-        tcg_gen_extu_i32_i64(tmp2, tmp32_2);
-        tcg_gen_shli_i64(tmp, tmp, 32);
-        tcg_gen_or_i64(tmp, tmp, tmp2);
-
-        /* divisor is in memory */
-        tcg_gen_qemu_ld32s(tmp2, tmp3, get_mem_index(s));
-
-        /* XXX divisor == 0 -> FixP divide exception */
-
-        tcg_gen_div_i64(tmp3, tmp, tmp2);
-        tcg_gen_rem_i64(tmp, tmp, tmp2);
-
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp3);
-
-        store_reg32(r1, tmp32_1); /* remainder */
-        store_reg32(r1 + 1, tmp32_2); /* quotient */
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x60: /* STD    R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3766,6 +3605,34 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
+static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
+{
+    gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
+    return_low128(o->out);
+    return NO_EXIT;
+}
+
 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
 {
     int shift = s->insn->data & 0xff;
@@ -4089,6 +3956,12 @@ static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
     o->out = tcg_temp_new_i64();
 }
 
+static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->out = tcg_temp_new_i64();
+    o->out2 = tcg_temp_new_i64();
+}
+
 static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->out = regs[get_field(f, r1)];
@@ -4120,6 +3993,14 @@ static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg32_i64(get_field(f, r1), o->out);
 }
 
+static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    store_reg32_i64(r1, o->out);
+    store_reg32_i64((r1 + 1) & 15, o->out2);
+}
+
 static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     /* ??? Specification exception: r1 must be even.  */
@@ -4183,6 +4064,14 @@ static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
 }
 
+static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
+}
+
 static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r2));
commit c61aad6943cd77046e47cdb5beedad9d035d2216
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 14:22:58 2012 -0700

    target-s390: Convert BRANCH ON COUNT
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0bd05ab..8ea6630 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -74,6 +74,14 @@
 /* BRANCH RELATIVE ON CONDITION */
     C(0xa704, BRC,     RI_c,  Z,   0, 0, 0, 0, bc, 0)
     C(0xc004, BRCL,    RIL_c, Z,   0, 0, 0, 0, bc, 0)
+/* BRANCH ON COUNT */
+    C(0x0600, BCTR,    RR_a,  Z,   0, r2_nz, 0, 0, bct32, 0)
+    C(0xb946, BCTGR,   RRE,   Z,   0, r2_nz, 0, 0, bct64, 0)
+    C(0x4600, BCT,     RX_a,  Z,   0, a2, 0, 0, bct32, 0)
+    C(0xe346, BCTG,    RXY_a, Z,   0, a2, 0, 0, bct64, 0)
+/* BRANCH RELATIVE ON COUNT */
+    C(0xa706, BRCT,    RI_b,  Z,   0, 0, 0, 0, bct32, 0)
+    C(0xa707, BRCTG,   RI_b,  Z,   0, 0, 0, 0, bct64, 0)
 
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index e663fe5..fdf0129 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1004,43 +1004,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
-{
-    DisasCompare c;
-    TCGCond cond;
-
-    disas_jcc(s, &c, mask);
-    cond = tcg_invert_cond(c.cond);
-
-    if (c.is_64) {
-        tcg_gen_brcond_i64(cond, c.u.s64.a, c.u.s64.b, skip);
-    } else {
-        tcg_gen_brcond_i32(cond, c.u.s32.a, c.u.s32.b, skip);
-    }
-
-    free_compare(&c);
-}
-
-static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
-{
-    int skip;
-
-    if (mask == 0xf) {
-        /* unconditional */
-        gen_goto_tb(s, 0, s->pc + offset);
-    } else if (mask == 0) {
-        /* ignore cc and never match */
-        gen_goto_tb(s, 0, s->pc + 4);
-    } else {
-        skip = gen_new_label();
-        gen_jcc(s, mask, skip);
-        gen_goto_tb(s, 0, s->pc + offset);
-        gen_set_label(skip);
-        gen_goto_tb(s, 1, s->pc + 4);
-    }
-    s->is_jmp = DISAS_TB_JUMP;
-}
-
 static void gen_op_mvc(DisasContext *s, int l, TCGv_i64 s1, TCGv_i64 s2)
 {
     TCGv_i64 tmp, tmp2;
@@ -1759,8 +1722,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int i2)
 {
     TCGv_i64 tmp, tmp2;
-    TCGv_i32 tmp32_1;
-    int l1;
 
     LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
     switch (op) {
@@ -1788,35 +1749,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x4: /* brc m1, i2 */
-        gen_brc(r1, s, i2 * 2LL);
-        return;
-    case 0x6: /* BRCT     R1,I2     [RI] */
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
-        store_reg32(r1, tmp32_1);
-        gen_update_cc_op(s);
-        l1 = gen_new_label();
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
-        gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
-        gen_set_label(l1);
-        gen_goto_tb(s, 1, s->pc + 4);
-        s->is_jmp = DISAS_TB_JUMP;
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x7: /* BRCTG     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tcg_gen_subi_i64(tmp, tmp, 1);
-        store_reg(r1, tmp);
-        gen_update_cc_op(s);
-        l1 = gen_new_label();
-        tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1);
-        gen_goto_tb(s, 0, s->pc + (i2 * 2LL));
-        gen_set_label(l1);
-        gen_goto_tb(s, 1, s->pc + 4);
-        s->is_jmp = DISAS_TB_JUMP;
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal a7 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2574,7 +2506,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     uint64_t insn;
     int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
     TCGv_i32 vl;
-    int l1;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -2586,32 +2517,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         /* set addressing mode, but we only do 64bit anyways */
         break;
 #endif
-    case 0x6: /* BCTR     R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
-        store_reg32(r1, tmp32_1);
-
-        if (r2) {
-            gen_update_cc_op(s);
-            l1 = gen_new_label();
-            tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
-
-            /* not taking the branch, jump to after the instruction */
-            gen_goto_tb(s, 0, s->pc + 2);
-            gen_set_label(l1);
-
-            /* take the branch, move R2 into psw.addr */
-            tmp32_1 = load_reg32(r2);
-            tmp = tcg_temp_new_i64();
-            tcg_gen_extu_i32_i64(tmp, tmp32_1);
-            tcg_gen_mov_i64(psw_addr, tmp);
-            s->is_jmp = DISAS_JUMP;
-            tcg_temp_free_i32(tmp32_1);
-            tcg_temp_free_i64(tmp);
-        }
-        break;
     case 0xa: /* SVC    I         [RR] */
         insn = ld_code2(env, s->pc);
         debug_insn(insn);
@@ -2709,30 +2614,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x46: /* BCT    R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tcg_temp_free_i64(tmp);
-
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
-        store_reg32(r1, tmp32_1);
-
-        gen_update_cc_op(s);
-        l1 = gen_new_label();
-        tcg_gen_brcondi_i32(TCG_COND_NE, tmp32_1, 0, l1);
-
-        /* not taking the branch, jump to after the instruction */
-        gen_goto_tb(s, 0, s->pc + 4);
-        gen_set_label(l1);
-
-        /* take the branch, move R2 into psw.addr */
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tcg_gen_mov_i64(psw_addr, tmp);
-        s->is_jmp = DISAS_JUMP;
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x4e: /* CVD    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3842,6 +3723,49 @@ static ExitStatus op_bc(DisasContext *s, DisasOps *o)
     return help_branch(s, &c, is_imm, imm, o->in2);
 }
 
+static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    bool is_imm = have_field(s->fields, i2);
+    int imm = is_imm ? get_field(s->fields, i2) : 0;
+    DisasCompare c;
+    TCGv_i64 t;
+
+    c.cond = TCG_COND_NE;
+    c.is_64 = false;
+    c.g1 = false;
+    c.g2 = false;
+
+    t = tcg_temp_new_i64();
+    tcg_gen_subi_i64(t, regs[r1], 1);
+    store_reg32_i64(r1, t);
+    c.u.s32.a = tcg_temp_new_i32();
+    c.u.s32.b = tcg_const_i32(0);
+    tcg_gen_trunc_i64_i32(c.u.s32.a, t);
+    tcg_temp_free_i64(t);
+
+    return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
+static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
+{
+    int r1 = get_field(s->fields, r1);
+    bool is_imm = have_field(s->fields, i2);
+    int imm = is_imm ? get_field(s->fields, i2) : 0;
+    DisasCompare c;
+
+    c.cond = TCG_COND_NE;
+    c.is_64 = true;
+    c.g1 = true;
+    c.g2 = false;
+
+    tcg_gen_subi_i64(regs[r1], regs[r1], 1);
+    c.u.s64.a = regs[r1];
+    c.u.s64.b = tcg_const_i64(0);
+
+    return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
 {
     int shift = s->insn->data & 0xff;
commit 7233f2ed17175eea043faad749143c1fb5ffe0b3
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 08:28:02 2012 -0700

    target-s390: Convert BRANCH ON CONDITION
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ba78f47..0bd05ab 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -68,6 +68,12 @@
 /* BRANCH RELATIVE AND SAVE */
     C(0xa705, BRAS,    RI_b,  Z,   0, 0, r1, 0, basi, 0)
     C(0xc005, BRASL,   RIL_b, Z,   0, 0, r1, 0, basi, 0)
+/* BRANCH ON CONDITION */
+    C(0x0700, BCR,     RR_b,  Z,   0, r2_nz, 0, 0, bc, 0)
+    C(0x4700, BC,      RX_b,  Z,   0, a2, 0, 0, bc, 0)
+/* BRANCH RELATIVE ON CONDITION */
+    C(0xa704, BRC,     RI_c,  Z,   0, 0, 0, 0, bc, 0)
+    C(0xc004, BRCL,    RIL_c, Z,   0, 0, 0, 0, bc, 0)
 
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6d87d08..e663fe5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1021,35 +1021,6 @@ static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
     free_compare(&c);
 }
 
-static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
-                    uint64_t offset)
-{
-    int skip;
-
-    if (mask == 0xf) {
-        /* unconditional */
-        gen_update_cc_op(s);
-        tcg_gen_mov_i64(psw_addr, target);
-        tcg_gen_exit_tb(0);
-    } else if (mask == 0) {
-        /* ignore cc and never match */
-        gen_goto_tb(s, 0, offset + 2);
-    } else {
-        TCGv_i64 new_addr = tcg_temp_local_new_i64();
-
-        tcg_gen_mov_i64(new_addr, target);
-        skip = gen_new_label();
-        gen_jcc(s, mask, skip);
-        gen_update_cc_op(s);
-        tcg_gen_mov_i64(psw_addr, new_addr);
-        tcg_temp_free_i64(new_addr);
-        tcg_gen_exit_tb(0);
-        gen_set_label(skip);
-        tcg_temp_free_i64(new_addr);
-        gen_goto_tb(s, 1, offset + 2);
-    }
-}
-
 static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
 {
     int skip;
@@ -2595,46 +2566,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
     }
 }
 
-static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2)
-{
-    TCGv_i32 tmp32_1, tmp32_2;
-    uint64_t target = s->pc + i2 * 2LL;
-    int l1;
-
-    LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2);
-
-    switch (op) {
-    case 0x4: /* BRCL     M1,I2     [RIL] */
-        if (r1 == 15) { /* m1 == r1 */
-            gen_goto_tb(s, 0, target);
-            s->is_jmp = DISAS_TB_JUMP;
-            break;
-        }
-        /* m1 & (1 << (3 - cc)) */
-        tmp32_1 = tcg_const_i32(3);
-        tmp32_2 = tcg_const_i32(1);
-        gen_op_calc_cc(s);
-        tcg_gen_sub_i32(tmp32_1, tmp32_1, cc_op);
-        tcg_gen_shl_i32(tmp32_2, tmp32_2, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tmp32_1 = tcg_const_i32(r1); /* m1 == r1 */
-        tcg_gen_and_i32(tmp32_1, tmp32_1, tmp32_2);
-        l1 = gen_new_label();
-        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp32_1, 0, l1);
-        gen_goto_tb(s, 0, target);
-        gen_set_label(l1);
-        gen_goto_tb(s, 1, s->pc + 6);
-        s->is_jmp = DISAS_TB_JUMP;
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
-    default:
-        LOG_DISAS("illegal c0 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -2681,18 +2612,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
             tcg_temp_free_i64(tmp);
         }
         break;
-    case 0x7: /* BCR    M1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        if (r2) {
-            tmp = load_reg(r2);
-            gen_bcr(s, r1, tmp, s->pc);
-            tcg_temp_free_i64(tmp);
-            s->is_jmp = DISAS_TB_JUMP;
-        } else {
-            /* XXX: "serialization and checkpoint-synchronization function"? */
-        }
-        break;
     case 0xa: /* SVC    I         [RR] */
         insn = ld_code2(env, s->pc);
         debug_insn(insn);
@@ -2814,13 +2733,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-    case 0x47: /* BC     M1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        gen_bcr(s, r1, tmp, s->pc + 4);
-        tcg_temp_free_i64(tmp);
-        s->is_jmp = DISAS_TB_JUMP;
-        break;
     case 0x4e: /* CVD    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3348,13 +3260,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
             gen_op_movi_cc(s, 0);
         }
         break;
-    case 0xc0:
-        insn = ld_code6(env, s->pc);
-        r1 = (insn >> 36) & 0xf;
-        op = (insn >> 32) & 0xf;
-        i2 = (int)insn;
-        disas_c0(env, s, op, r1, i2);
-        break;
     case 0xd2: /* MVC    D1(L,B1),D2(B2)         [SS] */
     case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
     case 0xd5: /* CLC    D1(L,B1),D2(B2)         [SS] */
@@ -3728,6 +3633,131 @@ static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
     }
 }
 
+static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
+                              bool is_imm, int imm, TCGv_i64 cdest)
+{
+    ExitStatus ret;
+    uint64_t dest = s->pc + 2 * imm;
+    int lab;
+
+    /* Take care of the special cases first.  */
+    if (c->cond == TCG_COND_NEVER) {
+        ret = NO_EXIT;
+        goto egress;
+    }
+    if (is_imm) {
+        if (dest == s->next_pc) {
+            /* Branch to next.  */
+            ret = NO_EXIT;
+            goto egress;
+        }
+        if (c->cond == TCG_COND_ALWAYS) {
+            ret = help_goto_direct(s, dest);
+            goto egress;
+        }
+    } else {
+        if (TCGV_IS_UNUSED_I64(cdest)) {
+            /* E.g. bcr %r0 -> no branch.  */
+            ret = NO_EXIT;
+            goto egress;
+        }
+        if (c->cond == TCG_COND_ALWAYS) {
+            tcg_gen_mov_i64(psw_addr, cdest);
+            ret = EXIT_PC_UPDATED;
+            goto egress;
+        }
+    }
+
+    if (use_goto_tb(s, s->next_pc)) {
+        if (is_imm && use_goto_tb(s, dest)) {
+            /* Both exits can use goto_tb.  */
+            gen_update_cc_op(s);
+
+            lab = gen_new_label();
+            if (c->is_64) {
+                tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
+            } else {
+                tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
+            }
+
+            /* Branch not taken.  */
+            tcg_gen_goto_tb(0);
+            tcg_gen_movi_i64(psw_addr, s->next_pc);
+            tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
+
+            /* Branch taken.  */
+            gen_set_label(lab);
+            tcg_gen_goto_tb(1);
+            tcg_gen_movi_i64(psw_addr, dest);
+            tcg_gen_exit_tb((tcg_target_long)s->tb + 1);
+
+            ret = EXIT_GOTO_TB;
+        } else {
+            /* Fallthru can use goto_tb, but taken branch cannot.  */
+            /* Store taken branch destination before the brcond.  This
+               avoids having to allocate a new local temp to hold it.
+               We'll overwrite this in the not taken case anyway.  */
+            if (!is_imm) {
+                tcg_gen_mov_i64(psw_addr, cdest);
+            }
+
+            lab = gen_new_label();
+            if (c->is_64) {
+                tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
+            } else {
+                tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
+            }
+
+            /* Branch not taken.  */
+            gen_update_cc_op(s);
+            tcg_gen_goto_tb(0);
+            tcg_gen_movi_i64(psw_addr, s->next_pc);
+            tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
+
+            gen_set_label(lab);
+            if (is_imm) {
+                tcg_gen_movi_i64(psw_addr, dest);
+            }
+            ret = EXIT_PC_UPDATED;
+        }
+    } else {
+        /* Fallthru cannot use goto_tb.  This by itself is vanishingly rare.
+           Most commonly we're single-stepping or some other condition that
+           disables all use of goto_tb.  Just update the PC and exit.  */
+
+        TCGv_i64 next = tcg_const_i64(s->next_pc);
+        if (is_imm) {
+            cdest = tcg_const_i64(dest);
+        }
+
+        if (c->is_64) {
+            tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
+                                cdest, next);
+        } else {
+            TCGv_i32 t0 = tcg_temp_new_i32();
+            TCGv_i64 t1 = tcg_temp_new_i64();
+            TCGv_i64 z = tcg_const_i64(0);
+            tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
+            tcg_gen_extu_i32_i64(t1, t0);
+            tcg_temp_free_i32(t0);
+            tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
+            tcg_temp_free_i64(t1);
+            tcg_temp_free_i64(z);
+        }
+
+        if (is_imm) {
+            tcg_temp_free_i64(cdest);
+        }
+        tcg_temp_free_i64(next);
+
+        ret = EXIT_PC_UPDATED;
+    }
+
+ egress:
+    free_compare(c);
+    return ret;
+}
+
 /* ====================================================================== */
 /* The operations.  These perform the bulk of the work for any insn,
    usually after the operands have been loaded and output initialized.  */
@@ -3801,6 +3831,17 @@ static ExitStatus op_basi(DisasContext *s, DisasOps *o)
     return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
 }
 
+static ExitStatus op_bc(DisasContext *s, DisasOps *o)
+{
+    int m1 = get_field(s->fields, m1);
+    bool is_imm = have_field(s->fields, i2);
+    int imm = is_imm ? get_field(s->fields, i2) : 0;
+    DisasCompare c;
+
+    disas_jcc(s, &c, m1);
+    return help_branch(s, &c, is_imm, imm, o->in2);
+}
+
 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
 {
     int shift = s->insn->data & 0xff;
commit 8ac33cdb8bfbf319adea60363cf1ba3e5dbf5c4f
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Aug 18 11:38:19 2012 -0700

    target-s390: Convert BRANCH AND SAVE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 373aa40..ba78f47 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -62,6 +62,13 @@
     D(0xa506, NILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
     D(0xa507, NILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
 
+/* BRANCH AND SAVE */
+    C(0x0d00, BASR,    RR_a,  Z,   0, r2_nz, r1, 0, bas, 0)
+    C(0x4d00, BAS,     RX_a,  Z,   0, a2, r1, 0, bas, 0)
+/* BRANCH RELATIVE AND SAVE */
+    C(0xa705, BRAS,    RI_b,  Z,   0, 0, r1, 0, basi, 0)
+    C(0xc005, BRASL,   RIL_b, Z,   0, 0, r1, 0, basi, 0)
+
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
     C(0x5900, C,       RX_a,  Z,   r1_o, m2_32s, 0, 0, 0, cmps32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6f3a5df..6d87d08 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -713,20 +713,23 @@ static inline TCGv_i64 decode_si(DisasContext *s, uint64_t insn, int *i2,
     return get_address(s, 0, *b1, *d1);
 }
 
-static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
+static int use_goto_tb(DisasContext *s, uint64_t dest)
 {
-    TranslationBlock *tb;
+    /* NOTE: we handle the case where the TB spans two pages here */
+    return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
+             || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
+            && !s->singlestep_enabled
+            && !(s->tb->cflags & CF_LAST_IO));
+}
 
+static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
+{
     gen_update_cc_op(s);
 
-    tb = s->tb;
-    /* NOTE: we handle the case where the TB spans two pages here */
-    if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
-        (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))  {
-        /* jump to same page: we can use a direct jump */
+    if (use_goto_tb(s, pc)) {
         tcg_gen_goto_tb(tb_num);
         tcg_gen_movi_i64(psw_addr, pc);
-        tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
+        tcg_gen_exit_tb((tcg_target_long)s->tb + tb_num);
     } else {
         /* jump to another page: currently not optimized */
         tcg_gen_movi_i64(psw_addr, pc);
@@ -1817,13 +1820,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
     case 0x4: /* brc m1, i2 */
         gen_brc(r1, s, i2 * 2LL);
         return;
-    case 0x5: /* BRAS     R1,I2     [RI] */
-        tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        gen_goto_tb(s, 0, s->pc + i2 * 2LL);
-        s->is_jmp = DISAS_TB_JUMP;
-        break;
     case 0x6: /* BRCT     R1,I2     [RI] */
         tmp32_1 = load_reg32(r1);
         tcg_gen_subi_i32(tmp32_1, tmp32_1, 1);
@@ -2601,7 +2597,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
 static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2)
 {
-    TCGv_i64 tmp;
     TCGv_i32 tmp32_1, tmp32_2;
     uint64_t target = s->pc + i2 * 2LL;
     int l1;
@@ -2633,13 +2628,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x5: /* brasl r1, i2 */
-        tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 6));
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        gen_goto_tb(s, 0, target);
-        s->is_jmp = DISAS_TB_JUMP;
-        break;
     default:
         LOG_DISAS("illegal c0 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2720,19 +2708,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xd: /* BASR   R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp = tcg_const_i64(pc_to_link_info(s, s->pc + 2));
-        store_reg(r1, tmp);
-        if (r2) {
-            tmp2 = load_reg(r2);
-            tcg_gen_mov_i64(psw_addr, tmp2);
-            tcg_temp_free_i64(tmp2);
-            s->is_jmp = DISAS_JUMP;
-        }
-        tcg_temp_free_i64(tmp);
-        break;
     case 0xe: /* MVCL   R1,R2     [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -2846,16 +2821,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         s->is_jmp = DISAS_TB_JUMP;
         break;
-    case 0x4d: /* BAS    R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_const_i64(pc_to_link_info(s, s->pc + 4));
-        store_reg(r1, tmp2);
-        tcg_gen_mov_i64(psw_addr, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        s->is_jmp = DISAS_JUMP;
-        break;
     case 0x4e: /* CVD    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3744,6 +3709,26 @@ struct DisasInsn {
 };
 
 /* ====================================================================== */
+/* Miscelaneous helpers, used by several operations.  */
+
+static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
+{
+    if (dest == s->next_pc) {
+        return NO_EXIT;
+    }
+    if (use_goto_tb(s, dest)) {
+        gen_update_cc_op(s);
+        tcg_gen_goto_tb(0);
+        tcg_gen_movi_i64(psw_addr, dest);
+        tcg_gen_exit_tb((tcg_target_long)s->tb);
+        return EXIT_GOTO_TB;
+    } else {
+        tcg_gen_movi_i64(psw_addr, dest);
+        return EXIT_PC_UPDATED;
+    }
+}
+
+/* ====================================================================== */
 /* The operations.  These perform the bulk of the work for any insn,
    usually after the operands have been loaded and output initialized.  */
 
@@ -3799,6 +3784,23 @@ static ExitStatus op_andi(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_bas(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
+    if (!TCGV_IS_UNUSED_I64(o->in2)) {
+        tcg_gen_mov_i64(psw_addr, o->in2);
+        return EXIT_PC_UPDATED;
+    } else {
+        return NO_EXIT;
+    }
+}
+
+static ExitStatus op_basi(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
+    return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
+}
+
 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
 {
     int shift = s->insn->data & 0xff;
@@ -4287,6 +4289,14 @@ static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in2 = true;
 }
 
+static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int r2 = get_field(f, r2);
+    if (r2 != 0) {
+        o->in2 = load_reg(r2);
+    }
+}
+
 static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_temp_new_i64();
commit 4e4bb43899c4c97e14b59fbd7cd5cb44eea850a4
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 18:52:33 2012 -0700

    target-s390: Convert ADD LOGICAL CARRY and SUBTRACT LOGICAL BORROW
    
    I'm resonably certain that the carry/borrow-out condition for both
    helpers was incorrect, failing to take into account the carry-in.
    Adding the new CC_OP codes also allows removing the awkward interface
    we used for the slb helpers.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cc_helper.c b/target-s390x/cc_helper.c
index 19ef145..880e3b2 100644
--- a/target-s390x/cc_helper.c
+++ b/target-s390x/cc_helper.c
@@ -146,22 +146,21 @@ static inline uint32_t cc_calc_add_64(CPUS390XState *env, int64_t a1,
     }
 }
 
-static inline uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
-                                       uint64_t a2, uint64_t ar)
+static uint32_t cc_calc_addu_64(CPUS390XState *env, uint64_t a1,
+                                uint64_t a2, uint64_t ar)
 {
-    if (ar == 0) {
-        if (a1) {
-            return 2;
-        } else {
-            return 0;
-        }
-    } else {
-        if (ar < a1 || ar < a2) {
-            return 3;
-        } else {
-            return 1;
-        }
-    }
+    return (ar != 0) + 2 * (ar < a1);
+}
+
+static uint32_t cc_calc_addc_64(CPUS390XState *env, uint64_t a1,
+                                uint64_t a2, uint64_t ar)
+{
+    /* Recover a2 + carry_in.  */
+    uint64_t a2c = ar - a1;
+    /* Check for a2+carry_in overflow, then a1+a2c overflow.  */
+    int carry_out = (a2c < a2) || (ar < a1);
+
+    return (ar != 0) + 2 * carry_out;
 }
 
 static inline uint32_t cc_calc_sub_64(CPUS390XState *env, int64_t a1,
@@ -194,6 +193,25 @@ static inline uint32_t cc_calc_subu_64(CPUS390XState *env, uint64_t a1,
     }
 }
 
+static uint32_t cc_calc_subb_64(CPUS390XState *env, uint64_t a1,
+                                uint64_t a2, uint64_t ar)
+{
+    /* We had borrow-in if normal subtraction isn't equal.  */
+    int borrow_in = ar - (a1 - a2);
+    int borrow_out;
+
+    /* If a2 was ULONG_MAX, and borrow_in, then a2 is logically 65 bits,
+       and we must have had borrow out.  */
+    if (borrow_in && a2 == (uint64_t)-1) {
+        borrow_out = 1;
+    } else {
+        a2 += borrow_in;
+        borrow_out = (a2 > a1);
+    }
+
+    return (ar != 0) + 2 * !borrow_out;
+}
+
 static inline uint32_t cc_calc_abs_64(CPUS390XState *env, int64_t dst)
 {
     if ((uint64_t)dst == 0x8000000000000000ULL) {
@@ -240,22 +258,21 @@ static inline uint32_t cc_calc_add_32(CPUS390XState *env, int32_t a1,
     }
 }
 
-static inline uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
-                                       uint32_t a2, uint32_t ar)
+static uint32_t cc_calc_addu_32(CPUS390XState *env, uint32_t a1,
+                                uint32_t a2, uint32_t ar)
 {
-    if (ar == 0) {
-        if (a1) {
-            return 2;
-        } else {
-            return 0;
-        }
-    } else {
-        if (ar < a1 || ar < a2) {
-            return 3;
-        } else {
-            return 1;
-        }
-    }
+    return (ar != 0) + 2 * (ar < a1);
+}
+
+static uint32_t cc_calc_addc_32(CPUS390XState *env, uint32_t a1,
+                                uint32_t a2, uint32_t ar)
+{
+    /* Recover a2 + carry_in.  */
+    uint32_t a2c = ar - a1;
+    /* Check for a2+carry_in overflow, then a1+a2c overflow.  */
+    int carry_out = (a2c < a2) || (ar < a1);
+
+    return (ar != 0) + 2 * carry_out;
 }
 
 static inline uint32_t cc_calc_sub_32(CPUS390XState *env, int32_t a1,
@@ -288,6 +305,25 @@ static inline uint32_t cc_calc_subu_32(CPUS390XState *env, uint32_t a1,
     }
 }
 
+static uint32_t cc_calc_subb_32(CPUS390XState *env, uint32_t a1,
+                                uint32_t a2, uint32_t ar)
+{
+    /* We had borrow-in if normal subtraction isn't equal.  */
+    int borrow_in = ar - (a1 - a2);
+    int borrow_out;
+
+    /* If a2 was UINT_MAX, and borrow_in, then a2 is logically 65 bits,
+       and we must have had borrow out.  */
+    if (borrow_in && a2 == (uint32_t)-1) {
+        borrow_out = 1;
+    } else {
+        a2 += borrow_in;
+        borrow_out = (a2 > a1);
+    }
+
+    return (ar != 0) + 2 * !borrow_out;
+}
+
 static inline uint32_t cc_calc_abs_32(CPUS390XState *env, int32_t dst)
 {
     if ((uint32_t)dst == 0x80000000UL) {
@@ -426,12 +462,18 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
     case CC_OP_ADDU_64:
         r =  cc_calc_addu_64(env, src, dst, vr);
         break;
+    case CC_OP_ADDC_64:
+        r =  cc_calc_addc_64(env, src, dst, vr);
+        break;
     case CC_OP_SUB_64:
         r =  cc_calc_sub_64(env, src, dst, vr);
         break;
     case CC_OP_SUBU_64:
         r =  cc_calc_subu_64(env, src, dst, vr);
         break;
+    case CC_OP_SUBB_64:
+        r =  cc_calc_subb_64(env, src, dst, vr);
+        break;
     case CC_OP_ABS_64:
         r =  cc_calc_abs_64(env, dst);
         break;
@@ -448,12 +490,18 @@ static inline uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op,
     case CC_OP_ADDU_32:
         r =  cc_calc_addu_32(env, src, dst, vr);
         break;
+    case CC_OP_ADDC_32:
+        r =  cc_calc_addc_32(env, src, dst, vr);
+        break;
     case CC_OP_SUB_32:
         r =  cc_calc_sub_32(env, src, dst, vr);
         break;
     case CC_OP_SUBU_32:
         r =  cc_calc_subu_32(env, src, dst, vr);
         break;
+    case CC_OP_SUBB_32:
+        r =  cc_calc_subb_32(env, src, dst, vr);
+        break;
     case CC_OP_ABS_32:
         r =  cc_calc_abs_64(env, dst);
         break;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index afe33dc..ea1bc86 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -449,15 +449,19 @@ enum cc_op {
 
     CC_OP_ADD_64,               /* overflow on add (64bit) */
     CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
+    CC_OP_ADDC_64,              /* overflow on unsigned add-carry (64bit) */
     CC_OP_SUB_64,               /* overflow on subtraction (64bit) */
     CC_OP_SUBU_64,              /* overflow on unsigned subtraction (64bit) */
+    CC_OP_SUBB_64,              /* overflow on unsigned sub-borrow (64bit) */
     CC_OP_ABS_64,               /* sign eval on abs (64bit) */
     CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
 
     CC_OP_ADD_32,               /* overflow on add (32bit) */
     CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
+    CC_OP_ADDC_32,              /* overflow on unsigned add-carry (32bit) */
     CC_OP_SUB_32,               /* overflow on subtraction (32bit) */
     CC_OP_SUBU_32,              /* overflow on unsigned subtraction (32bit) */
+    CC_OP_SUBB_32,              /* overflow on unsigned sub-borrow (32bit) */
     CC_OP_ABS_32,               /* sign eval on abs (64bit) */
     CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
 
@@ -494,14 +498,18 @@ static const char *cc_names[] = {
     [CC_OP_LTGT0_64]  = "CC_OP_LTGT0_64",
     [CC_OP_ADD_64]    = "CC_OP_ADD_64",
     [CC_OP_ADDU_64]   = "CC_OP_ADDU_64",
+    [CC_OP_ADDC_64]   = "CC_OP_ADDC_64",
     [CC_OP_SUB_64]    = "CC_OP_SUB_64",
     [CC_OP_SUBU_64]   = "CC_OP_SUBU_64",
+    [CC_OP_SUBB_64]   = "CC_OP_SUBB_64",
     [CC_OP_ABS_64]    = "CC_OP_ABS_64",
     [CC_OP_NABS_64]   = "CC_OP_NABS_64",
     [CC_OP_ADD_32]    = "CC_OP_ADD_32",
     [CC_OP_ADDU_32]   = "CC_OP_ADDU_32",
+    [CC_OP_ADDC_32]   = "CC_OP_ADDC_32",
     [CC_OP_SUB_32]    = "CC_OP_SUB_32",
     [CC_OP_SUBU_32]   = "CC_OP_SUBU_32",
+    [CC_OP_SUBB_32]   = "CC_OP_SUBB_32",
     [CC_OP_ABS_32]    = "CC_OP_ABS_32",
     [CC_OP_NABS_32]   = "CC_OP_NABS_32",
     [CC_OP_COMP_32]   = "CC_OP_COMP_32",
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 88a065c..a45b1c3 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -26,13 +26,10 @@ DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64)
 DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
 DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
 DEF_HELPER_3(ipm, void, env, i32, i32)
-DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
 DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
 DEF_HELPER_4(clcle, i32, env, i32, i64, i32)
-DEF_HELPER_4(slb, i32, env, i32, i32, i32)
-DEF_HELPER_5(slbg, i32, env, i32, i32, i64, i64)
 DEF_HELPER_3(cefbr, void, env, i32, s32)
 DEF_HELPER_3(cdfbr, void, env, i32, s32)
 DEF_HELPER_3(cxfbr, void, env, i32, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f441a66..373aa40 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -40,6 +40,11 @@
     C(0xecda, ALHSIK,  RIE_d, DO,  r3, i2, new, r1_32, add, addu32)
     C(0xeb7e, ALGSI,   SIY,   GIE, m1_64, i2, new, m1_64, add, addu64)
     C(0xecdb, ALGHSIK, RIE_d, DO,  r3, i2, r1, 0, add, addu64)
+/* ADD LOGICAL WITH CARRY */
+    C(0xb998, ALCR,    RRE,   Z,   r1, r2, new, r1_32, addc, addc32)
+    C(0xb988, ALCGR,   RRE,   Z,   r1, r2, r1, 0, addc, addc64)
+    C(0xe398, ALC,     RXY_a, Z,   r1, m2_32u, new, r1_32, addc, addc32)
+    C(0xe388, ALCG,    RXY_a, Z,   r1, m2_64, r1, 0, addc, addc64)
 
 /* AND */
     C(0x1400, NR,      RR_a,  Z,   r1, r2, new, r1_32, and, nz32)
@@ -291,3 +296,8 @@
 /* SUBTRACT LOGICAL IMMEDIATE */
     C(0xc205, SLFI,    RIL_a, EI,  r1, i2_32u, new, r1_32, sub, subu32)
     C(0xc204, SLGFI,   RIL_a, EI,  r1, i2_32u, r1, 0, sub, subu64)
+/* SUBTRACT LOGICAL WITH BORROW */
+    C(0xb999, SLBR,    RRE,   Z,   r1, r2, new, r1_32, subb, subb32)
+    C(0xb989, SLBGR,   RRE,   Z,   r1, r2, r1, 0, subb, subb64)
+    C(0xe399, SLB,     RXY_a, Z,   r1, m2_32u, new, r1_32, subb, subb32)
+    C(0xe389, SLBG,    RXY_a, Z,   r1, m2_64, r1, 0, subb, subb64)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index 4f18d29..17c4771 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -107,49 +107,6 @@ int64_t HELPER(nabs_i64)(int64_t val)
     }
 }
 
-/* add with carry 32-bit unsigned */
-uint32_t HELPER(addc_u32)(uint32_t cc, uint32_t v1, uint32_t v2)
-{
-    uint32_t res;
-
-    res = v1 + v2;
-    if (cc & 2) {
-        res++;
-    }
-
-    return res;
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slb)(CPUS390XState *env, uint32_t cc, uint32_t r1, uint32_t v2)
-{
-    uint32_t v1 = env->regs[r1];
-    uint32_t res = v1 + (~v2) + (cc >> 1);
-
-    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | res;
-    if (cc & 2) {
-        /* borrow */
-        return v1 ? 1 : 0;
-    } else {
-        return v1 ? 3 : 2;
-    }
-}
-
-/* subtract unsigned v2 from v1 with borrow */
-uint32_t HELPER(slbg)(CPUS390XState *env, uint32_t cc, uint32_t r1,
-                      uint64_t v1, uint64_t v2)
-{
-    uint64_t res = v1 + (~v2) + (cc >> 1);
-
-    env->regs[r1] = res;
-    if (cc & 2) {
-        /* borrow */
-        return v1 ? 1 : 0;
-    } else {
-        return v1 ? 3 : 2;
-    }
-}
-
 /* find leftmost one */
 uint32_t HELPER(flogr)(CPUS390XState *env, uint32_t r1, uint64_t v2)
 {
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f17fa2f..6f3a5df 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -474,15 +474,6 @@ static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
     s->cc_op = op;
 }
 
-static void gen_op_update3_cc_i32(DisasContext *s, enum cc_op op, TCGv_i32 src,
-                                  TCGv_i32 dst, TCGv_i32 vr)
-{
-    tcg_gen_extu_i32_i64(cc_src, src);
-    tcg_gen_extu_i32_i64(cc_dst, dst);
-    tcg_gen_extu_i32_i64(cc_vr, vr);
-    s->cc_op = op;
-}
-
 static inline void set_cc_nz_u32(DisasContext *s, TCGv_i32 val)
 {
     gen_op_update1_cc_i32(s, CC_OP_NZ, val);
@@ -564,18 +555,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
-                          TCGv_i64 vr)
-{
-    gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
-}
-
-static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
-                          TCGv_i32 vr)
-{
-    gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
-}
-
 static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
 {
     gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
@@ -661,12 +640,16 @@ static void gen_op_calc_cc(DisasContext *s)
         break;
     case CC_OP_ADD_64:
     case CC_OP_ADDU_64:
+    case CC_OP_ADDC_64:
     case CC_OP_SUB_64:
     case CC_OP_SUBU_64:
+    case CC_OP_SUBB_64:
     case CC_OP_ADD_32:
     case CC_OP_ADDU_32:
+    case CC_OP_ADDC_32:
     case CC_OP_SUB_32:
     case CC_OP_SUBU_32:
+    case CC_OP_SUBB_32:
         /* 3 arguments */
         gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
         break;
@@ -1313,7 +1296,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
                      int x2, int b2, int d2)
 {
     TCGv_i64 addr, tmp, tmp2, tmp3, tmp4;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_e3: op 0x%x r1 %d x2 %d b2 %d d2 %d\n",
               op, r1, x2, b2, d2);
@@ -1394,33 +1377,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x88: /* ALCG      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        /* XXX possible optimization point */
-        gen_op_calc_cc(s);
-        tcg_gen_extu_i32_i64(tmp3, cc_op);
-        tcg_gen_shri_i64(tmp3, tmp3, 1);
-        tcg_gen_andi_i64(tmp3, tmp3, 1);
-        tcg_gen_add_i64(tmp3, tmp2, tmp3);
-        tcg_gen_add_i64(tmp3, regs[r1], tmp3);
-        store_reg(r1, tmp3);
-        set_cc_addu64(s, regs[r1], tmp2, tmp3);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-    case 0x89: /* SLBG      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_const_i32(r1);
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        /* XXX possible optimization point */
-        gen_op_calc_cc(s);
-        gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, regs[r1], tmp2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x97: /* DL     R1,D2(X2,B2)     [RXY] */
         /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
         /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -1441,37 +1397,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x98: /* ALC     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp32_3 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        /* XXX possible optimization point */
-        gen_op_calc_cc(s);
-        gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
-        set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
-        store_reg32(r1, tmp32_3);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0x99: /* SLB     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_const_i32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        /* XXX possible optimization point */
-        gen_op_calc_cc(s);
-        gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_1, tmp32_2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     default:
         LOG_DISAS("illegal e3 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2591,7 +2516,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int r2)
 {
     TCGv_i64 tmp, tmp2, tmp3;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i32 tmp32_1;
 
     LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
     switch (op) {
@@ -2648,33 +2573,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x88: /* ALCGR     R1,R2     [RRE] */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        tmp3 = tcg_temp_new_i64();
-        gen_op_calc_cc(s);
-        tcg_gen_extu_i32_i64(tmp3, cc_op);
-        tcg_gen_shri_i64(tmp3, tmp3, 1);
-        tcg_gen_andi_i64(tmp3, tmp3, 1);
-        tcg_gen_add_i64(tmp3, tmp2, tmp3);
-        tcg_gen_add_i64(tmp3, tmp, tmp3);
-        store_reg(r1, tmp3);
-        set_cc_addu64(s, tmp, tmp2, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-    case 0x89: /* SLBGR   R1,R2     [RRE] */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        tmp32_1 = tcg_const_i32(r1);
-        gen_op_calc_cc(s);
-        gen_helper_slbg(cc_op, cpu_env, cc_op, tmp32_1, tmp, tmp2);
-        set_cc_static(s);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x97: /* DLR     R1,R2     [RRE] */
         /* reg(r1) = reg(r1, r1+1) % reg(r2) */
         /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -2694,28 +2592,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x98: /* ALCR    R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r2);
-        tmp32_3 = tcg_temp_new_i32();
-        /* XXX possible optimization point */
-        gen_op_calc_cc(s);
-        gen_helper_addc_u32(tmp32_3, cc_op, tmp32_1, tmp32_2);
-        set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
-        store_reg32(r1, tmp32_3);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0x99: /* SLBR    R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp32_2 = tcg_const_i32(r1);
-        gen_op_calc_cc(s);
-        gen_helper_slb(cc_op, cpu_env, cc_op, tmp32_2, tmp32_1);
-        set_cc_static(s);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     default:
         LOG_DISAS("illegal b9 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -3883,6 +3759,23 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_addc(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 cc;
+
+    tcg_gen_add_i64(o->out, o->in1, o->in2);
+
+    /* XXX possible optimization point */
+    gen_op_calc_cc(s);
+    cc = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(cc, cc_op);
+    tcg_gen_shri_i64(cc, cc, 1);
+
+    tcg_gen_add_i64(o->out, o->out, cc);
+    tcg_temp_free_i64(cc);
+    return NO_EXIT;
+}
+
 static ExitStatus op_and(DisasContext *s, DisasOps *o)
 {
     tcg_gen_and_i64(o->out, o->in1, o->in2);
@@ -4042,6 +3935,24 @@ static ExitStatus op_sub(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_subb(DisasContext *s, DisasOps *o)
+{
+    TCGv_i64 cc;
+
+    assert(!o->g_in2);
+    tcg_gen_not_i64(o->in2, o->in2);
+    tcg_gen_add_i64(o->out, o->in1, o->in2);
+
+    /* XXX possible optimization point */
+    gen_op_calc_cc(s);
+    cc = tcg_temp_new_i64();
+    tcg_gen_extu_i32_i64(cc, cc_op);
+    tcg_gen_shri_i64(cc, cc, 1);
+    tcg_gen_add_i64(o->out, o->out, cc);
+    tcg_temp_free_i64(cc);
+    return NO_EXIT;
+}
+
 static ExitStatus op_xor(DisasContext *s, DisasOps *o)
 {
     tcg_gen_xor_i64(o->out, o->in1, o->in2);
@@ -4099,6 +4010,16 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
     gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
 }
 
+static void cout_addc32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
+}
+
+static void cout_addc64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
+}
+
 static void cout_cmps32(DisasContext *s, DisasOps *o)
 {
     gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
@@ -4180,6 +4101,16 @@ static void cout_subu64(DisasContext *s, DisasOps *o)
     gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
 }
 
+static void cout_subb32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subb64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
+}
+
 /* ====================================================================== */
 /* The "PREPeration" generators.  These initialize the DisasOps.OUT fields
    with the TCG register to which we will write.  Used in combination with
commit 2b280b97085ae90e804c1b31557a79d1da2789a4
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 16:00:08 2012 -0700

    target-s390: Convert STORE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 705b655..f441a66 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -249,6 +249,22 @@
     D(0xa50a, OILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
     D(0xa50b, OILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
 
+/* STORE */
+    C(0x5000, ST,      RX_a,  Z,   r1_o, a2, 0, 0, st32, 0)
+    C(0xe350, STY,     RXY_a, LD,  r1_o, a2, 0, 0, st32, 0)
+    C(0xe324, STG,     RXY_a, Z,   r1_o, a2, 0, 0, st64, 0)
+/* STORE RELATIVE LONG */
+    C(0xc40f, STRL,    RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0)
+    C(0xc40b, STGRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0)
+/* STORE CHARACTER */
+    C(0x4200, STC,     RX_a,  Z,   r1_o, a2, 0, 0, st8, 0)
+    C(0xe372, STCY,    RXY_a, LD,  r1_o, a2, 0, 0, st8, 0)
+/* STORE HALFWORD */
+    C(0x4000, STH,     RX_a,  Z,   r1_o, a2, 0, 0, st16, 0)
+    C(0xe370, STHY,    RXY_a, LD,  r1_o, a2, 0, 0, st16, 0)
+/* STORE HALFWORD RELATIVE LONG */
+    C(0xc407, STHRL,   RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
+
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
     C(0xb9f9, SRK,     RRF_a, DO,  r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 06db4c5..f17fa2f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1371,9 +1371,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg16(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x24: /* stg r1, d2(x2,b2) */
-        tcg_gen_qemu_st64(regs[r1], addr, get_mem_index(s));
-        break;
     case 0x3e: /* STRV R1,D2(X2,B2) [RXY] */
         tmp32_1 = load_reg32(r1);
         tmp2 = tcg_temp_new_i64();
@@ -1383,22 +1380,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x50: /* STY  R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x72: /* STCY R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_ext_i32_i64(tmp2, tmp32_1);
-        tcg_gen_qemu_st8(tmp2, addr, get_mem_index(s));
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x73: /* ICY R1,D2(X2,B2) [RXY] */
         tmp3 = tcg_temp_new_i64();
         tcg_gen_qemu_ld8u(tmp3, addr, get_mem_index(s));
@@ -2936,22 +2917,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         store_freg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x40: /* STH    R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = load_reg(r1);
-        tcg_gen_qemu_st16(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x42: /* STC    R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = load_reg(r1);
-        tcg_gen_qemu_st8(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x43: /* IC     R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3027,14 +2992,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x50: /* st r1, d2(x2, b2) */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = load_reg(r1);
-        tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x5d: /* D      R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4055,6 +4012,30 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_st8(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_st16(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_st32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_st64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
commit facfc8648728b5c5554b3269355a4c13824e664b
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 15:01:36 2012 -0700

    target-s390: Convert AND, OR, XOR, INSERT IMMEDIATE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 9507262..705b655 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -49,6 +49,13 @@
     C(0xb980, NGR,     RRE,   Z,   r1, r2, r1, 0, and, nz64)
     C(0xb9e4, NGRK,    RRF_a, DO,  r2, r3, r1, 0, and, nz64)
     C(0xe380, NG,      RXY_a, Z,   r1, m2_64, r1, 0, and, nz64)
+/* AND IMMEDIATE */
+    D(0xc00a, NIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, andi, 0, 0x2020)
+    D(0xc00b, NILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, andi, 0, 0x2000)
+    D(0xa504, NIHH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1030)
+    D(0xa505, NIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1020)
+    D(0xa506, NILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1010)
+    D(0xa507, NILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, andi, 0, 0x1000)
 
 /* COMPARE */
     C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
@@ -106,6 +113,17 @@
     C(0xb982, XGR,     RRE,   Z,   r1, r2, r1, 0, xor, nz64)
     C(0xb9e7, XGRK,    RRF_a, DO,  r2, r3, r1, 0, xor, nz64)
     C(0xe382, XG,      RXY_a, Z,   r1, m2_64, r1, 0, xor, nz64)
+/* EXCLUSIVE OR IMMEDIATE */
+    D(0xc006, XIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2020)
+    D(0xc007, XILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, xori, 0, 0x2000)
+
+/* INSERT IMMEDIATE */
+    D(0xc008, IIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2020)
+    D(0xc009, IILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, insi, 0, 0x2000)
+    D(0xa500, IIHH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1030)
+    D(0xa501, IIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1020)
+    D(0xa502, IILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1010)
+    D(0xa503, IILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, insi, 0, 0x1000)
 
 /* LOAD */
     C(0x1800, LR,      RR_a,  Z,   0, r2_o, 0, cond_r1r2_32, mov2, 0)
@@ -223,6 +241,13 @@
     C(0xb981, OGR,     RRE,   Z,   r1, r2, r1, 0, or, nz64)
     C(0xb9e6, OGRK,    RRF_a, DO,  r2, r3, r1, 0, or, nz64)
     C(0xe381, OG,      RXY_a, Z,   r1, m2_64, r1, 0, or, nz64)
+/* OR IMMEDIATE */
+    D(0xc00c, OIHF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, ori, 0, 0x2020)
+    D(0xc00d, OILF,    RIL_a, EI,  r1_o, i2_32u, r1, 0, ori, 0, 0x2000)
+    D(0xa508, OIHH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1030)
+    D(0xa509, OIHL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1020)
+    D(0xa50a, OILH,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1010)
+    D(0xa50b, OILL,    RI_a,  Z,   r1_o, i2_16u, r1, 0, ori, 0, 0x1000)
 
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2da94f5..06db4c5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1875,141 +1875,6 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
     tcg_temp_free_i64(addr);
 }
 
-static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int i2)
-{
-    TCGv_i64 tmp, tmp2;
-    TCGv_i32 tmp32;
-    LOG_DISAS("disas_a5: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
-    switch (op) {
-    case 0x0: /* IIHH     R1,I2     [RI] */
-        tmp = tcg_const_i64(i2);
-        tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 48, 16);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x1: /* IIHL     R1,I2     [RI] */
-        tmp = tcg_const_i64(i2);
-        tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 32, 16);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x2: /* IILH     R1,I2     [RI] */
-        tmp = tcg_const_i64(i2);
-        tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 16, 16);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x3: /* IILL     R1,I2     [RI] */
-        tmp = tcg_const_i64(i2);
-        tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 0, 16);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x4: /* NIHH     R1,I2     [RI] */
-    case 0x8: /* OIHH     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tmp32 = tcg_temp_new_i32();
-        switch (op) {
-        case 0x4:
-            tmp2 = tcg_const_i64((((uint64_t)i2) << 48)
-                               | 0x0000ffffffffffffULL);
-            tcg_gen_and_i64(tmp, tmp, tmp2);
-            break;
-        case 0x8:
-            tmp2 = tcg_const_i64(((uint64_t)i2) << 48);
-            tcg_gen_or_i64(tmp, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp);
-        tcg_gen_shri_i64(tmp2, tmp, 48);
-        tcg_gen_trunc_i64_i32(tmp32, tmp2);
-        set_cc_nz_u32(s, tmp32);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x5: /* NIHL     R1,I2     [RI] */
-    case 0x9: /* OIHL     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tmp32 = tcg_temp_new_i32();
-        switch (op) {
-        case 0x5:
-            tmp2 = tcg_const_i64((((uint64_t)i2) << 32)
-                               | 0xffff0000ffffffffULL);
-            tcg_gen_and_i64(tmp, tmp, tmp2);
-            break;
-        case 0x9:
-            tmp2 = tcg_const_i64(((uint64_t)i2) << 32);
-            tcg_gen_or_i64(tmp, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp);
-        tcg_gen_shri_i64(tmp2, tmp, 32);
-        tcg_gen_trunc_i64_i32(tmp32, tmp2);
-        tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
-        set_cc_nz_u32(s, tmp32);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x6: /* NILH     R1,I2     [RI] */
-    case 0xa: /* OILH     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tmp32 = tcg_temp_new_i32();
-        switch (op) {
-        case 0x6:
-            tmp2 = tcg_const_i64((((uint64_t)i2) << 16)
-                               | 0xffffffff0000ffffULL);
-            tcg_gen_and_i64(tmp, tmp, tmp2);
-            break;
-        case 0xa:
-            tmp2 = tcg_const_i64(((uint64_t)i2) << 16);
-            tcg_gen_or_i64(tmp, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp);
-        tcg_gen_shri_i64(tmp, tmp, 16);
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
-        set_cc_nz_u32(s, tmp32);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x7: /* NILL     R1,I2     [RI] */
-    case 0xb: /* OILL     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tmp32 = tcg_temp_new_i32();
-        switch (op) {
-        case 0x7:
-            tmp2 = tcg_const_i64(i2 | 0xffffffffffff0000ULL);
-            tcg_gen_and_i64(tmp, tmp, tmp2);
-            break;
-        case 0xb:
-            tmp2 = tcg_const_i64(i2);
-            tcg_gen_or_i64(tmp, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp);
-        tcg_gen_trunc_i64_i32(tmp32, tmp);
-        tcg_gen_andi_i32(tmp32, tmp32, 0xffff);
-        set_cc_nz_u32(s, tmp32);        /* signedness should not matter here */
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32);
-        tcg_temp_free_i64(tmp);
-        break;
-    default:
-        LOG_DISAS("illegal a5 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        return;
-    }
-}
-
 static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int i2)
 {
@@ -2918,44 +2783,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         gen_goto_tb(s, 0, target);
         s->is_jmp = DISAS_TB_JUMP;
         break;
-    case 0x7: /* XILF R1,I2 [RIL] */
-    case 0xb: /* NILF R1,I2 [RIL] */
-    case 0xd: /* OILF R1,I2 [RIL] */
-        tmp32_1 = load_reg32(r1);
-        switch (op) {
-        case 0x7:
-            tcg_gen_xori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
-            break;
-        case 0xb:
-            tcg_gen_andi_i32(tmp32_1, tmp32_1, (uint32_t)i2);
-            break;
-        case 0xd:
-            tcg_gen_ori_i32(tmp32_1, tmp32_1, (uint32_t)i2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_1);
-        set_cc_nz_u32(s, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x9: /* IILF R1,I2 [RIL] */
-        tmp32_1 = tcg_const_i32((uint32_t)i2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0xa: /* NIHF R1,I2 [RIL] */
-        tmp = load_reg(r1);
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_andi_i64(tmp, tmp, (((uint64_t)((uint32_t)i2)) << 32)
-                                   | 0xffffffffULL);
-        store_reg(r1, tmp);
-        tcg_gen_shri_i64(tmp, tmp, 32);
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        set_cc_nz_u32(s, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     default:
         LOG_DISAS("illegal c0 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -3487,13 +3314,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0xa5:
-        insn = ld_code4(env, s->pc);
-        r1 = (insn >> 20) & 0xf;
-        op = (insn >> 16) & 0xf;
-        i2 = insn & 0xffff;
-        disas_a5(env, s, op, r1, i2);
-        break;
     case 0xa7:
         insn = ld_code4(env, s->pc);
         r1 = (insn >> 20) & 0xf;
@@ -4112,6 +3932,31 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_andi(DisasContext *s, DisasOps *o)
+{
+    int shift = s->insn->data & 0xff;
+    int size = s->insn->data >> 8;
+    uint64_t mask = ((1ull << size) - 1) << shift;
+
+    assert(!o->g_in2);
+    tcg_gen_shli_i64(o->in2, o->in2, shift);
+    tcg_gen_ori_i64(o->in2, o->in2, ~mask);
+    tcg_gen_and_i64(o->out, o->in1, o->in2);
+
+    /* Produce the CC from only the bits manipulated.  */
+    tcg_gen_andi_i64(cc_dst, o->out, mask);
+    set_cc_nz_u64(s, cc_dst);
+    return NO_EXIT;
+}
+
+static ExitStatus op_insi(DisasContext *s, DisasOps *o)
+{
+    int shift = s->insn->data & 0xff;
+    int size = s->insn->data >> 8;
+    tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
+    return NO_EXIT;
+}
+
 static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
 {
     tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
@@ -4194,6 +4039,22 @@ static ExitStatus op_or(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ori(DisasContext *s, DisasOps *o)
+{
+    int shift = s->insn->data & 0xff;
+    int size = s->insn->data >> 8;
+    uint64_t mask = ((1ull << size) - 1) << shift;
+
+    assert(!o->g_in2);
+    tcg_gen_shli_i64(o->in2, o->in2, shift);
+    tcg_gen_or_i64(o->out, o->in1, o->in2);
+
+    /* Produce the CC from only the bits manipulated.  */
+    tcg_gen_andi_i64(cc_dst, o->out, mask);
+    set_cc_nz_u64(s, cc_dst);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4206,6 +4067,22 @@ static ExitStatus op_xor(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_xori(DisasContext *s, DisasOps *o)
+{
+    int shift = s->insn->data & 0xff;
+    int size = s->insn->data >> 8;
+    uint64_t mask = ((1ull << size) - 1) << shift;
+
+    assert(!o->g_in2);
+    tcg_gen_shli_i64(o->in2, o->in2, shift);
+    tcg_gen_xor_i64(o->out, o->in1, o->in2);
+
+    /* Produce the CC from only the bits manipulated.  */
+    tcg_gen_andi_i64(cc_dst, o->out, mask);
+    set_cc_nz_u64(s, cc_dst);
+    return NO_EXIT;
+}
+
 /* ====================================================================== */
 /* The "Cc OUTput" generators.  Given the generated output (and in some cases
    the original inputs), update the various cc data structures in order to
commit b9bca3e57a4570ce2aff46388fa1edc9da5437a4
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 11:38:37 2012 -0700

    target-s390: Convert LOAD COMPLIMENT, POSITIVE, NEGATIVE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 89bc635..9507262 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -138,6 +138,10 @@
     C(0xb906, LGBR,    RRE,   EI,  0, r2_8s, 0, r1, mov2, 0)
     C(0xe376, LB,      RXY_a, LD,  0, a2, new, r1_32, ld8s, 0)
     C(0xe377, LGB,     RXY_a, LD,  0, a2, r1, 0, ld8s, 0)
+/* LOAD COMPLEMENT */
+    C(0x1300, LCR,     RR_a,  Z,   0, r2, new, r1_32, neg, neg32)
+    C(0xb903, LCGR,    RRE,   Z,   0, r2, r1, 0, neg, neg64)
+    C(0xb913, LCGFR,   RRE,   Z,   0, r2_32s, r1, 0, neg, neg64)
 /* LOAD HALFWORD */
     C(0xb927, LHR,     RRE,   EI,  0, r2_16s, 0, r1_32, mov2, 0)
     C(0xb907, LGHR,    RRE,   EI,  0, r2_16s, 0, r1, mov2, 0)
@@ -175,6 +179,14 @@
     D(0xa50d, LLIHL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 32)
     D(0xa50e, LLILH,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 16)
     D(0xa50f, LLILL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 0)
+/* LOAD NEGATIVE */
+    C(0x1100, LNR,     RR_a,  Z,   0, r2_32s, new, r1_32, nabs, nabs32)
+    C(0xb901, LNGR,    RRE,   Z,   0, r2, r1, 0, nabs, nabs64)
+    C(0xb911, LNGFR,   RRE,   Z,   0, r2_32s, r1, 0, nabs, nabs64)
+/* LOAD POSITIVE */
+    C(0x1000, LPR,     RR_a,  Z,   0, r2_32s, new, r1_32, abs, abs32)
+    C(0xb900, LPGR,    RRE,   Z,   0, r2, r1, 0, abs, abs64)
+    C(0xb910, LPGFR,   RRE,   Z,   0, r2_32s, r1, 0, abs, abs64)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0143758..2da94f5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -570,42 +570,12 @@ static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
     gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
 }
 
-static void set_cc_abs64(DisasContext *s, TCGv_i64 v1)
-{
-    gen_op_update1_cc_i64(s, CC_OP_ABS_64, v1);
-}
-
-static void set_cc_nabs64(DisasContext *s, TCGv_i64 v1)
-{
-    gen_op_update1_cc_i64(s, CC_OP_NABS_64, v1);
-}
-
 static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
                           TCGv_i32 vr)
 {
     gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
 }
 
-static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
-{
-    gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
-}
-
-static void set_cc_nabs32(DisasContext *s, TCGv_i32 v1)
-{
-    gen_op_update1_cc_i32(s, CC_OP_NABS_32, v1);
-}
-
-static void set_cc_comp32(DisasContext *s, TCGv_i32 v1)
-{
-    gen_op_update1_cc_i32(s, CC_OP_COMP_32, v1);
-}
-
-static void set_cc_comp64(DisasContext *s, TCGv_i64 v1)
-{
-    gen_op_update1_cc_i64(s, CC_OP_COMP_64, v1);
-}
-
 static void set_cc_icm(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2)
 {
     gen_op_update2_cc_i32(s, CC_OP_ICM, v1, v2);
@@ -2779,43 +2749,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
 
     LOG_DISAS("disas_b9: op 0x%x r1 %d r2 %d\n", op, r1, r2);
     switch (op) {
-    case 0x0: /* LPGR     R1,R2     [RRE] */
-    case 0x1: /* LNGR     R1,R2     [RRE] */
-    case 0x2: /* LTGR R1,R2 [RRE] */
-    case 0x3: /* LCGR     R1,R2     [RRE] */
-    case 0x10: /* LPGFR R1,R2 [RRE] */
-    case 0x11: /* LNFGR     R1,R2     [RRE] */
-    case 0x12: /* LTGFR R1,R2 [RRE] */
-    case 0x13: /* LCGFR    R1,R2     [RRE] */
-        if (op & 0x10) {
-            tmp = load_reg32_i64(r2);
-        } else {
-            tmp = load_reg(r2);
-        }
-        switch (op & 0xf) {
-        case 0x0: /* LP?GR */
-            set_cc_abs64(s, tmp);
-            gen_helper_abs_i64(tmp, tmp);
-            store_reg(r1, tmp);
-            break;
-        case 0x1: /* LN?GR */
-            set_cc_nabs64(s, tmp);
-            gen_helper_nabs_i64(tmp, tmp);
-            store_reg(r1, tmp);
-            break;
-        case 0x2: /* LT?GR */
-            if (r1 != r2) {
-                store_reg(r1, tmp);
-            }
-            set_cc_s64(s, tmp);
-            break;
-        case 0x3: /* LC?GR */
-            tcg_gen_neg_i64(regs[r1], tmp);
-            set_cc_comp64(s, regs[r1]);
-            break;
-        }
-        tcg_temp_free_i64(tmp);
-        break;
     case 0xd: /* DSGR      R1,R2     [RRE] */
     case 0x1d: /* DSGFR      R1,R2     [RRE] */
         tmp = load_reg(r1 + 1);
@@ -3127,33 +3060,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x10: /* LPR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r2);
-        set_cc_abs32(s, tmp32_1);
-        gen_helper_abs_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x11: /* LNR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r2);
-        set_cc_nabs32(s, tmp32_1);
-        gen_helper_nabs_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x13: /* LCR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_neg_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        set_cc_comp32(s, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x1d: /* DR     R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -4188,6 +4094,12 @@ struct DisasInsn {
 /* The operations.  These perform the bulk of the work for any insn,
    usually after the operands have been loaded and output initialized.  */
 
+static ExitStatus op_abs(DisasContext *s, DisasOps *o)
+{
+    gen_helper_abs_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_add(DisasContext *s, DisasOps *o)
 {
     tcg_gen_add_i64(o->out, o->in1, o->in2);
@@ -4264,6 +4176,18 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
+{
+    gen_helper_nabs_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_neg(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_neg_i64(o->out, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_or(DisasContext *s, DisasOps *o)
 {
     tcg_gen_or_i64(o->out, o->in1, o->in2);
@@ -4287,6 +4211,16 @@ static ExitStatus op_xor(DisasContext *s, DisasOps *o)
    the original inputs), update the various cc data structures in order to
    be able to compute the new condition code.  */
 
+static void cout_abs32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
+}
+
+static void cout_abs64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
+}
+
 static void cout_adds32(DisasContext *s, DisasOps *o)
 {
     gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
@@ -4327,6 +4261,26 @@ static void cout_cmpu64(DisasContext *s, DisasOps *o)
     gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
 }
 
+static void cout_nabs32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
+}
+
+static void cout_nabs64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
+}
+
+static void cout_neg32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
+}
+
+static void cout_neg64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
+}
+
 static void cout_nz32(DisasContext *s, DisasOps *o)
 {
     tcg_gen_ext32u_i64(cc_dst, o->out);
commit ade9dea429e202eabf87a36a20d1d3bbc34d8910
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 11:20:33 2012 -0700

    target-s390: Convert LOAD LOGICAL IMMEDIATE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7a8dcbd..89bc635 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -168,6 +168,13 @@
 /* LOAD LOGICAL HALFWORD RELATIVE LONG */
     C(0xc402, LLHRL,   RIL_b, GIE, 0, ri2, new, r1_32, ld16u, 0)
     C(0xc406, LLGHRL,  RIL_b, GIE, 0, ri2, r1, 0, ld16u, 0)
+/* LOAD LOGICAL IMMEDATE */
+    D(0xc00e, LLIHF,   RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 32)
+    D(0xc00f, LLILF,   RIL_a, EI, 0, i2_32u_shl, 0, r1, mov2, 0, 0)
+    D(0xa50c, LLIHH,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 48)
+    D(0xa50d, LLIHL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 32)
+    D(0xa50e, LLILH,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 16)
+    D(0xa50f, LLILL,   RI_a,  Z,  0, i2_16u_shl, 0, r1, mov2, 0, 0)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9239025..0143758 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2033,26 +2033,6 @@ static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i32(tmp32);
         tcg_temp_free_i64(tmp);
         break;
-    case 0xc: /* LLIHH     R1,I2     [RI] */
-        tmp = tcg_const_i64( ((uint64_t)i2) << 48 );
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xd: /* LLIHL     R1,I2     [RI] */
-        tmp = tcg_const_i64( ((uint64_t)i2) << 32 );
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xe: /* LLILH     R1,I2     [RI] */
-        tmp = tcg_const_i64( ((uint64_t)i2) << 16 );
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xf: /* LLILL     R1,I2     [RI] */
-        tmp = tcg_const_i64(i2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal a5 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -3043,16 +3023,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0xe: /* LLIHF R1,I2 [RIL] */
-        tmp = tcg_const_i64(((uint64_t)(uint32_t)i2) << 32);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xf: /* LLILF R1,I2 [RIL] */
-        tmp = tcg_const_i64((uint32_t)i2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal c0 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -4694,6 +4664,18 @@ static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
 }
 
+static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    uint64_t i2 = (uint16_t)get_field(f, i2);
+    o->in2 = tcg_const_i64(i2 << s->insn->data);
+}
+
+static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    uint64_t i2 = (uint32_t)get_field(f, i2);
+    o->in2 = tcg_const_i64(i2 << s->insn->data);
+}
+
 /* ====================================================================== */
 
 /* Find opc within the table of insns.  This is formulated as a switch
commit 11bf2d73d0dba509e14dbfc2189365410a5a2c06
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 11:03:39 2012 -0700

    target-s390: Convert LOAD AND TEST
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 796185f..7a8dcbd 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -126,6 +126,13 @@
     C(0xe371, LAY,     RXY_a, LD,  0, a2, 0, r1, mov2, 0)
 /* LOAD ADDRESS RELATIVE LONG */
     C(0xc000, LARL,    RIL_b, Z,   0, ri2, 0, r1, mov2, 0)
+/* LOAD AND TEST */
+    C(0x1200, LTR,     RR_a,  Z,   0, r2_o, 0, cond_r1r2_32, mov2, s32)
+    C(0xb902, LTGR,    RRE,   Z,   0, r2_o, 0, r1, mov2, s64)
+    C(0xb912, LTGFR,   RRE,   Z,   0, r2_32s, 0, r1, mov2, s64)
+    C(0xe312, LT,      RXY_a, EI,  0, a2, new, r1_32, ld32s, s64)
+    C(0xe302, LTG,     RXY_a, EI,  0, a2, r1, 0, ld64, s64)
+    C(0xe332, LTGF,    RXY_a, GIE, 0, a2, r1, 0, ld32s, s64)
 /* LOAD BYTE */
     C(0xb926, LBR,     RRE,   EI,  0, r2_8s, 0, r1_32, mov2, 0)
     C(0xb906, LGBR,    RRE,   EI,  0, r2_8s, 0, r1, mov2, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 840bd6e..9239025 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1349,23 +1349,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
               op, r1, x2, b2, d2);
     addr = get_address(s, x2, b2, d2);
     switch (op) {
-    case 0x2: /* LTG R1,D2(X2,B2) [RXY] */
-    case 0x4: /* LG r1,d2(x2,b2) */
-        tcg_gen_qemu_ld64(regs[r1], addr, get_mem_index(s));
-        if (op == 0x2) {
-            set_cc_s64(s, regs[r1]);
-        }
-        break;
-    case 0x12: /* LT R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        store_reg32(r1, tmp32_1);
-        set_cc_s32(s, tmp32_1);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0xd: /* DSG      R1,D2(X2,B2)     [RXY] */
     case 0x1d: /* DSGF      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
@@ -3192,16 +3175,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x12: /* LTR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r2);
-        if (r1 != r2) {
-            store_reg32(r1, tmp32_1);
-        }
-        set_cc_s32(s, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x13: /* LCR    R1,R2     [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -4395,6 +4368,16 @@ static void cout_nz64(DisasContext *s, DisasOps *o)
     gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
 }
 
+static void cout_s32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
+}
+
+static void cout_s64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
+}
+
 static void cout_subs32(DisasContext *s, DisasOps *o)
 {
     gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
commit c698d8768756c66dd0dd55ea884c69c2212d59f9
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 10:27:29 2012 -0700

    target-s390: Convert LOAD (LOGICAL) BYTE, CHARACTER, HALFWORD
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f0dcea6..796185f 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -126,11 +126,41 @@
     C(0xe371, LAY,     RXY_a, LD,  0, a2, 0, r1, mov2, 0)
 /* LOAD ADDRESS RELATIVE LONG */
     C(0xc000, LARL,    RIL_b, Z,   0, ri2, 0, r1, mov2, 0)
+/* LOAD BYTE */
+    C(0xb926, LBR,     RRE,   EI,  0, r2_8s, 0, r1_32, mov2, 0)
+    C(0xb906, LGBR,    RRE,   EI,  0, r2_8s, 0, r1, mov2, 0)
+    C(0xe376, LB,      RXY_a, LD,  0, a2, new, r1_32, ld8s, 0)
+    C(0xe377, LGB,     RXY_a, LD,  0, a2, r1, 0, ld8s, 0)
+/* LOAD HALFWORD */
+    C(0xb927, LHR,     RRE,   EI,  0, r2_16s, 0, r1_32, mov2, 0)
+    C(0xb907, LGHR,    RRE,   EI,  0, r2_16s, 0, r1, mov2, 0)
+    C(0x4800, LH,      RX_a,  Z,   0, a2, new, r1_32, ld16s, 0)
+    C(0xe378, LHY,     RXY_a, LD,  0, a2, new, r1_32, ld16s, 0)
+    C(0xe315, LGH,     RXY_a, Z,   0, a2, r1, 0, ld16s, 0)
+/* LOAD HALFWORD IMMEDIATE */
+    C(0xa708, LHI,     RI_a,  Z,   0, i2, 0, r1_32, mov2, 0)
+    C(0xa709, LGHI,    RI_a,  Z,   0, i2, 0, r1, mov2, 0)
+/* LOAD HALFWORD RELATIVE LONG */
+    C(0xc405, LHRL,    RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0)
+    C(0xc404, LGHRL,   RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0)
 /* LOAD LOGICAL */
     C(0xb916, LLGFR,   RRE,   Z,   0, r2_32u, 0, r1, mov2, 0)
     C(0xe316, LLGF,    RXY_a, Z,   0, a2, r1, 0, ld32u, 0)
 /* LOAD LOGICAL RELATIVE LONG */
     C(0xc40e, LLGFRL,  RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0)
+/* LOAD LOGICAL CHARACTER */
+    C(0xb994, LLCR,    RRE,   EI,  0, r2_8u, 0, r1_32, mov2, 0)
+    C(0xb984, LLGCR,   RRE,   EI,  0, r2_8u, 0, r1, mov2, 0)
+    C(0xe394, LLC,     RXY_a, EI,  0, a2, new, r1_32, ld8u, 0)
+    C(0xe390, LLGC,    RXY_a, Z,   0, a2, r1, 0, ld8u, 0)
+/* LOAD LOGICAL HALFWORD */
+    C(0xb995, LLHR,    RRE,   EI,  0, r2_16u, 0, r1_32, mov2, 0)
+    C(0xb985, LLGHR,   RRE,   EI,  0, r2_16u, 0, r1, mov2, 0)
+    C(0xe395, LLH,     RXY_a, EI,  0, a2, new, r1_32, ld16u, 0)
+    C(0xe391, LLGH,    RXY_a, Z,   0, a2, r1, 0, ld16u, 0)
+/* LOAD LOGICAL HALFWORD RELATIVE LONG */
+    C(0xc402, LLHRL,   RIL_b, GIE, 0, ri2, new, r1_32, ld16u, 0)
+    C(0xc406, LLGHRL,  RIL_b, GIE, 0, ri2, r1, 0, ld16u, 0)
 
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0cf0902..840bd6e 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1391,12 +1391,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x15: /* LGH     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x17: /* LLGT      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
@@ -1458,30 +1452,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg8(r1, tmp3);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x76: /* LB R1,D2(X2,B2) [RXY] */
-    case 0x77: /* LGB R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8s(tmp2, addr, get_mem_index(s));
-        switch (op) {
-        case 0x76:
-            tcg_gen_ext8s_i64(tmp2, tmp2);
-            store_reg32_i64(r1, tmp2);
-            break;
-        case 0x77:
-            tcg_gen_ext8s_i64(tmp2, tmp2);
-            store_reg(r1, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x78: /* LHY R1,D2(X2,B2) [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x87: /* DLG      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_const_i32(r1);
@@ -1517,24 +1487,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x90: /* LLGC      R1,D2(X2,B2)     [RXY] */
-        tcg_gen_qemu_ld8u(regs[r1], addr, get_mem_index(s));
-        break;
-    case 0x91: /* LLGH      R1,D2(X2,B2)     [RXY] */
-        tcg_gen_qemu_ld16u(regs[r1], addr, get_mem_index(s));
-        break;
-    case 0x94: /* LLC     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8u(tmp2, addr, get_mem_index(s));
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x95: /* LLH     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld16u(tmp2, addr, get_mem_index(s));
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x97: /* DL     R1,D2(X2,B2)     [RXY] */
         /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
         /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -2194,16 +2146,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         s->is_jmp = DISAS_TB_JUMP;
         tcg_temp_free_i64(tmp);
         break;
-    case 0x8: /* lhi r1, i2 */
-        tmp32_1 = tcg_const_i32(i2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x9: /* lghi r1, i2 */
-        tmp = tcg_const_i64(i2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal a7 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -2911,12 +2853,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         }
         tcg_temp_free_i64(tmp);
         break;
-    case 0x6: /* LGBR R1,R2 [RRE] */
-        tmp2 = load_reg(r2);
-        tcg_gen_ext8s_i64(tmp2, tmp2);
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0xd: /* DSGR      R1,R2     [RRE] */
     case 0x1d: /* DSGFR      R1,R2     [RRE] */
         tmp = load_reg(r1 + 1);
@@ -2955,18 +2891,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x26: /* LBR R1,R2 [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_ext8s_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x27: /* LHR R1,R2 [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_ext16s_i32(tmp32_1, tmp32_1);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x83: /* FLOGR R1,R2 [RRE] */
         tmp = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
@@ -2975,18 +2899,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x84: /* LLGCR R1,R2 [RRE] */
-        tmp = load_reg(r2);
-        tcg_gen_andi_i64(tmp, tmp, 0xff);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x85: /* LLGHR R1,R2 [RRE] */
-        tmp = load_reg(r2);
-        tcg_gen_andi_i64(tmp, tmp, 0xffff);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x87: /* DLGR      R1,R2     [RRE] */
         tmp32_1 = tcg_const_i32(r1);
         tmp = load_reg(r2);
@@ -3021,18 +2933,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x94: /* LLCR R1,R2 [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xff);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0x95: /* LLHR R1,R2 [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tcg_gen_andi_i32(tmp32_1, tmp32_1, 0xffff);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x97: /* DLR     R1,R2     [RRE] */
         /* reg(r1) = reg(r1, r1+1) % reg(r2) */
         /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -3429,15 +3329,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         s->is_jmp = DISAS_TB_JUMP;
         break;
-    case 0x48: /* LH     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x4d: /* BAS    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4366,6 +4257,30 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
 static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
 {
     tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
@@ -4676,6 +4591,30 @@ static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in2 = true;
 }
 
+static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
 static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r3));
commit aedec19d628dacf4f04ee7258ac2c5c9e47b5a7e
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 09:57:07 2012 -0700

    target-s390: Convert LOAD ADDRESS
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 0a7cba3..f0dcea6 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -121,6 +121,11 @@
     C(0xc40d, LRL,     RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0)
     C(0xc408, LGRL,    RIL_b, GIE, 0, ri2, r1, 0, ld64, 0)
     C(0xc40c, LGFRL,   RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0)
+/* LOAD ADDRESS */
+    C(0x4100, LA,      RX_a,  Z,   0, a2, 0, r1, mov2, 0)
+    C(0xe371, LAY,     RXY_a, LD,  0, a2, 0, r1, mov2, 0)
+/* LOAD ADDRESS RELATIVE LONG */
+    C(0xc000, LARL,    RIL_b, Z,   0, ri2, 0, r1, mov2, 0)
 /* LOAD LOGICAL */
     C(0xb916, LLGFR,   RRE,   Z,   0, r2_32u, 0, r1, mov2, 0)
     C(0xe316, LLGF,    RXY_a, Z,   0, a2, r1, 0, ld32u, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5c31ecf..0cf0902 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1444,9 +1444,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
-        store_reg(r1, addr);
-        break;
     case 0x72: /* STCY R1,D2(X2,B2) [RXY] */
         tmp32_1 = load_reg32(r1);
         tmp2 = tcg_temp_new_i64();
@@ -3094,11 +3091,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
     LOG_DISAS("disas_c0: op 0x%x r1 %d i2 %d\n", op, r1, i2);
 
     switch (op) {
-    case 0: /* larl r1, i2 */
-        tmp = tcg_const_i64(target);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x4: /* BRCL     M1,I2     [RIL] */
         if (r1 == 15) { /* m1 == r1 */
             gen_goto_tb(s, 0, target);
@@ -3376,12 +3368,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x41:        /* la */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        store_reg(r1, tmp); /* FIXME: 31/24-bit addressing */
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x42: /* STC    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
commit 22c37a08bd0ce680d6b9750c73704a025bc3fc93
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 17 09:45:53 2012 -0700

    target-s390: Convert LOAD, LOAD LOGICAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 09eb30e..0a7cba3 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -107,6 +107,26 @@
     C(0xb9e7, XGRK,    RRF_a, DO,  r2, r3, r1, 0, xor, nz64)
     C(0xe382, XG,      RXY_a, Z,   r1, m2_64, r1, 0, xor, nz64)
 
+/* LOAD */
+    C(0x1800, LR,      RR_a,  Z,   0, r2_o, 0, cond_r1r2_32, mov2, 0)
+    C(0x5800, L,       RX_a,  Z,   0, a2, new, r1_32, ld32s, 0)
+    C(0xe358, LY,      RXY_a, Z,   0, a2, new, r1_32, ld32s, 0)
+    C(0xb904, LGR,     RRE,   Z,   0, r2_o, 0, r1, mov2, 0)
+    C(0xb914, LGFR,    RRE,   Z,   0, r2_32s, 0, r1, mov2, 0)
+    C(0xe304, LG,      RXY_a, Z,   0, a2, r1, 0, ld64, 0)
+    C(0xe314, LGF,     RXY_a, Z,   0, a2, r1, 0, ld32s, 0)
+/* LOAD IMMEDIATE */
+    C(0xc001, LGFI,    RIL_a, EI,  0, i2, 0, r1, mov2, 0)
+/* LOAD RELATIVE LONG */
+    C(0xc40d, LRL,     RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0)
+    C(0xc408, LGRL,    RIL_b, GIE, 0, ri2, r1, 0, ld64, 0)
+    C(0xc40c, LGFRL,   RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0)
+/* LOAD LOGICAL */
+    C(0xb916, LLGFR,   RRE,   Z,   0, r2_32u, 0, r1, mov2, 0)
+    C(0xe316, LLGF,    RXY_a, Z,   0, a2, r1, 0, ld32u, 0)
+/* LOAD LOGICAL RELATIVE LONG */
+    C(0xc40e, LLGFRL,  RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0)
+
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
     C(0x5c00, M,       RX_a,  Z,   r1p1_32s, m2_32s, new, r1_D32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 09c8534..5c31ecf 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1350,7 +1350,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
     addr = get_address(s, x2, b2, d2);
     switch (op) {
     case 0x2: /* LTG R1,D2(X2,B2) [RXY] */
-    case 0x4: /* lg r1,d2(x2,b2) */
+    case 0x4: /* LG r1,d2(x2,b2) */
         tcg_gen_qemu_ld64(regs[r1], addr, get_mem_index(s));
         if (op == 0x2) {
             set_cc_s64(s, regs[r1]);
@@ -1391,16 +1391,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x14: /* LGF      R1,D2(X2,B2)     [RXY] */
-    case 0x16: /* LLGF      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        if (op == 0x14) {
-            tcg_gen_ext32s_i64(tmp2, tmp2);
-        }
-        store_reg(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x15: /* LGH     R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tcg_gen_qemu_ld16s(tmp2, addr, get_mem_index(s));
@@ -1454,12 +1444,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x58: /* LY R1,D2(X2,B2) [RXY] */
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp3, addr, get_mem_index(s));
-        store_reg32_i64(r1, tmp3);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
         store_reg(r1, addr);
         break;
@@ -2930,9 +2914,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         }
         tcg_temp_free_i64(tmp);
         break;
-    case 0x4: /* LGR R1,R2 [RRE] */
-        store_reg(r1, regs[r2]);
-        break;
     case 0x6: /* LGBR R1,R2 [RRE] */
         tmp2 = load_reg(r2);
         tcg_gen_ext8s_i64(tmp2, tmp2);
@@ -2959,22 +2940,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x14: /* LGFR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp = tcg_temp_new_i64();
-        tcg_gen_ext_i32_i64(tmp, tmp32_1);
-        store_reg(r1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x16: /* LLGFR      R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp = tcg_temp_new_i64();
-        tcg_gen_extu_i32_i64(tmp, tmp32_1);
-        store_reg(r1, tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x17: /* LLGTR      R1,R2     [RRE] */
         tmp32_1 = load_reg32(r2);
         tmp = tcg_temp_new_i64();
@@ -3134,11 +3099,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         store_reg(r1, tmp);
         tcg_temp_free_i64(tmp);
         break;
-    case 0x1: /* LGFI R1,I2 [RIL] */
-        tmp = tcg_const_i64((int64_t)i2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0x4: /* BRCL     M1,I2     [RIL] */
         if (r1 == 15) { /* m1 == r1 */
             gen_goto_tb(s, 0, target);
@@ -3359,13 +3319,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         set_cc_comp32(s, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x18: /* LR     R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x1d: /* DR     R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3529,18 +3482,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x58: /* l r1, d2(x2, b2) */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x5d: /* D      R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4439,6 +4380,33 @@ static ExitStatus op_and(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
+    return NO_EXIT;
+}
+
+static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
+{
+    o->out = o->in2;
+    o->g_out = o->g_in2;
+    TCGV_UNUSED_I64(o->in2);
+    o->g_in2 = false;
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
@@ -4578,6 +4546,11 @@ static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
    generally handled by having a "prep" generator install the TCG global
    as the destination of the operation.  */
 
+static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_reg(get_field(f, r1), o->out);
+}
+
 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     store_reg32_i64(get_field(f, r1), o->out);
@@ -4592,6 +4565,13 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg32_i64(r1, o->out);
 }
 
+static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    if (get_field(f, r1) != get_field(f, r2)) {
+        store_reg32_i64(get_field(f, r1), o->out);
+    }
+}
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
commit a7e836d5ebef23022ec53a0dba5d3a1ac0883a03
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 16 15:20:51 2012 -0700

    target-s390: Convert COMPARE, COMPARE LOGICAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7563cd8..09eb30e 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -50,6 +50,54 @@
     C(0xb9e4, NGRK,    RRF_a, DO,  r2, r3, r1, 0, and, nz64)
     C(0xe380, NG,      RXY_a, Z,   r1, m2_64, r1, 0, and, nz64)
 
+/* COMPARE */
+    C(0x1900, CR,      RR_a,  Z,   r1_o, r2_o, 0, 0, 0, cmps32)
+    C(0x5900, C,       RX_a,  Z,   r1_o, m2_32s, 0, 0, 0, cmps32)
+    C(0xe359, CY,      RXY_a, LD,  r1_o, m2_32s, 0, 0, 0, cmps32)
+    C(0xb920, CGR,     RRE,   Z,   r1_o, r2_o, 0, 0, 0, cmps64)
+    C(0xb930, CGFR,    RRE,   Z,   r1_o, r2_32s, 0, 0, 0, cmps64)
+    C(0xe320, CG,      RXY_a, Z,   r1_o, m2_64, 0, 0, 0, cmps64)
+    C(0xe330, CGF,     RXY_a, Z,   r1_o, m2_32s, 0, 0, 0, cmps64)
+/* COMPARE IMMEDIATE */
+    C(0xc20d, CFI,     RIL_a, EI,  r1, i2, 0, 0, 0, cmps32)
+    C(0xc20c, CGFI,    RIL_a, EI,  r1, i2, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD */
+    C(0x4900, CH,      RX_a,  Z,   r1_o, m2_16s, 0, 0, 0, cmps32)
+    C(0xe379, CHY,     RXY_a, LD,  r1_o, m2_16s, 0, 0, 0, cmps32)
+    C(0xe334, CGH,     RXY_a, GIE, r1_o, m2_16s, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD IMMEDIATE */
+    C(0xa70e, CHI,     RI_a,  Z,   r1_o, i2, 0, 0, 0, cmps32)
+    C(0xa70f, CGHI,    RI_a,  Z,   r1_o, i2, 0, 0, 0, cmps64)
+    C(0xe554, CHHSI,   SIL,   GIE, m1_16s, i2, 0, 0, 0, cmps64)
+    C(0xe55c, CHSI,    SIL,   GIE, m1_32s, i2, 0, 0, 0, cmps64)
+    C(0xe558, CGHSI,   SIL,   GIE, m1_64, i2, 0, 0, 0, cmps64)
+/* COMPARE HALFWORD RELATIVE LONG */
+    C(0xc605, CHRL,    RIL_a, GIE, r1_o, mri2_32s, 0, 0, 0, cmps32)
+    C(0xc604, CGHRL,   RIL_a, GIE, r1_o, mri2_64, 0, 0, 0, cmps64)
+
+/* COMPARE LOGICAL */
+    C(0x1500, CLR,     RR_a,  Z,   r1, r2, 0, 0, 0, cmpu32)
+    C(0x5500, CL,      RX_a,  Z,   r1, m2_32s, 0, 0, 0, cmpu32)
+    C(0xe355, CLY,     RXY_a, LD,  r1, m2_32s, 0, 0, 0, cmpu32)
+    C(0xb921, CLGR,    RRE,   Z,   r1, r2, 0, 0, 0, cmpu64)
+    C(0xb931, CLGFR,   RRE,   Z,   r1, r2_32u, 0, 0, 0, cmpu64)
+    C(0xe321, CLG,     RXY_a, Z,   r1, m2_64, 0, 0, 0, cmpu64)
+    C(0xe331, CLGF,    RXY_a, Z,   r1, m2_32u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL IMMEDIATE */
+    C(0xc20f, CLFI,    RIL_a, EI,  r1, i2, 0, 0, 0, cmpu32)
+    C(0xc20e, CLGFI,   RIL_a, EI,  r1, i2_32u, 0, 0, 0, cmpu64)
+    C(0x9500, CLI,     SI,    Z,   m1_8u, i2_8u, 0, 0, 0, cmpu64)
+    C(0xeb55, CLIY,    SIY,   LD,  m1_8u, i2_8u, 0, 0, 0, cmpu64)
+    C(0xe555, CLHHSI,  SIL,   GIE, m1_16u, i2_16u, 0, 0, 0, cmpu64)
+    C(0xe55d, CLFHSI,  SIL,   GIE, m1_32u, i2_16u, 0, 0, 0, cmpu64)
+    C(0xe559, CLGHSI,  SIL,   GIE, m1_64, i2_16u, 0, 0, 0, cmpu64)
+/* COMPARE LOGICAL RELATIVE LONG */
+    C(0xc60f, CLRL,    RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu32)
+    C(0xc60a, CLGRL,   RIL_b, GIE, r1_o, mri2_64, 0, 0, 0, cmpu64)
+    C(0xc60e, CLGFRL,  RIL_b, GIE, r1_o, mri2_32u, 0, 0, 0, cmpu64)
+    C(0xc607, CLHRL,   RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu32)
+    C(0xc606, CLGHRL,  RIL_b, GIE, r1_o, mri2_16u, 0, 0, 0, cmpu64)
+
 /* EXCLUSIVE OR */
     C(0x1700, XR,      RR_a,  Z,   r1, r2, new, r1_32, xor, nz32)
     C(0xb9f7, XRK,     RRF_a, DO,  r2, r3, new, r1_32, xor, nz32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index ba154f7..09c8534 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1434,39 +1434,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg16(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x20: /* CG      R1,D2(X2,B2)     [RXY] */
-    case 0x21: /* CLG      R1,D2(X2,B2) */
-    case 0x30: /* CGF       R1,D2(X2,B2)     [RXY] */
-    case 0x31: /* CLGF      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        switch (op) {
-        case 0x20:
-        case 0x21:
-            tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-            break;
-        case 0x30:
-            tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-            break;
-        case 0x31:
-            tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-            break;
-        default:
-            tcg_abort();
-        }
-        switch (op) {
-        case 0x20:
-        case 0x30:
-            cmp_s64(s, regs[r1], tmp2);
-            break;
-        case 0x21:
-        case 0x31:
-            cmp_u64(s, regs[r1], tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x24: /* stg r1, d2(x2,b2) */
         tcg_gen_qemu_st64(regs[r1], addr, get_mem_index(s));
         break;
@@ -1881,17 +1848,6 @@ do_mh:
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x55: /* CLIY D1(B1),I2 [SIY] */
-        tmp3 = get_address(s, 0, b2, d2); /* SIY -> this is the 1st operand */
-        tmp = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld8u(tmp, tmp3, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp);
-        cmp_u32c(s, tmp32_1, (r1 << 4) | r3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x80: /* ICMH      R1,M3,D2(B2)     [RSY] */
         tmp = get_address(s, 0, b2, d2);
         tmp32_1 = tcg_const_i32(r1);
@@ -2267,16 +2223,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg(r1, tmp);
         tcg_temp_free_i64(tmp);
         break;
-    case 0xe: /* CHI     R1,I2     [RI] */
-        tmp32_1 = load_reg32(r1);
-        cmp_s32c(s, tmp32_1, i2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0xf: /* CGHI     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        cmp_s64c(s, tmp, i2);
-        tcg_temp_free_i64(tmp);
-        break;
     default:
         LOG_DISAS("illegal a7 operation 0x%x\n", op);
         gen_illegal_opcode(s);
@@ -3047,28 +2993,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x20: /* CGR      R1,R2     [RRE] */
-    case 0x30: /* CGFR     R1,R2     [RRE] */
-        tmp2 = load_reg(r2);
-        if (op == 0x30) {
-            tcg_gen_ext32s_i64(tmp2, tmp2);
-        }
-        tmp = load_reg(r1);
-        cmp_s64(s, tmp, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
-    case 0x21: /* CLGR     R1,R2     [RRE] */
-    case 0x31: /* CLGFR    R1,R2     [RRE] */
-        tmp2 = load_reg(r2);
-        if (op == 0x31) {
-            tcg_gen_ext32u_i64(tmp2, tmp2);
-        }
-        tmp = load_reg(r1);
-        cmp_u64(s, tmp, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x26: /* LBR R1,R2 [RRE] */
         tmp32_1 = load_reg32(r2);
         tcg_gen_ext8s_i32(tmp32_1, tmp32_1);
@@ -3301,40 +3225,6 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
     }
 }
 
-static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
-                     int i2)
-{
-    TCGv_i64 tmp;
-    TCGv_i32 tmp32_1;
-
-    switch (op) {
-    case 0xc: /* CGFI R1,I2 [RIL] */
-        tmp = load_reg(r1);
-        cmp_s64c(s, tmp, (int64_t)i2);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xe: /* CLGFI R1,I2 [RIL] */
-        tmp = load_reg(r1);
-        cmp_u64c(s, tmp, (uint64_t)(uint32_t)i2);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0xd: /* CFI R1,I2 [RIL] */
-        tmp32_1 = load_reg32(r1);
-        cmp_s32c(s, tmp32_1, i2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0xf: /* CLFI R1,I2 [RIL] */
-        tmp32_1 = load_reg32(r1);
-        cmp_u32c(s, tmp32_1, i2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    default:
-        LOG_DISAS("illegal c2 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-}
-
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3476,20 +3366,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x15: /* CLR    R1,R2     [RR] */
-    case 0x19: /* CR     R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r2);
-        if (opc == 0x15) {
-            cmp_u32(s, tmp32_1, tmp32_2);
-        } else {
-            cmp_s32(s, tmp32_1, tmp32_2);
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x1d: /* DR     R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3623,20 +3499,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x49: /* CH     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        cmp_s32(s, tmp32_1, tmp32_2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x4d: /* BAS    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3667,20 +3529,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x55: /* CL     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tmp32_2 = load_reg32(r1);
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        cmp_u32(s, tmp32_2, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x58: /* l r1, d2(x2, b2) */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3693,20 +3541,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x59: /* C      R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tmp32_2 = load_reg32(r1);
-        tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        cmp_s32(s, tmp32_2, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x5d: /* D      R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -3962,15 +3796,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x95: /* CLI    D1(B1),I2        [SI] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_si(s, insn, &i2, &b1, &d1);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld8u(tmp2, tmp, get_mem_index(s));
-        cmp_u64c(s, tmp2, i2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x9a: /* LAM      R1,R3,D2(B2)     [RS] */
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4239,21 +4064,11 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         }
         break;
     case 0xc0:
-    case 0xc2:
         insn = ld_code6(env, s->pc);
         r1 = (insn >> 36) & 0xf;
         op = (insn >> 32) & 0xf;
         i2 = (int)insn;
-        switch (opc) {
-        case 0xc0:
-            disas_c0(env, s, op, r1, i2);
-            break;
-        case 0xc2:
-            disas_c2(env, s, op, r1, i2);
-            break;
-        default:
-            tcg_abort();
-        }
+        disas_c0(env, s, op, r1, i2);
         break;
     case 0xd2: /* MVC    D1(L,B1),D2(B2)         [SS] */
     case 0xd4: /* NC     D1(L,B1),D2(B2)         [SS] */
@@ -4680,6 +4495,26 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
     gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
 }
 
+static void cout_cmps32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
+}
+
+static void cout_cmps64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
+}
+
+static void cout_cmpu32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
+}
+
+static void cout_cmpu64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
+}
+
 static void cout_nz32(DisasContext *s, DisasOps *o)
 {
     tcg_gen_ext32u_i64(cc_dst, o->out);
@@ -4819,6 +4654,27 @@ static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
     o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
 }
 
+static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
+}
+
 static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in1_la1(s, f, o);
@@ -4877,6 +4733,11 @@ static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
 }
 
+static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
+}
+
 static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
@@ -4901,11 +4762,45 @@ static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
 }
 
+static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_ri2(s, f, o);
+    tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_ri2(s, f, o);
+    tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_ri2(s, f, o);
+    tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_ri2(s, f, o);
+    tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
+}
+
 static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64(get_field(f, i2));
 }
 
+static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
+}
+
+static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
+}
+
 static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
commit 3bbfbd1f956d82f552a0fe160abf929ec88a78ad
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 16:28:39 2012 -0700

    target-s390: Convert AND, OR, XOR
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 94cd220..7563cd8 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,6 +41,24 @@
     C(0xeb7e, ALGSI,   SIY,   GIE, m1_64, i2, new, m1_64, add, addu64)
     C(0xecdb, ALGHSIK, RIE_d, DO,  r3, i2, r1, 0, add, addu64)
 
+/* AND */
+    C(0x1400, NR,      RR_a,  Z,   r1, r2, new, r1_32, and, nz32)
+    C(0xb9f4, NRK,     RRF_a, DO,  r2, r3, new, r1_32, and, nz32)
+    C(0x5400, N,       RX_a,  Z,   r1, m2_32s, new, r1_32, and, nz32)
+    C(0xe354, NY,      RXY_a, LD,  r1, m2_32s, new, r1_32, and, nz32)
+    C(0xb980, NGR,     RRE,   Z,   r1, r2, r1, 0, and, nz64)
+    C(0xb9e4, NGRK,    RRF_a, DO,  r2, r3, r1, 0, and, nz64)
+    C(0xe380, NG,      RXY_a, Z,   r1, m2_64, r1, 0, and, nz64)
+
+/* EXCLUSIVE OR */
+    C(0x1700, XR,      RR_a,  Z,   r1, r2, new, r1_32, xor, nz32)
+    C(0xb9f7, XRK,     RRF_a, DO,  r2, r3, new, r1_32, xor, nz32)
+    C(0x5700, X,       RX_a,  Z,   r1, m2_32s, new, r1_32, xor, nz32)
+    C(0xe357, XY,      RXY_a, LD,  r1, m2_32s, new, r1_32, xor, nz32)
+    C(0xb982, XGR,     RRE,   Z,   r1, r2, r1, 0, xor, nz64)
+    C(0xb9e7, XGRK,    RRF_a, DO,  r2, r3, r1, 0, xor, nz64)
+    C(0xe382, XG,      RXY_a, Z,   r1, m2_64, r1, 0, xor, nz64)
+
 /* MULTIPLY */
     C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
     C(0x5c00, M,       RX_a,  Z,   r1p1_32s, m2_32s, new, r1_D32, mul, 0)
@@ -68,6 +86,15 @@
     C(0xc201, MSFI,    RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
     C(0xc200, MSGFI,   RIL_a, GIE, r1_o, i2, r1, 0, mul, 0)
 
+/* OR */
+    C(0x1600, OR,      RR_a,  Z,   r1, r2, new, r1_32, or, nz32)
+    C(0xb9f6, ORK,     RRF_a, DO,  r2, r3, new, r1_32, or, nz32)
+    C(0x5600, O,       RX_a,  Z,   r1, m2_32s, new, r1_32, or, nz32)
+    C(0xe356, OY,      RXY_a, LD,  r1, m2_32s, new, r1_32, or, nz32)
+    C(0xb981, OGR,     RRE,   Z,   r1, r2, r1, 0, or, nz64)
+    C(0xb9e6, OGRK,    RRF_a, DO,  r2, r3, r1, 0, or, nz64)
+    C(0xe381, OG,      RXY_a, Z,   r1, m2_64, r1, 0, or, nz64)
+
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
     C(0xb9f9, SRK,     RRF_a, DO,  r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c38dde8..ba154f7 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1487,19 +1487,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_gen_qemu_st32(tmp2, addr, get_mem_index(s));
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x57: /* XY R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_gen_xor_i32(tmp32_2, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_2);
-        set_cc_nz_u32(s, tmp32_2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x58: /* LY R1,D2(X2,B2) [RXY] */
         tmp3 = tcg_temp_new_i64();
         tcg_gen_qemu_ld32u(tmp3, addr, get_mem_index(s));
@@ -1547,27 +1534,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg32_i64(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x80: /* NG      R1,D2(X2,B2)     [RXY] */
-    case 0x81: /* OG      R1,D2(X2,B2)     [RXY] */
-    case 0x82: /* XG      R1,D2(X2,B2)     [RXY] */
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp3, addr, get_mem_index(s));
-        switch (op) {
-        case 0x80:
-            tcg_gen_and_i64(regs[r1], regs[r1], tmp3);
-            break;
-        case 0x81:
-            tcg_gen_or_i64(regs[r1], regs[r1], tmp3);
-            break;
-        case 0x82:
-            tcg_gen_xor_i64(regs[r1], regs[r1], tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        set_cc_nz_u64(s, regs[r1]);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x87: /* DLG      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_const_i32(r1);
@@ -3115,29 +3081,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x80: /* NGR R1,R2 [RRE] */
-    case 0x81: /* OGR R1,R2 [RRE] */
-    case 0x82: /* XGR R1,R2 [RRE] */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        switch (op) {
-        case 0x80:
-            tcg_gen_and_i64(tmp, tmp, tmp2);
-            break;
-        case 0x81:
-            tcg_gen_or_i64(tmp, tmp, tmp2);
-            break;
-        case 0x82:
-            tcg_gen_xor_i64(tmp, tmp, tmp2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp);
-        set_cc_nz_u64(s, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x83: /* FLOGR R1,R2 [RRE] */
         tmp = load_reg(r2);
         tmp32_1 = tcg_const_i32(r1);
@@ -3392,23 +3335,6 @@ static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
     }
 }
 
-static void gen_and_or_xor_i32(int opc, TCGv_i32 tmp, TCGv_i32 tmp2)
-{
-    switch (opc & 0xf) {
-    case 0x4:
-        tcg_gen_and_i32(tmp, tmp, tmp2);
-        break;
-    case 0x6:
-        tcg_gen_or_i32(tmp, tmp, tmp2);
-        break;
-    case 0x7:
-        tcg_gen_xor_i32(tmp, tmp, tmp2);
-        break;
-    default:
-        tcg_abort();
-    }
-}
-
 static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 {
     TCGv_i64 tmp, tmp2, tmp3, tmp4;
@@ -3543,19 +3469,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         set_cc_comp32(s, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x14: /* NR     R1,R2     [RR] */
-    case 0x16: /* OR     R1,R2     [RR] */
-    case 0x17: /* XR     R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_2 = load_reg32(r2);
-        tmp32_1 = load_reg32(r1);
-        gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_1);
-        set_cc_nz_u32(s, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x18: /* LR     R1,R2     [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3768,24 +3681,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x54: /* N      R1,D2(X2,B2)     [RX] */
-    case 0x56: /* O      R1,D2(X2,B2)     [RX] */
-    case 0x57: /* X      R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        gen_and_or_xor_i32(opc, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_1);
-        set_cc_nz_u32(s, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x58: /* l r1, d2(x2, b2) */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4723,6 +4618,12 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_and(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_and_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
 {
     tcg_gen_mul_i64(o->out, o->in1, o->in2);
@@ -4736,12 +4637,24 @@ static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_or(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_or_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
     return NO_EXIT;
 }
 
+static ExitStatus op_xor(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_xor_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 /* ====================================================================== */
 /* The "Cc OUTput" generators.  Given the generated output (and in some cases
    the original inputs), update the various cc data structures in order to
@@ -4767,6 +4680,17 @@ static void cout_addu64(DisasContext *s, DisasOps *o)
     gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
 }
 
+static void cout_nz32(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_ext32u_i64(cc_dst, o->out);
+    gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
+}
+
+static void cout_nz64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
+}
+
 static void cout_subs32(DisasContext *s, DisasOps *o)
 {
     gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
commit 1ac5889f48127321a585886524013fcb6e2c91e3
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 25 15:26:59 2012 -0700

    target-s390: Convert 64-bit MULTIPLY LOGICAL
    
    Use a new "retxl" member of CPUS290XState to return the "eXtra Low" part
    of a 128-bit value.  That said, this will get used when two independent
    values need returning (e.g. quotient+remainder) as well.
    
    At the same time, shuffle the elements of CPUS390XState to get this new
    space from existing padding in the structure.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 83e618a..afe33dc 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -60,17 +60,20 @@ typedef struct ExtQueue {
 } ExtQueue;
 
 typedef struct CPUS390XState {
-    uint64_t regs[16];	/* GP registers */
+    uint64_t regs[16];     /* GP registers */
+    CPU_DoubleU fregs[16]; /* FP registers */
+    uint32_t aregs[16];    /* access registers */
 
-    uint32_t aregs[16];	/* access registers */
+    uint32_t fpc;          /* floating-point control register */
+    uint32_t cc_op;
 
-    uint32_t fpc;	/* floating-point control register */
-    CPU_DoubleU fregs[16]; /* FP registers */
     float_status fpu_status; /* passed to softfloat lib */
 
+    /* The low part of a 128-bit return, or remainder of a divide.  */
+    uint64_t retxl;
+
     PSW psw;
 
-    uint32_t cc_op;
     uint64_t cc_src;
     uint64_t cc_dst;
     uint64_t cc_vr;
@@ -86,8 +89,8 @@ typedef struct CPUS390XState {
 
     uint64_t cregs[16]; /* control registers */
 
-    int pending_int;
     ExtQueue ext_queue[MAX_EXT_QUEUE];
+    int pending_int;
 
     int ext_index;
 
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 2498f83..88a065c 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -9,7 +9,7 @@ DEF_HELPER_4(clc, i32, env, i32, i64, i64)
 DEF_HELPER_3(mvcl, i32, env, i32, i32)
 DEF_HELPER_4(clm, i32, env, i32, i32, i64)
 DEF_HELPER_4(stcm, void, env, i32, i32, i64)
-DEF_HELPER_3(mlg, void, env, i32, i64)
+DEF_HELPER_FLAGS_3(mul128, TCG_CALL_NO_RWG, i64, env, i64, i64)
 DEF_HELPER_3(dlg, void, env, i32, i64)
 DEF_HELPER_4(srst, i32, env, i32, i32, i32)
 DEF_HELPER_4(clst, i32, env, i32, i32, i32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index ca12e47..94cd220 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -54,6 +54,8 @@
 /* MULTIPLY LOGICAL */
     C(0xb996, MLR,     RRE,   Z,   r1p1_32u, r2_32u, new, r1_D32, mul, 0)
     C(0xe396, ML,      RXY_a, Z,   r1p1_32u, m2_32u, new, r1_D32, mul, 0)
+    C(0xb986, MLGR,    RRE,   Z,   r1p1, r2_o, r1_P, 0, mul128, 0)
+    C(0xe386, MLG,     RXY_a, Z,   r1p1, m2_64, r1_P, 0, mul128, 0)
 /* MULTIPLY SINGLE */
     C(0xb252, MSR,     RRE,   Z,   r1_o, r2_o, new, r1_32, mul, 0)
     C(0x7100, MS,      RX_a,  Z,   r1_o, m2_32s, new, r1_32, mul, 0)
diff --git a/target-s390x/int_helper.c b/target-s390x/int_helper.c
index b683709..4f18d29 100644
--- a/target-s390x/int_helper.c
+++ b/target-s390x/int_helper.c
@@ -30,18 +30,11 @@
 #endif
 
 /* 64/64 -> 128 unsigned multiplication */
-void HELPER(mlg)(CPUS390XState *env, uint32_t r1, uint64_t v2)
+uint64_t HELPER(mul128)(CPUS390XState *env, uint64_t v1, uint64_t v2)
 {
-#if HOST_LONG_BITS == 64 && defined(__GNUC__)
-    /* assuming 64-bit hosts have __uint128_t */
-    __uint128_t res = (__uint128_t)env->regs[r1 + 1];
-
-    res *= (__uint128_t)v2;
-    env->regs[r1] = (uint64_t)(res >> 64);
-    env->regs[r1 + 1] = (uint64_t)res;
-#else
-    mulu64(&env->regs[r1 + 1], &env->regs[r1], env->regs[r1 + 1], v2);
-#endif
+    uint64_t reth;
+    mulu64(&env->retxl, &reth, v1, v2);
+    return reth;
 }
 
 /* 128 -> 64/64 unsigned division */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a08d471..c38dde8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -293,6 +293,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
 #endif
 }
 
+static inline void return_low128(TCGv_i64 dest)
+{
+    tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
+}
+
 static inline void update_psw_addr(DisasContext *s)
 {
     /* psw.addr */
@@ -1563,14 +1568,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         set_cc_nz_u64(s, regs[r1]);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x86: /* MLG      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_const_i32(r1);
-        tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        gen_helper_mlg(cpu_env, tmp32_1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x87: /* DLG      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
         tmp32_1 = tcg_const_i32(r1);
@@ -4732,6 +4729,13 @@ static ExitStatus op_mul(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
+{
+    gen_helper_mul128(o->out, cpu_env, o->in1, o->in2);
+    return_low128(o->out2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4800,6 +4804,15 @@ static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_out = true;
 }
 
+static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    o->out = regs[r1];
+    o->out2 = regs[(r1 + 1) & 15];
+    o->g_out = o->g_out2 = true;
+}
+
 /* ====================================================================== */
 /* The "Write OUTput" generators.  These generally perform some non-trivial
    copy of data to TCG globals, or to main memory.  The trivial cases are
@@ -4844,6 +4857,13 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = true;
 }
 
+static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    o->in1 = load_reg((r1 + 1) & 15);
+}
+
 static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     /* ??? Specification exception: r1 must be even.  */
commit d87aaf934f2fa24443bba7db60036b698e04d6a8
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 25 15:17:59 2012 -0700

    target-s390: Convert 32-bit MULTIPLY, MULTIPLY LOGICAL
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 055113a..ca12e47 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,12 +41,19 @@
     C(0xeb7e, ALGSI,   SIY,   GIE, m1_64, i2, new, m1_64, add, addu64)
     C(0xecdb, ALGHSIK, RIE_d, DO,  r3, i2, r1, 0, add, addu64)
 
+/* MULTIPLY */
+    C(0x1c00, MR,      RR_a,  Z,   r1p1_32s, r2_32s, new, r1_D32, mul, 0)
+    C(0x5c00, M,       RX_a,  Z,   r1p1_32s, m2_32s, new, r1_D32, mul, 0)
+    C(0xe35c, MFY,     RXY_a, GIE, r1p1_32s, m2_32s, new, r1_D32, mul, 0)
 /* MULTIPLY HALFWORD */
     C(0x4c00, MH,      RX_a,  Z,   r1_o, m2_16s, new, r1_32, mul, 0)
     C(0xe37c, MHY,     RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
 /* MULTIPLY HALFWORD IMMEDIATE */
     C(0xa70c, MHI,     RI_a,  Z,   r1_o, i2, new, r1_32, mul, 0)
     C(0xa70d, MGHI,    RI_a,  Z,   r1_o, i2, r1, 0, mul, 0)
+/* MULTIPLY LOGICAL */
+    C(0xb996, MLR,     RRE,   Z,   r1p1_32u, r2_32u, new, r1_D32, mul, 0)
+    C(0xe396, ML,      RXY_a, Z,   r1p1_32u, m2_32u, new, r1_D32, mul, 0)
 /* MULTIPLY SINGLE */
     C(0xb252, MSR,     RRE,   Z,   r1_o, r2_o, new, r1_32, mul, 0)
     C(0x7100, MS,      RX_a,  Z,   r1_o, m2_32s, new, r1_32, mul, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f09b7d1..a08d471 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1624,18 +1624,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg32_i64(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x96: /* ML      R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32u_i64(tmp3, tmp3);
-        tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        tcg_gen_mul_i64(tmp2, tmp2, tmp3);
-        store_reg32_i64((r1 + 1) & 15, tmp2);
-        tcg_gen_shri_i64(tmp2, tmp2, 32);
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x97: /* DL     R1,D2(X2,B2)     [RXY] */
         /* reg(r1) = reg(r1, r1+1) % ld32(addr) */
         /* reg(r1+1) = reg(r1, r1+1) / ld32(addr) */
@@ -3219,19 +3207,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x96: /* MLR     R1,R2     [RRE] */
-        /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
-        tmp2 = load_reg(r2);
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32u_i64(tmp2, tmp2);
-        tcg_gen_ext32u_i64(tmp3, tmp3);
-        tcg_gen_mul_i64(tmp2, tmp2, tmp3);
-        store_reg32_i64((r1 + 1) & 15, tmp2);
-        tcg_gen_shri_i64(tmp2, tmp2, 32);
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x97: /* DLR     R1,R2     [RRE] */
         /* reg(r1) = reg(r1, r1+1) % reg(r2) */
         /* reg(r1+1) = reg(r1, r1+1) / reg(r2) */
@@ -3605,21 +3580,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x1c: /* MR     R1,R2     [RR] */
-        /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp2 = load_reg(r2);
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32s_i64(tmp2, tmp2);
-        tcg_gen_ext32s_i64(tmp3, tmp3);
-        tcg_gen_mul_i64(tmp2, tmp2, tmp3);
-        store_reg32_i64((r1 + 1) & 15, tmp2);
-        tcg_gen_shri_i64(tmp2, tmp2, 32);
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x1d: /* DR     R1,R2               [RR] */
         insn = ld_code2(env, s->pc);
         decode_rr(s, insn, &r1, &r2);
@@ -3855,23 +3815,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x5c: /* M      R1,D2(X2,B2)        [RX] */
-        /* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
-        tmp3 = load_reg((r1 + 1) & 15);
-        tcg_gen_ext32s_i64(tmp2, tmp2);
-        tcg_gen_ext32s_i64(tmp3, tmp3);
-        tcg_gen_mul_i64(tmp2, tmp2, tmp3);
-        store_reg32_i64((r1 + 1) & 15, tmp2);
-        tcg_gen_shri_i64(tmp2, tmp2, 32);
-        store_reg32_i64(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x5d: /* D      R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp3 = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4868,6 +4811,15 @@ static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg32_i64(get_field(f, r1), o->out);
 }
 
+static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    store_reg32_i64((r1 + 1) & 15, o->out);
+    tcg_gen_shri_i64(o->out, o->out, 32);
+    store_reg32_i64(r1, o->out);
+}
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@@ -4892,6 +4844,22 @@ static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
     o->g_in1 = true;
 }
 
+static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32s_i64(o->in1, regs[(r1 + 1) & 15]);
+}
+
+static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    /* ??? Specification exception: r1 must be even.  */
+    int r1 = get_field(f, r1);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in1, regs[(r1 + 1) & 15]);
+}
+
 static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r2));
commit d1c04a2ba05bec8567a52f28979288e2237dfe9c
Author: Richard Henderson <rth at twiddle.net>
Date:   Tue Sep 25 15:10:35 2012 -0700

    target-s390: Convert MULTIPLY HALFWORD, SINGLE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index acde181..055113a 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -41,6 +41,24 @@
     C(0xeb7e, ALGSI,   SIY,   GIE, m1_64, i2, new, m1_64, add, addu64)
     C(0xecdb, ALGHSIK, RIE_d, DO,  r3, i2, r1, 0, add, addu64)
 
+/* MULTIPLY HALFWORD */
+    C(0x4c00, MH,      RX_a,  Z,   r1_o, m2_16s, new, r1_32, mul, 0)
+    C(0xe37c, MHY,     RXY_a, GIE, r1_o, m2_16s, new, r1_32, mul, 0)
+/* MULTIPLY HALFWORD IMMEDIATE */
+    C(0xa70c, MHI,     RI_a,  Z,   r1_o, i2, new, r1_32, mul, 0)
+    C(0xa70d, MGHI,    RI_a,  Z,   r1_o, i2, r1, 0, mul, 0)
+/* MULTIPLY SINGLE */
+    C(0xb252, MSR,     RRE,   Z,   r1_o, r2_o, new, r1_32, mul, 0)
+    C(0x7100, MS,      RX_a,  Z,   r1_o, m2_32s, new, r1_32, mul, 0)
+    C(0xe351, MSY,     RXY_a, LD,  r1_o, m2_32s, new, r1_32, mul, 0)
+    C(0xb90c, MSGR,    RRE,   Z,   r1_o, r2_o, r1, 0, mul, 0)
+    C(0xb91c, MSGFR,   RRE,   Z,   r1_o, r2_32s, r1, 0, mul, 0)
+    C(0xe30c, MSG,     RXY_a, Z,   r1_o, m2_64, r1, 0, mul, 0)
+    C(0xe31c, MSGF,    RXY_a, Z,   r1_o, m2_32s, r1, 0, mul, 0)
+/* MULTIPLY SINGLE IMMEDIATE */
+    C(0xc201, MSFI,    RIL_a, GIE, r1_o, i2, new, r1_32, mul, 0)
+    C(0xc200, MSGFI,   RIL_a, GIE, r1_o, i2, r1, 0, mul, 0)
+
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
     C(0xb9f9, SRK,     RRF_a, DO,  r2, r3, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 5d5856a..f09b7d1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -575,22 +575,12 @@ static void set_cc_nabs64(DisasContext *s, TCGv_i64 v1)
     gen_op_update1_cc_i64(s, CC_OP_NABS_64, v1);
 }
 
-static void set_cc_add32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
-{
-    gen_op_update3_cc_i32(s, CC_OP_ADD_32, v1, v2, vr);
-}
-
 static void set_cc_addu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
                           TCGv_i32 vr)
 {
     gen_op_update3_cc_i32(s, CC_OP_ADDU_32, v1, v2, vr);
 }
 
-static void set_cc_sub32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
-{
-    gen_op_update3_cc_i32(s, CC_OP_SUB_32, v1, v2, vr);
-}
-
 static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
 {
     gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
@@ -1371,17 +1361,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0xc: /* MSG      R1,D2(X2,B2)     [RXY] */
-    case 0x1c: /* MSGF     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        if (op == 0xc) {
-            tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        } else {
-            tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        }
-        tcg_gen_mul_i64(regs[r1], regs[r1], tmp2);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0xd: /* DSG      R1,D2(X2,B2)     [RXY] */
     case 0x1d: /* DSGF      R1,D2(X2,B2)     [RXY] */
         tmp2 = tcg_temp_new_i64();
@@ -2337,18 +2316,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg(r1, tmp);
         tcg_temp_free_i64(tmp);
         break;
-    case 0xc: /* MHI     R1,I2     [RI] */
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_muli_i32(tmp32_1, tmp32_1, i2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    case 0xd: /* MGHI     R1,I2     [RI] */
-        tmp = load_reg(r1);
-        tcg_gen_muli_i64(tmp, tmp, i2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
     case 0xe: /* CHI     R1,I2     [RI] */
         tmp32_1 = load_reg32(r1);
         cmp_s32c(s, tmp32_1, i2);
@@ -2408,14 +2375,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         store_reg32(r1, tmp32_1);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x52: /* MSR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r2);
-        tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x54: /* MVPG     R1,R2     [RRE] */
         tmp = load_reg(0);
         tmp2 = load_reg(r1);
@@ -3083,18 +3042,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0xc: /* MSGR      R1,R2     [RRE] */
-    case 0x1c: /* MSGFR      R1,R2     [RRE] */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        if (op == 0x1c) {
-            tcg_gen_ext32s_i64(tmp2, tmp2);
-        }
-        tcg_gen_mul_i64(tmp, tmp, tmp2);
-        store_reg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0xd: /* DSGR      R1,R2     [RRE] */
     case 0x1d: /* DSGFR      R1,R2     [RRE] */
         tmp = load_reg(r1 + 1);
@@ -3820,41 +3767,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x4a: /* AH     R1,D2(X2,B2)     [RX] */
-    case 0x4b: /* SH     R1,D2(X2,B2)     [RX] */
-    case 0x4c: /* MH     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp32_3 = tcg_temp_new_i32();
-
-        tcg_gen_qemu_ld16s(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        switch (opc) {
-        case 0x4a:
-            tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
-            set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x4b:
-            tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
-            set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x4c:
-            tcg_gen_mul_i32(tmp32_3, tmp32_1, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_3);
-
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x4d: /* BAS    R1,D2(X2,B2)     [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4022,21 +3934,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x71: /* MS      R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32s(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        tcg_gen_mul_i32(tmp32_1, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        break;
     case 0x78: /* LE     R1,D2(X2,B2)        [RX] */
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -4886,6 +4783,12 @@ static ExitStatus op_add(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_mul(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_mul_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
 {
     tcg_gen_sub_i64(o->out, o->in1, o->in2);
@@ -4983,6 +4886,12 @@ static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in1 = load_reg(get_field(f, r1));
 }
 
+static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = regs[get_field(f, r1)];
+    o->g_in1 = true;
+}
+
 static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in1 = load_reg(get_field(f, r2));
@@ -5027,6 +4936,12 @@ static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = load_reg(get_field(f, r2));
 }
 
+static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = regs[get_field(f, r2)];
+    o->g_in2 = true;
+}
+
 static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     o->in2 = load_reg(get_field(f, r3));
commit e272b3ace35ffafe24754986b999bda19f56f373
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 16 14:42:49 2012 -0700

    target-s390: Implement ADD LOGICAL WITH SIGNED IMMEDIATE
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 44e1ca7..acde181 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -35,6 +35,11 @@
 /* ADD LOGICAL IMMEDIATE */
     C(0xc20b, ALFI,    RIL_a, EI,  r1, i2_32u, new, r1_32, add, addu32)
     C(0xc20a, ALGFI,   RIL_a, EI,  r1, i2_32u, r1, 0, add, addu64)
+/* ADD LOGICAL WITH SIGNED IMMEDIATE */
+    C(0xeb6e, ALSI,    SIY,   GIE, m1_32u, i2, new, m1_32, add, addu32)
+    C(0xecda, ALHSIK,  RIE_d, DO,  r3, i2, new, r1_32, add, addu32)
+    C(0xeb7e, ALGSI,   SIY,   GIE, m1_64, i2, new, m1_64, add, addu64)
+    C(0xecdb, ALGHSIK, RIE_d, DO,  r3, i2, r1, 0, add, addu64)
 
 /* SUBTRACT */
     C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0a916b1..5d5856a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5005,6 +5005,13 @@ static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
 }
 
+static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
+}
+
 static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in1_la1(s, f, o);
commit 3f4cb56a4351b0710f90d1205f2d6178a8ebc02f
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 27 14:46:42 2012 -0700

    target-s390: Implement SUBTRACT HALFWORD
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 2acc8f0..44e1ca7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -46,6 +46,9 @@
     C(0xb9e9, SGRK,    RRF_a, DO,  r2, r3, r1, 0, sub, subs64)
     C(0xe309, SG,      RXY_a, Z,   r1, m2_64, r1, 0, sub, subs64)
     C(0xe319, SGF,     RXY_a, Z,   r1, m2_32s, r1, 0, sub, subs64)
+/* SUBTRACT HALFWORD */
+    C(0x4b00, SH,      RX_a,  Z,   r1, m2_16s, new, r1_32, sub, subs32)
+    C(0xe37b, SHY,     RXY_a, LD,  r1, m2_16s, new, r1_32, sub, subs32)
 /* SUBTRACT LOGICAL */
     C(0x1f00, SLR,     RR_a,  Z,   r1, r2, new, r1_32, sub, subu32)
     C(0xb9fb, SLRK,    RRF_a, DO,  r2, r3, new, r1_32, sub, subu32)
commit d82287dee9d8bfe2c4cb520e30c76244fcbb705c
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 16 14:09:45 2012 -0700

    target-s390: Convert ADD HALFWORD
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 7d81928..2acc8f0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -15,6 +15,13 @@
     C(0xc208, AGFI,    RIL_a, EI,  r1, i2, r1, 0, add, adds64)
     C(0xeb7a, AGSI,    SIY,   GIE, m1_64, i2, new, m1_64, add, adds64)
     C(0xecd9, AGHIK,   RIE_d, DO,  r3, i2, r1, 0, add, adds64)
+/* ADD HALFWORD */
+    C(0x4a00, AH,      RX_a,  Z,   r1, m2_16s, new, r1_32, add, adds32)
+    C(0xe37a, AHY,     RXY_a, LD,  r1, m2_16s, new, r1_32, add, adds32)
+/* ADD HALFWORD IMMEDIATE */
+    C(0xa70a, AHI,     RI_a,  Z,   r1, i2, new, r1_32, add, adds32)
+    C(0xa70b, AGHI,    RI_a,  Z,   r1, i2, r1, 0, add, adds64)
+
 /* ADD LOGICAL */
     C(0x1e00, ALR,     RR_a,  Z,   r1, r2, new, r1_32, add, addu32)
     C(0xb9fa, ALRK,    RRF_a, DO,  r2, r3, new, r1_32, add, addu32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 076bb7f..0a916b1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -559,11 +559,6 @@ static inline void set_cc_s64(DisasContext *s, TCGv_i64 val)
     gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, val);
 }
 
-static void set_cc_add64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
-{
-    gen_op_update3_cc_i64(s, CC_OP_ADD_64, v1, v2, vr);
-}
-
 static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
                           TCGv_i64 vr)
 {
@@ -2267,7 +2262,7 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int i2)
 {
     TCGv_i64 tmp, tmp2;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i32 tmp32_1;
     int l1;
 
     LOG_DISAS("disas_a7: op 0x%x r1 %d i2 0x%x\n", op, r1, i2);
@@ -2342,36 +2337,6 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg(r1, tmp);
         tcg_temp_free_i64(tmp);
         break;
-    case 0xa: /* AHI     R1,I2     [RI] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp32_3 = tcg_const_i32(i2);
-
-        if (i2 < 0) {
-            tcg_gen_subi_i32(tmp32_2, tmp32_1, -i2);
-        } else {
-            tcg_gen_add_i32(tmp32_2, tmp32_1, tmp32_3);
-        }
-
-        store_reg32(r1, tmp32_2);
-        set_cc_add32(s, tmp32_1, tmp32_3, tmp32_2);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0xb: /* aghi r1, i2 */
-        tmp = load_reg(r1);
-        tmp2 = tcg_const_i64(i2);
-
-        if (i2 < 0) {
-            tcg_gen_subi_i64(regs[r1], tmp, -i2);
-        } else {
-            tcg_gen_add_i64(regs[r1], tmp, tmp2);
-        }
-        set_cc_add64(s, tmp, tmp2, regs[r1]);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0xc: /* MHI     R1,I2     [RI] */
         tmp32_1 = load_reg32(r1);
         tcg_gen_muli_i32(tmp32_1, tmp32_1, i2);
@@ -5078,6 +5043,12 @@ static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
     o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
 }
 
+static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
+}
+
 static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     in2_a2(s, f, o);
commit d5a103cd6eb3b407feb4e007cb778a89b1b20c5f
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Sep 14 19:31:57 2012 -0700

    target-s390: Reorg exception handling
    
    Make the user path more like the system path.  Prepare for more kinds
    of runtime exceptions.  Rename ILC to ILEN to make it clear that we
    want to pass around a full instruction length, rather than a "code"
    that happens to be stored one bit left in a larger field.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/linux-user/main.c b/linux-user/main.c
index f6c4c8d..15bacb9 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2933,71 +2933,115 @@ void cpu_loop(CPUAlphaState *env)
 #ifdef TARGET_S390X
 void cpu_loop(CPUS390XState *env)
 {
-    int trapnr;
+    int trapnr, n, sig;
     target_siginfo_t info;
+    target_ulong addr;
 
     while (1) {
-        trapnr = cpu_s390x_exec (env);
-
+        trapnr = cpu_s390x_exec(env);
         switch (trapnr) {
         case EXCP_INTERRUPT:
-            /* just indicate that signals should be handled asap */
+            /* Just indicate that signals should be handled asap.  */
             break;
-        case EXCP_DEBUG:
-            {
-                int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
-                if (sig) {
-                    info.si_signo = sig;
-                    info.si_errno = 0;
-                    info.si_code = TARGET_TRAP_BRKPT;
-                    queue_signal(env, info.si_signo, &info);
-                }
+        case EXCP_SVC:
+            n = env->int_svc_code;
+            if (!n) {
+                /* syscalls > 255 */
+                n = env->regs[1];
             }
+            env->psw.addr += env->int_svc_ilen;
+            env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
+                                      env->regs[4], env->regs[5],
+                                      env->regs[6], env->regs[7], 0, 0);
             break;
-        case EXCP_SVC:
-            {
-                int n = env->int_svc_code;
-                if (!n) {
-                    /* syscalls > 255 */
-                    n = env->regs[1];
-                }
-                env->psw.addr += env->int_svc_ilc;
-                env->regs[2] = do_syscall(env, n,
-                           env->regs[2],
-                           env->regs[3],
-                           env->regs[4],
-                           env->regs[5],
-                           env->regs[6],
-                           env->regs[7],
-                           0, 0);
+
+        case EXCP_DEBUG:
+            sig = gdb_handlesig(env, TARGET_SIGTRAP);
+            if (sig) {
+                n = TARGET_TRAP_BRKPT;
+                goto do_signal_pc;
             }
             break;
-        case EXCP_ADDR:
-            {
-                info.si_signo = SIGSEGV;
-                info.si_errno = 0;
+        case EXCP_PGM:
+            n = env->int_pgm_code;
+            switch (n) {
+            case PGM_OPERATION:
+            case PGM_PRIVILEGED:
+                sig = SIGILL;
+                n = TARGET_ILL_ILLOPC;
+                goto do_signal_pc;
+            case PGM_PROTECTION:
+            case PGM_ADDRESSING:
+                sig = SIGSEGV;
                 /* XXX: check env->error_code */
-                info.si_code = TARGET_SEGV_MAPERR;
-                info._sifields._sigfault._addr = env->__excp_addr;
-                queue_signal(env, info.si_signo, &info);
+                n = TARGET_SEGV_MAPERR;
+                addr = env->__excp_addr;
+                goto do_signal;
+            case PGM_EXECUTE:
+            case PGM_SPECIFICATION:
+            case PGM_SPECIAL_OP:
+            case PGM_OPERAND:
+            do_sigill_opn:
+                sig = SIGILL;
+                n = TARGET_ILL_ILLOPN;
+                goto do_signal_pc;
+
+            case PGM_FIXPT_OVERFLOW:
+                sig = SIGFPE;
+                n = TARGET_FPE_INTOVF;
+                goto do_signal_pc;
+            case PGM_FIXPT_DIVIDE:
+                sig = SIGFPE;
+                n = TARGET_FPE_INTDIV;
+                goto do_signal_pc;
+
+            case PGM_DATA:
+                n = (env->fpc >> 8) & 0xff;
+                if (n == 0xff) {
+                    /* compare-and-trap */
+                    goto do_sigill_opn;
+                } else {
+                    /* An IEEE exception, simulated or otherwise.  */
+                    if (n & 0x80) {
+                        n = TARGET_FPE_FLTINV;
+                    } else if (n & 0x40) {
+                        n = TARGET_FPE_FLTDIV;
+                    } else if (n & 0x20) {
+                        n = TARGET_FPE_FLTOVF;
+                    } else if (n & 0x10) {
+                        n = TARGET_FPE_FLTUND;
+                    } else if (n & 0x08) {
+                        n = TARGET_FPE_FLTRES;
+                    } else {
+                        /* ??? Quantum exception; BFP, DFP error.  */
+                        goto do_sigill_opn;
+                    }
+                    sig = SIGFPE;
+                    goto do_signal_pc;
+                }
+
+            default:
+                fprintf(stderr, "Unhandled program exception: %#x\n", n);
+                cpu_dump_state(env, stderr, fprintf, 0);
+                exit(1);
             }
             break;
-        case EXCP_SPEC:
-            {
-                fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
-                info.si_signo = SIGILL;
-                info.si_errno = 0;
-                info.si_code = TARGET_ILL_ILLOPC;
-                info._sifields._sigfault._addr = env->__excp_addr;
-                queue_signal(env, info.si_signo, &info);
-            }
+
+        do_signal_pc:
+            addr = env->psw.addr;
+        do_signal:
+            info.si_signo = sig;
+            info.si_errno = 0;
+            info.si_code = n;
+            info._sifields._sigfault._addr = addr;
+            queue_signal(env, info.si_signo, &info);
             break;
+
         default:
-            printf ("Unhandled trap: 0x%x\n", trapnr);
+            fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
             cpu_dump_state(env, stderr, fprintf, 0);
-            exit (1);
+            exit(1);
         }
         process_pending_signals (env);
     }
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index c2ea151..e4603b7 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -16,7 +16,7 @@ struct target_pt_regs {
     target_psw_t psw;
     abi_ulong gprs[TARGET_NUM_GPRS];
     abi_ulong orig_gpr2;
-    unsigned short ilc;
+    unsigned short ilen;
     unsigned short trap;
 };
 
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 529716d..83e618a 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -79,10 +79,10 @@ typedef struct CPUS390XState {
     uint64_t psa;
 
     uint32_t int_pgm_code;
-    uint32_t int_pgm_ilc;
+    uint32_t int_pgm_ilen;
 
     uint32_t int_svc_code;
-    uint32_t int_svc_ilc;
+    uint32_t int_svc_ilen;
 
     uint64_t cregs[16]; /* control registers */
 
@@ -253,25 +253,31 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
              ((env->psw.mask & PSW_MASK_32) ? FLAG_MASK_32 : 0);
 }
 
-static inline int get_ilc(uint8_t opc)
+/* While the PoO talks about ILC (a number between 1-3) what is actually
+   stored in LowCore is shifted left one bit (an even between 2-6).  As
+   this is the actual length of the insn and therefore more useful, that
+   is what we want to pass around and manipulate.  To make sure that we
+   have applied this distinction universally, rename the "ILC" to "ILEN".  */
+static inline int get_ilen(uint8_t opc)
 {
     switch (opc >> 6) {
     case 0:
-        return 1;
+        return 2;
     case 1:
     case 2:
-        return 2;
-    case 3:
-        return 3;
+        return 4;
+    default:
+        return 6;
     }
-
-    return 0;
 }
 
-#define ILC_LATER       0x20
-#define ILC_LATER_INC   0x21
-#define ILC_LATER_INC_2 0x22
-
+#ifndef CONFIG_USER_ONLY
+/* In several cases of runtime exceptions, we havn't recorded the true
+   instruction length.  Use these codes when raising exceptions in order
+   to re-compute the length by examining the insn in memory.  */
+#define ILEN_LATER       0x20
+#define ILEN_LATER_INC   0x21
+#endif
 
 S390CPU *cpu_s390x_init(const char *cpu_model);
 void s390x_translate_init(void);
@@ -352,21 +358,10 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
 
 #include "exec/exec-all.h"
 
-#ifdef CONFIG_USER_ONLY
-
-#define EXCP_OPEX 1 /* operation exception (sigill) */
-#define EXCP_SVC 2 /* supervisor call (syscall) */
-#define EXCP_ADDR 5 /* addressing exception */
-#define EXCP_SPEC 6 /* specification exception */
-
-#else
-
 #define EXCP_EXT 1 /* external interrupt */
 #define EXCP_SVC 2 /* supervisor call (syscall) */
 #define EXCP_PGM 3 /* program interruption */
 
-#endif /* CONFIG_USER_ONLY */
-
 #define INTERRUPT_EXT        (1 << 0)
 #define INTERRUPT_TOD        (1 << 1)
 #define INTERRUPT_CPUTIMER   (1 << 2)
@@ -532,9 +527,9 @@ typedef struct LowCore
     uint32_t        ext_params;               /* 0x080 */
     uint16_t        cpu_addr;                 /* 0x084 */
     uint16_t        ext_int_code;             /* 0x086 */
-    uint16_t        svc_ilc;                  /* 0x088 */
+    uint16_t        svc_ilen;                 /* 0x088 */
     uint16_t        svc_code;                 /* 0x08a */
-    uint16_t        pgm_ilc;                  /* 0x08c */
+    uint16_t        pgm_ilen;                 /* 0x08c */
     uint16_t        pgm_code;                 /* 0x08e */
     uint32_t        data_exc_code;            /* 0x090 */
     uint16_t        mon_class_num;            /* 0x094 */
@@ -924,6 +919,6 @@ uint32_t set_cc_nz_f32(float32 v);
 uint32_t set_cc_nz_f64(float64 v);
 
 /* misc_helper.c */
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc);
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
 
 #endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 7dc4d46..9a132e6 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -99,10 +99,10 @@ void do_interrupt(CPUS390XState *env)
 int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
                                int rw, int mmu_idx)
 {
-    /* fprintf(stderr, "%s: address 0x%lx rw %d mmu_idx %d\n",
-       __func__, address, rw, mmu_idx); */
-    env->exception_index = EXCP_ADDR;
-    /* FIXME: find out how this works on a real machine */
+    env->exception_index = EXCP_PGM;
+    env->int_pgm_code = PGM_ADDRESSING;
+    /* On real machines this value is dropped into LowMem.  Since this
+       is userland, simply put this someplace that cpu_loop can find it.  */
     env->__excp_addr = address;
     return 1;
 }
@@ -111,11 +111,11 @@ int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong address,
 
 /* Ensure to exit the TB after this call! */
 static void trigger_pgm_exception(CPUS390XState *env, uint32_t code,
-                                  uint32_t ilc)
+                                  uint32_t ilen)
 {
     env->exception_index = EXCP_PGM;
     env->int_pgm_code = code;
-    env->int_pgm_ilc = ilc;
+    env->int_pgm_ilen = ilen;
 }
 
 static int trans_bits(CPUS390XState *env, uint64_t mode)
@@ -143,30 +143,30 @@ static int trans_bits(CPUS390XState *env, uint64_t mode)
 static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr,
                                uint64_t mode)
 {
-    int ilc = ILC_LATER_INC_2;
+    int ilen = ILEN_LATER_INC;
     int bits = trans_bits(env, mode) | 4;
 
     DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
     stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
-    trigger_pgm_exception(env, PGM_PROTECTION, ilc);
+    trigger_pgm_exception(env, PGM_PROTECTION, ilen);
 }
 
 static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr,
                                uint32_t type, uint64_t asc, int rw)
 {
-    int ilc = ILC_LATER;
+    int ilen = ILEN_LATER;
     int bits = trans_bits(env, asc);
 
+    /* Code accesses have an undefined ilc.  */
     if (rw == 2) {
-        /* code has is undefined ilc */
-        ilc = 2;
+        ilen = 2;
     }
 
     DPRINTF("%s: vaddr=%016" PRIx64 " bits=%d\n", __func__, vaddr, bits);
 
     stq_phys(env->psa + offsetof(LowCore, trans_exc_code), vaddr | bits);
-    trigger_pgm_exception(env, type, ilc);
+    trigger_pgm_exception(env, type, ilen);
 }
 
 static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
@@ -406,7 +406,7 @@ int cpu_s390x_handle_mmu_fault(CPUS390XState *env, target_ulong orig_vaddr,
     if (raddr > (ram_size + virtio_size)) {
         DPRINTF("%s: aaddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__,
                 (uint64_t)aaddr, (uint64_t)ram_size);
-        trigger_pgm_exception(env, PGM_ADDRESSING, ILC_LATER);
+        trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER);
         return 1;
     }
 
@@ -480,9 +480,9 @@ static void do_svc_interrupt(CPUS390XState *env)
     lowcore = cpu_physical_memory_map(env->psa, &len, 1);
 
     lowcore->svc_code = cpu_to_be16(env->int_svc_code);
-    lowcore->svc_ilc = cpu_to_be16(env->int_svc_ilc);
+    lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
     lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
-    lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + (env->int_svc_ilc));
+    lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
     mask = be64_to_cpu(lowcore->svc_new_psw.mask);
     addr = be64_to_cpu(lowcore->svc_new_psw.addr);
 
@@ -496,28 +496,26 @@ static void do_program_interrupt(CPUS390XState *env)
     uint64_t mask, addr;
     LowCore *lowcore;
     hwaddr len = TARGET_PAGE_SIZE;
-    int ilc = env->int_pgm_ilc;
+    int ilen = env->int_pgm_ilen;
 
-    switch (ilc) {
-    case ILC_LATER:
-        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
-        break;
-    case ILC_LATER_INC:
-        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr));
-        env->psw.addr += ilc * 2;
+    switch (ilen) {
+    case ILEN_LATER:
+        ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
         break;
-    case ILC_LATER_INC_2:
-        ilc = get_ilc(cpu_ldub_code(env, env->psw.addr)) * 2;
-        env->psw.addr += ilc;
+    case ILEN_LATER_INC:
+        ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
+        env->psw.addr += ilen;
         break;
+    default:
+        assert(ilen == 2 || ilen == 4 || ilen == 6);
     }
 
-    qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilc=%d\n",
-                  __func__, env->int_pgm_code, ilc);
+    qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n",
+                  __func__, env->int_pgm_code, ilen);
 
     lowcore = cpu_physical_memory_map(env->psa, &len, 1);
 
-    lowcore->pgm_ilc = cpu_to_be16(ilc);
+    lowcore->pgm_ilen = cpu_to_be16(ilen);
     lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
     lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
     lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
@@ -527,7 +525,7 @@ static void do_program_interrupt(CPUS390XState *env)
     cpu_physical_memory_unmap(lowcore, len, 1, len);
 
     DPRINTF("%s: %x %x %" PRIx64 " %" PRIx64 "\n", __func__,
-            env->int_pgm_code, ilc, env->psw.mask,
+            env->int_pgm_code, ilen, env->psw.mask,
             env->psw.addr);
 
     load_psw(env, mask, addr);
diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c
index bed21e6..7eb3790 100644
--- a/target-s390x/mem_helper.c
+++ b/target-s390x/mem_helper.c
@@ -594,7 +594,7 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
         HELPER_LOG("%s: svc %ld via execute\n", __func__, (insn | v1) & 0xff);
         env->psw.addr = ret - 4;
         env->int_svc_code = (insn | v1) & 0xff;
-        env->int_svc_ilc = 4;
+        env->int_svc_ilen = 4;
         helper_exception(env, EXCP_SVC);
     } else if ((insn & 0xff00) == 0xbf00) {
         uint32_t insn2, r1, r3, b2, d2;
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 70f9739..2aa1ed0 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -41,7 +41,7 @@
 #define HELPER_LOG(x...)
 #endif
 
-/* raise an exception */
+/* Raise an exception statically from a TB.  */
 void HELPER(exception)(CPUS390XState *env, uint32_t excp)
 {
     HELPER_LOG("%s: exception %d\n", __func__, excp);
@@ -50,7 +50,7 @@ void HELPER(exception)(CPUS390XState *env, uint32_t excp)
 }
 
 #ifndef CONFIG_USER_ONLY
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
 {
     qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
                   env->psw.addr);
@@ -61,7 +61,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
 #endif
     } else {
         env->int_pgm_code = code;
-        env->int_pgm_ilc = ilc;
+        env->int_pgm_ilen = ilen;
         env->exception_index = EXCP_PGM;
         cpu_loop_exit(env);
     }
@@ -105,7 +105,7 @@ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
     }
 
     if (r) {
-        program_interrupt(env, PGM_OPERATION, ILC_LATER_INC);
+        program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
     }
 
     return r;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6761889..076bb7f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -18,7 +18,6 @@
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* #define DEBUG_ILLEGAL_INSTRUCTIONS */
 /* #define DEBUG_INLINE_BRANCHES */
 #define S390X_DEBUG_DISAS
 /* #define S390X_DEBUG_DISAS_VERBOSE */
@@ -338,105 +337,52 @@ static inline int get_mem_index(DisasContext *s)
     }
 }
 
-static inline void gen_debug(DisasContext *s)
+static void gen_exception(int excp)
 {
-    TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
-    update_psw_addr(s);
-    gen_op_calc_cc(s);
-    gen_helper_exception(cpu_env, tmp);
-    tcg_temp_free_i32(tmp);
-    s->is_jmp = DISAS_EXCP;
-}
-
-#ifdef CONFIG_USER_ONLY
-
-static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc)
-{
-    TCGv_i32 tmp = tcg_const_i32(EXCP_SPEC);
-    update_psw_addr(s);
-    gen_op_calc_cc(s);
+    TCGv_i32 tmp = tcg_const_i32(excp);
     gen_helper_exception(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
-    s->is_jmp = DISAS_EXCP;
 }
 
-#else /* CONFIG_USER_ONLY */
-
-static void debug_print_inst(CPUS390XState *env, DisasContext *s, int ilc)
-{
-#ifdef DEBUG_ILLEGAL_INSTRUCTIONS
-    uint64_t inst = 0;
-
-    switch (ilc & 3) {
-    case 1:
-        inst = ld_code2(env, s->pc);
-        break;
-    case 2:
-        inst = ld_code4(env, s->pc);
-        break;
-    case 3:
-        inst = ld_code6(env, s->pc);
-        break;
-    }
-
-    fprintf(stderr, "Illegal instruction [%d at %016" PRIx64 "]: 0x%016"
-            PRIx64 "\n", ilc, s->pc, inst);
-#endif
-}
-
-static void gen_program_exception(CPUS390XState *env, DisasContext *s, int ilc,
-                                  int code)
+static void gen_program_exception(DisasContext *s, int code)
 {
     TCGv_i32 tmp;
 
-    debug_print_inst(env, s, ilc);
-
-    /* remember what pgm exeption this was */
+    /* Remember what pgm exeption this was.  */
     tmp = tcg_const_i32(code);
     tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
     tcg_temp_free_i32(tmp);
 
-    tmp = tcg_const_i32(ilc);
-    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilc));
+    tmp = tcg_const_i32(s->next_pc - s->pc);
+    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
     tcg_temp_free_i32(tmp);
 
-    /* advance past instruction */
-    s->pc += (ilc * 2);
+    /* Advance past instruction.  */
+    s->pc = s->next_pc;
     update_psw_addr(s);
 
-    /* save off cc */
+    /* Save off cc.  */
     gen_op_calc_cc(s);
 
-    /* trigger exception */
-    tmp = tcg_const_i32(EXCP_PGM);
-    gen_helper_exception(cpu_env, tmp);
-    tcg_temp_free_i32(tmp);
+    /* Trigger exception.  */
+    gen_exception(EXCP_PGM);
 
-    /* end TB here */
+    /* End TB here.  */
     s->is_jmp = DISAS_EXCP;
 }
 
-
-static void gen_illegal_opcode(CPUS390XState *env, DisasContext *s, int ilc)
+static inline void gen_illegal_opcode(DisasContext *s)
 {
-    gen_program_exception(env, s, ilc, PGM_SPECIFICATION);
+    gen_program_exception(s, PGM_SPECIFICATION);
 }
 
-static void gen_privileged_exception(CPUS390XState *env, DisasContext *s,
-                                     int ilc)
-{
-    gen_program_exception(env, s, ilc, PGM_PRIVILEGED);
-}
-
-static void check_privileged(CPUS390XState *env, DisasContext *s, int ilc)
+static inline void check_privileged(DisasContext *s)
 {
     if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
-        gen_privileged_exception(env, s, ilc);
+        gen_program_exception(s, PGM_PRIVILEGED);
     }
 }
 
-#endif /* CONFIG_USER_ONLY */
-
 static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
 {
     TCGv_i64 tmp;
@@ -1769,7 +1715,7 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal e3 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 3);
+        gen_illegal_opcode(s);
         break;
     }
     tcg_temp_free_i64(addr);
@@ -1794,7 +1740,7 @@ static void disas_e5(CPUS390XState *env, DisasContext* s, uint64_t insn)
         break;
     default:
         LOG_DISAS("illegal e5 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 3);
+        gen_illegal_opcode(s);
         break;
     }
 
@@ -1809,7 +1755,6 @@ static void disas_eb(CPUS390XState *env, DisasContext *s, int op, int r1,
     TCGv_i64 tmp, tmp2, tmp3, tmp4;
     TCGv_i32 tmp32_1, tmp32_2;
     int i, stm_len;
-    int ilc = 3;
 
     LOG_DISAS("disas_eb: op 0x%x r1 %d r3 %d b2 %d d2 0x%x\n",
               op, r1, r3, b2, d2);
@@ -1947,7 +1892,7 @@ do_mh:
 #ifndef CONFIG_USER_ONLY
     case 0x2f: /* LCTLG     R1,R3,D2(B2)     [RSE] */
         /* Load Control */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         tmp = get_address(s, 0, b2, d2);
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
@@ -1959,7 +1904,7 @@ do_mh:
         break;
     case 0x25: /* STCTG     R1,R3,D2(B2)     [RSE] */
         /* Store Control */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         tmp = get_address(s, 0, b2, d2);
         tmp32_1 = tcg_const_i32(r1);
         tmp32_2 = tcg_const_i32(r3);
@@ -2036,7 +1981,7 @@ do_mh:
         break;
     default:
         LOG_DISAS("illegal eb operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, ilc);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -2156,7 +2101,7 @@ static void disas_ed(CPUS390XState *env, DisasContext *s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal ed operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 3);
+        gen_illegal_opcode(s);
         return;
     }
     tcg_temp_free_i32(tmp_r1);
@@ -2313,7 +2258,7 @@ static void disas_a5(CPUS390XState *env, DisasContext *s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal a5 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 2);
+        gen_illegal_opcode(s);
         return;
     }
 }
@@ -2451,7 +2396,7 @@ static void disas_a7(CPUS390XState *env, DisasContext *s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal a7 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 2);
+        gen_illegal_opcode(s);
         return;
     }
 }
@@ -2462,7 +2407,6 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     TCGv_i64 tmp, tmp2, tmp3;
     TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
     int r1, r2;
-    int ilc = 2;
 #ifndef CONFIG_USER_ONLY
     int r3, d2, b2;
 #endif
@@ -2556,7 +2500,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
 #ifndef CONFIG_USER_ONLY
     case 0x02: /* STIDP     D2(B2)     [S] */
         /* Store CPU ID */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2565,7 +2509,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x04: /* SCK       D2(B2)     [S] */
         /* Set Clock */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2584,7 +2528,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x06: /* SCKC     D2(B2)     [S] */
         /* Set Clock Comparator */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2593,7 +2537,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x07: /* STCKC    D2(B2)     [S] */
         /* Store Clock Comparator */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2602,7 +2546,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x08: /* SPT      D2(B2)     [S] */
         /* Set CPU Timer */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2611,7 +2555,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x09: /* STPT     D2(B2)     [S] */
         /* Store CPU Timer */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2620,7 +2564,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x0a: /* SPKA     D2(B2)     [S] */
         /* Set PSW Key from Address */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
@@ -2632,12 +2576,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x0d: /* PTLB                [S] */
         /* Purge TLB */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         gen_helper_ptlb(cpu_env);
         break;
     case 0x10: /* SPX      D2(B2)     [S] */
         /* Set Prefix Register */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
@@ -2646,7 +2590,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x11: /* STPX     D2(B2)     [S] */
         /* Store Prefix */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
@@ -2657,7 +2601,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x12: /* STAP     D2(B2)     [S] */
         /* Store CPU Address */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
@@ -2671,7 +2615,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x21: /* IPTE     R1,R2      [RRE] */
         /* Invalidate PTE */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp = load_reg(r1);
@@ -2682,7 +2626,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x29: /* ISKE     R1,R2      [RRE] */
         /* Insert Storage Key Extended */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp = load_reg(r2);
@@ -2694,7 +2638,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x2a: /* RRBE     R1,R2      [RRE] */
         /* Set Storage Key Extended */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp32_1 = load_reg32(r1);
@@ -2706,7 +2650,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x2b: /* SSKE     R1,R2      [RRE] */
         /* Set Storage Key Extended */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp32_1 = load_reg32(r1);
@@ -2717,12 +2661,12 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x34: /* STCH ? */
         /* Store Subchannel */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         gen_op_movi_cc(s, 3);
         break;
     case 0x46: /* STURA    R1,R2      [RRE] */
         /* Store Using Real Address */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp32_1 = load_reg32(r1);
@@ -2734,7 +2678,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x50: /* CSP      R1,R2      [RRE] */
         /* Compare And Swap And Purge */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         r1 = (insn >> 4) & 0xf;
         r2 = insn & 0xf;
         tmp32_1 = tcg_const_i32(r1);
@@ -2746,7 +2690,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x5f: /* CHSC ? */
         /* Channel Subsystem Call */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         gen_op_movi_cc(s, 3);
         break;
     case 0x78: /* STCKE    D2(B2)     [S] */
@@ -2760,19 +2704,19 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x79: /* SACF    D2(B2)     [S] */
         /* Set Address Space Control Fast */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         potential_page_fault(s);
         gen_helper_sacf(cpu_env, tmp);
         tcg_temp_free_i64(tmp);
         /* addressing mode has changed, so end the block */
-        s->pc += ilc * 2;
+        s->pc = s->next_pc;
         update_psw_addr(s);
         s->is_jmp = DISAS_JUMP;
         break;
     case 0x7d: /* STSI     D2,(B2)     [S] */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp32_1 = load_reg32(0);
@@ -2798,7 +2742,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0xb1: /* STFL     D2(B2)     [S] */
         /* Store Facility List (CPU features) at 200 */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         tmp2 = tcg_const_i64(0xc0000000);
         tmp = tcg_const_i64(200);
         tcg_gen_qemu_st32(tmp2, tmp, get_mem_index(s));
@@ -2807,7 +2751,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0xb2: /* LPSWE    D2(B2)     [S] */
         /* Load PSW Extended */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
         tmp2 = tcg_temp_new_i64();
@@ -2824,7 +2768,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         break;
     case 0x20: /* SERVC     R1,R2     [RRE] */
         /* SCLP Service call (PV hypercall) */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         potential_page_fault(s);
         tmp32_1 = load_reg32(r2);
         tmp = load_reg(r1);
@@ -2836,7 +2780,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
 #endif
     default:
         LOG_DISAS("illegal b2 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, ilc);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -3112,7 +3056,7 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
         break;
     default:
         LOG_DISAS("illegal b3 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 2);
+        gen_illegal_opcode(s);
         break;
     }
 
@@ -3419,7 +3363,7 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal b9 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 2);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -3525,7 +3469,7 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         break;
     default:
         LOG_DISAS("illegal c0 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 3);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -3559,7 +3503,7 @@ static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
         break;
     default:
         LOG_DISAS("illegal c2 operation 0x%x\n", op);
-        gen_illegal_opcode(env, s, 3);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -3589,14 +3533,11 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
     uint64_t insn;
     int op, r1, r2, r3, d1, d2, x2, b1, b2, i, i2, r1b;
     TCGv_i32 vl;
-    int ilc;
     int l1;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
 
-    ilc = get_ilc(opc);
-
     switch (opc) {
 #ifndef CONFIG_USER_ONLY
     case 0x01: /* SAM */
@@ -3649,15 +3590,13 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         update_psw_addr(s);
         gen_op_calc_cc(s);
         tmp32_1 = tcg_const_i32(i);
-        tmp32_2 = tcg_const_i32(ilc * 2);
-        tmp32_3 = tcg_const_i32(EXCP_SVC);
+        tmp32_2 = tcg_const_i32(s->next_pc - s->pc);
         tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, int_svc_code));
-        tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilc));
-        gen_helper_exception(cpu_env, tmp32_3);
+        tcg_gen_st_i32(tmp32_2, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
+        gen_exception(EXCP_SVC);
         s->is_jmp = DISAS_EXCP;
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
         break;
     case 0xd: /* BASR   R1,R2     [RR] */
         insn = ld_code2(env, s->pc);
@@ -4148,7 +4087,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 #ifndef CONFIG_USER_ONLY
     case 0x80: /* SSM      D2(B2)       [S] */
         /* Set System Mask */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -4164,7 +4103,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         break;
     case 0x82: /* LPSW     D2(B2)       [S] */
         /* Load PSW */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -4184,7 +4123,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         break;
     case 0x83: /* DIAG     R1,R3,D2     [RS] */
         /* Diagnose call (KVM hypercall) */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         potential_page_fault(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
@@ -4402,7 +4341,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 #ifndef CONFIG_USER_ONLY
     case 0xac: /* STNSM   D1(B1),I2     [SI] */
     case 0xad: /* STOSM   D1(B1),I2     [SI] */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         tmp = decode_si(s, insn, &i2, &b1, &d1);
         tmp2 = tcg_temp_new_i64();
@@ -4418,7 +4357,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i64(tmp2);
         break;
     case 0xae: /* SIGP   R1,R3,D2(B2)     [RS] */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -4432,7 +4371,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         break;
     case 0xb1: /* LRA    R1,D2(X2, B2)     [RX] */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
         tmp32_1 = tcg_const_i32(r1);
@@ -4476,7 +4415,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 #ifndef CONFIG_USER_ONLY
     case 0xb6: /* STCTL     R1,R3,D2(B2)     [RS] */
         /* Store Control */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -4490,7 +4429,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         break;
     case 0xb7: /* LCTL      R1,R3,D2(B2)     [RS] */
         /* Load Control */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code4(env, s->pc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -4674,7 +4613,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 #ifndef CONFIG_USER_ONLY
     case 0xda: /* MVCP     D1(R1,B1),D2(B2),R3   [SS] */
     case 0xdb: /* MVCS     D1(R1,B1),D2(B2),R3   [SS] */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         potential_page_fault(s);
         insn = ld_code6(env, s->pc);
         r1 = (insn >> 36) & 0xf;
@@ -4712,7 +4651,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
 #ifndef CONFIG_USER_ONLY
     case 0xe5:
         /* Test Protection */
-        check_privileged(env, s, ilc);
+        check_privileged(s);
         insn = ld_code6(env, s->pc);
         debug_insn(insn);
         disas_e5(env, s, insn);
@@ -4742,7 +4681,7 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
-        gen_illegal_opcode(env, s, ilc);
+        gen_illegal_opcode(s);
         break;
     }
 }
@@ -5273,19 +5212,22 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
                                      DisasFields *f)
 {
     uint64_t insn, pc = s->pc;
-    int op, op2;
+    int op, op2, ilen;
     const DisasInsn *info;
 
     insn = ld_code2(env, pc);
     op = (insn >> 8) & 0xff;
-    switch (get_ilc(op)) {
-    case 1:
+    ilen = get_ilen(op);
+    s->next_pc = s->pc + ilen;
+
+    switch (ilen) {
+    case 2:
         insn = insn << 48;
         break;
-    case 2:
+    case 4:
         insn = ld_code4(env, pc) << 32;
         break;
-    case 3:
+    case 6:
         insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
         break;
     default:
@@ -5361,9 +5303,6 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
 
     insn = extract_insn(env, s, &f);
 
-    /* Instruction length is encoded in the opcode */
-    s->next_pc = s->pc + get_ilc(f.op) * 2;
-
     /* If not found, try the old interpreter.  This includes ILLOPC.  */
     if (insn == NULL) {
         disas_s390_insn(env, s);
@@ -5452,6 +5391,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     int num_insns, max_insns;
     CPUBreakpoint *bp;
     ExitStatus status;
+    bool do_debug;
 
     pc_start = tb->pc;
 
@@ -5463,7 +5403,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     dc.tb = tb;
     dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
-    dc.singlestep_enabled = env->singlestep_enabled;
+    do_debug = dc.singlestep_enabled = env->singlestep_enabled;
     dc.is_jmp = DISAS_NEXT;
 
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
@@ -5479,14 +5419,6 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     gen_icount_start();
 
     do {
-        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
-            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
-                if (bp->pc == dc.pc) {
-                    gen_debug(&dc);
-                    break;
-                }
-            }
-        }
         if (search_pc) {
             j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
             if (lj < j) {
@@ -5508,7 +5440,19 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             tcg_gen_debug_insn_start(dc.pc);
         }
 
-        status = translate_one(env, &dc);
+        status = NO_EXIT;
+        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
+            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+                if (bp->pc == dc.pc) {
+                    status = EXIT_PC_STALE;
+                    do_debug = true;
+                    break;
+                }
+            }
+        }
+        if (status == NO_EXIT) {
+            status = translate_one(env, &dc);
+        }
 
         /* If we reach a page boundary, are single stepping,
            or exhaust instruction count, stop generation.  */
@@ -5541,8 +5485,8 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
                so make sure the cc op type is in env */
             gen_op_set_cc_op(&dc);
         }
-        if (env->singlestep_enabled) {
-            gen_debug(&dc);
+        if (do_debug) {
+            gen_exception(EXCP_DEBUG);
         } else {
             /* Generate the return instruction */
             tcg_gen_exit_tb(0);
commit 3fde06f5fb67dd9e5373b8105318e74e18eec895
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 13:31:01 2012 -0700

    target-s390: Split out disas_jcc
    
    Lots of duplicated code replaced with a couple of tables.  We no longer
    attempt to manually invert the logic operation: the comments now match
    the code.  In the fully general test, constant propagate (1 << (3 - cc))
    into (8 >> cc).
    
    The new function will be usable by non-branch insns as well.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 92d49e1..6761889 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -58,6 +58,18 @@ struct DisasContext {
     int is_jmp;
 };
 
+/* Information carried about a condition to be evaluated.  */
+typedef struct {
+    TCGCond cond:8;
+    bool is_64;
+    bool g1;
+    bool g2;
+    union {
+        struct { TCGv_i64 a, b; } s64;
+        struct { TCGv_i32 a, b; } s32;
+    } u;
+} DisasCompare;
+
 #define DISAS_EXCP 4
 
 static void gen_op_calc_cc(DisasContext *s);
@@ -840,357 +852,281 @@ static inline void account_noninline_branch(DisasContext *s, int cc_op)
 #endif
 }
 
-static inline void account_inline_branch(DisasContext *s)
+static inline void account_inline_branch(DisasContext *s, int cc_op)
 {
 #ifdef DEBUG_INLINE_BRANCHES
-    inline_branch_hit[s->cc_op]++;
+    inline_branch_hit[cc_op]++;
 #endif
 }
 
-static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
+/* Table of mask values to comparison codes, given a comparison as input.
+   For a true comparison CC=3 will never be set, but we treat this
+   conservatively for possible use when CC=3 indicates overflow.  */
+static const TCGCond ltgt_cond[16] = {
+    TCG_COND_NEVER,  TCG_COND_NEVER,     /*    |    |    | x */
+    TCG_COND_GT,     TCG_COND_NEVER,     /*    |    | GT | x */
+    TCG_COND_LT,     TCG_COND_NEVER,     /*    | LT |    | x */
+    TCG_COND_NE,     TCG_COND_NEVER,     /*    | LT | GT | x */
+    TCG_COND_EQ,     TCG_COND_NEVER,     /* EQ |    |    | x */
+    TCG_COND_GE,     TCG_COND_NEVER,     /* EQ |    | GT | x */
+    TCG_COND_LE,     TCG_COND_NEVER,     /* EQ | LT |    | x */
+    TCG_COND_ALWAYS, TCG_COND_ALWAYS,    /* EQ | LT | GT | x */
+};
+
+/* Table of mask values to comparison codes, given a logic op as input.
+   For such, only CC=0 and CC=1 should be possible.  */
+static const TCGCond nz_cond[16] = {
+    /*    |    | x | x */
+    TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER, TCG_COND_NEVER,
+    /*    | NE | x | x */
+    TCG_COND_NE, TCG_COND_NE, TCG_COND_NE, TCG_COND_NE,
+    /* EQ |    | x | x */
+    TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ, TCG_COND_EQ,
+    /* EQ | NE | x | x */
+    TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS, TCG_COND_ALWAYS,
+};
+
+/* Interpret MASK in terms of S->CC_OP, and fill in C with all the
+   details required to generate a TCG comparison.  */
+static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
 {
-    TCGv_i32 tmp, tmp2, r;
-    TCGv_i64 tmp64;
-    int old_cc_op;
+    TCGCond cond;
+    enum cc_op old_cc_op = s->cc_op;
 
-    switch (s->cc_op) {
+    if (mask == 15 || mask == 0) {
+        c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
+        c->u.s32.a = cc_op;
+        c->u.s32.b = cc_op;
+        c->g1 = c->g2 = true;
+        c->is_64 = false;
+        return;
+    }
+
+    /* Find the TCG condition for the mask + cc op.  */
+    switch (old_cc_op) {
     case CC_OP_LTGT0_32:
-        tmp = tcg_temp_new_i32();
-        tcg_gen_trunc_i64_i32(tmp, cc_dst);
-        switch (mask) {
-        case 0x8 | 0x4: /* dst <= 0 */
-            tcg_gen_brcondi_i32(TCG_COND_GT, tmp, 0, skip);
-            break;
-        case 0x8 | 0x2: /* dst >= 0 */
-            tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, skip);
-            break;
-        case 0x8: /* dst == 0 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
-            break;
-        case 0x7: /* dst != 0 */
-        case 0x6: /* dst != 0 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
-            break;
-        case 0x4: /* dst < 0 */
-            tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, skip);
-            break;
-        case 0x2: /* dst > 0 */
-            tcg_gen_brcondi_i32(TCG_COND_LE, tmp, 0, skip);
-            break;
-        default:
-            tcg_temp_free_i32(tmp);
-            goto do_dynamic;
-        }
-        account_inline_branch(s);
-        tcg_temp_free_i32(tmp);
-        break;
     case CC_OP_LTGT0_64:
-        switch (mask) {
-        case 0x8 | 0x4: /* dst <= 0 */
-            tcg_gen_brcondi_i64(TCG_COND_GT, cc_dst, 0, skip);
-            break;
-        case 0x8 | 0x2: /* dst >= 0 */
-            tcg_gen_brcondi_i64(TCG_COND_LT, cc_dst, 0, skip);
-            break;
-        case 0x8: /* dst == 0 */
-            tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
-            break;
-        case 0x7: /* dst != 0 */
-        case 0x6: /* dst != 0 */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
-            break;
-        case 0x4: /* dst < 0 */
-            tcg_gen_brcondi_i64(TCG_COND_GE, cc_dst, 0, skip);
-            break;
-        case 0x2: /* dst > 0 */
-            tcg_gen_brcondi_i64(TCG_COND_LE, cc_dst, 0, skip);
-            break;
-        default:
-            goto do_dynamic;
-        }
-        account_inline_branch(s);
-        break;
     case CC_OP_LTGT_32:
-        tmp = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i32();
-        tcg_gen_trunc_i64_i32(tmp, cc_src);
-        tcg_gen_trunc_i64_i32(tmp2, cc_dst);
-        switch (mask) {
-        case 0x8 | 0x4: /* src <= dst */
-            tcg_gen_brcond_i32(TCG_COND_GT, tmp, tmp2, skip);
-            break;
-        case 0x8 | 0x2: /* src >= dst */
-            tcg_gen_brcond_i32(TCG_COND_LT, tmp, tmp2, skip);
-            break;
-        case 0x8: /* src == dst */
-            tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
-            break;
-        case 0x7: /* src != dst */
-        case 0x6: /* src != dst */
-            tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
-            break;
-        case 0x4: /* src < dst */
-            tcg_gen_brcond_i32(TCG_COND_GE, tmp, tmp2, skip);
-            break;
-        case 0x2: /* src > dst */
-            tcg_gen_brcond_i32(TCG_COND_LE, tmp, tmp2, skip);
-            break;
-        default:
-            tcg_temp_free_i32(tmp);
-            tcg_temp_free_i32(tmp2);
-            goto do_dynamic;
-        }
-        account_inline_branch(s);
-        tcg_temp_free_i32(tmp);
-        tcg_temp_free_i32(tmp2);
-        break;
     case CC_OP_LTGT_64:
-        switch (mask) {
-        case 0x8 | 0x4: /* src <= dst */
-            tcg_gen_brcond_i64(TCG_COND_GT, cc_src, cc_dst, skip);
-            break;
-        case 0x8 | 0x2: /* src >= dst */
-            tcg_gen_brcond_i64(TCG_COND_LT, cc_src, cc_dst, skip);
-            break;
-        case 0x8: /* src == dst */
-            tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
-            break;
-        case 0x7: /* src != dst */
-        case 0x6: /* src != dst */
-            tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
-            break;
-        case 0x4: /* src < dst */
-            tcg_gen_brcond_i64(TCG_COND_GE, cc_src, cc_dst, skip);
-            break;
-        case 0x2: /* src > dst */
-            tcg_gen_brcond_i64(TCG_COND_LE, cc_src, cc_dst, skip);
-            break;
-        default:
+        cond = ltgt_cond[mask];
+        if (cond == TCG_COND_NEVER) {
             goto do_dynamic;
         }
-        account_inline_branch(s);
+        account_inline_branch(s, old_cc_op);
         break;
+
     case CC_OP_LTUGTU_32:
-        tmp = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i32();
-        tcg_gen_trunc_i64_i32(tmp, cc_src);
-        tcg_gen_trunc_i64_i32(tmp2, cc_dst);
-        switch (mask) {
-        case 0x8 | 0x4: /* src <= dst */
-            tcg_gen_brcond_i32(TCG_COND_GTU, tmp, tmp2, skip);
-            break;
-        case 0x8 | 0x2: /* src >= dst */
-            tcg_gen_brcond_i32(TCG_COND_LTU, tmp, tmp2, skip);
-            break;
-        case 0x8: /* src == dst */
-            tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, skip);
-            break;
-        case 0x7: /* src != dst */
-        case 0x6: /* src != dst */
-            tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, skip);
-            break;
-        case 0x4: /* src < dst */
-            tcg_gen_brcond_i32(TCG_COND_GEU, tmp, tmp2, skip);
-            break;
-        case 0x2: /* src > dst */
-            tcg_gen_brcond_i32(TCG_COND_LEU, tmp, tmp2, skip);
-            break;
-        default:
-            tcg_temp_free_i32(tmp);
-            tcg_temp_free_i32(tmp2);
-            goto do_dynamic;
-        }
-        account_inline_branch(s);
-        tcg_temp_free_i32(tmp);
-        tcg_temp_free_i32(tmp2);
-        break;
     case CC_OP_LTUGTU_64:
-        switch (mask) {
-        case 0x8 | 0x4: /* src <= dst */
-            tcg_gen_brcond_i64(TCG_COND_GTU, cc_src, cc_dst, skip);
-            break;
-        case 0x8 | 0x2: /* src >= dst */
-            tcg_gen_brcond_i64(TCG_COND_LTU, cc_src, cc_dst, skip);
-            break;
-        case 0x8: /* src == dst */
-            tcg_gen_brcond_i64(TCG_COND_NE, cc_src, cc_dst, skip);
-            break;
-        case 0x7: /* src != dst */
-        case 0x6: /* src != dst */
-            tcg_gen_brcond_i64(TCG_COND_EQ, cc_src, cc_dst, skip);
-            break;
-        case 0x4: /* src < dst */
-            tcg_gen_brcond_i64(TCG_COND_GEU, cc_src, cc_dst, skip);
-            break;
-        case 0x2: /* src > dst */
-            tcg_gen_brcond_i64(TCG_COND_LEU, cc_src, cc_dst, skip);
-            break;
-        default:
+        cond = tcg_unsigned_cond(ltgt_cond[mask]);
+        if (cond == TCG_COND_NEVER) {
             goto do_dynamic;
         }
-        account_inline_branch(s);
+        account_inline_branch(s, old_cc_op);
         break;
+
     case CC_OP_NZ:
-        switch (mask) {
-        /* dst == 0 || dst != 0 */
-        case 0x8 | 0x4:
-        case 0x8 | 0x4 | 0x2:
-        case 0x8 | 0x4 | 0x2 | 0x1:
-        case 0x8 | 0x4 | 0x1:
-            break;
-        /* dst == 0 */
-        case 0x8:
-        case 0x8 | 0x2:
-        case 0x8 | 0x2 | 0x1:
-        case 0x8 | 0x1:
-            tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
-            break;
-        /* dst != 0 */
-        case 0x4:
-        case 0x4 | 0x2:
-        case 0x4 | 0x2 | 0x1:
-        case 0x4 | 0x1:
-            tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
-            break;
-        default:
+        cond = nz_cond[mask];
+        if (cond == TCG_COND_NEVER) {
             goto do_dynamic;
         }
-        account_inline_branch(s);
+        account_inline_branch(s, old_cc_op);
         break;
-    case CC_OP_TM_32:
-        tmp = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i32();
 
-        tcg_gen_trunc_i64_i32(tmp, cc_src);
-        tcg_gen_trunc_i64_i32(tmp2, cc_dst);
-        tcg_gen_and_i32(tmp, tmp, tmp2);
-        switch (mask) {
-        case 0x8: /* val & mask == 0 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
-            break;
-        case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
-            break;
-        default:
-            tcg_temp_free_i32(tmp);
-            tcg_temp_free_i32(tmp2);
-            goto do_dynamic;
-        }
-        tcg_temp_free_i32(tmp);
-        tcg_temp_free_i32(tmp2);
-        account_inline_branch(s);
-        break;
+    case CC_OP_TM_32:
     case CC_OP_TM_64:
-        tmp64 = tcg_temp_new_i64();
-
-        tcg_gen_and_i64(tmp64, cc_src, cc_dst);
         switch (mask) {
-        case 0x8: /* val & mask == 0 */
-            tcg_gen_brcondi_i64(TCG_COND_NE, tmp64, 0, skip);
+        case 8:
+            cond = TCG_COND_EQ;
             break;
-        case 0x4 | 0x2 | 0x1: /* val & mask != 0 */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, tmp64, 0, skip);
+        case 4 | 2 | 1:
+            cond = TCG_COND_NE;
             break;
         default:
-            tcg_temp_free_i64(tmp64);
             goto do_dynamic;
         }
-        tcg_temp_free_i64(tmp64);
-        account_inline_branch(s);
+        account_inline_branch(s, old_cc_op);
         break;
+
     case CC_OP_ICM:
         switch (mask) {
-        case 0x8: /* val == 0 */
-            tcg_gen_brcondi_i64(TCG_COND_NE, cc_dst, 0, skip);
+        case 8:
+            cond = TCG_COND_EQ;
             break;
-        case 0x4 | 0x2 | 0x1: /* val != 0 */
-        case 0x4 | 0x2: /* val != 0 */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, cc_dst, 0, skip);
+        case 4 | 2 | 1:
+        case 4 | 2:
+            cond = TCG_COND_NE;
             break;
         default:
             goto do_dynamic;
         }
-        account_inline_branch(s);
+        account_inline_branch(s, old_cc_op);
         break;
-    case CC_OP_STATIC:
-        old_cc_op = s->cc_op;
-        goto do_dynamic_nocccalc;
-    case CC_OP_DYNAMIC:
+
     default:
-do_dynamic:
-        old_cc_op = s->cc_op;
-        /* calculate cc value */
+    do_dynamic:
+        /* Calculate cc value.  */
         gen_op_calc_cc(s);
+        /* FALLTHRU */
 
-do_dynamic_nocccalc:
-        /* jump based on cc */
+    case CC_OP_STATIC:
+        /* Jump based on CC.  We'll load up the real cond below;
+           the assignment here merely avoids a compiler warning.  */
         account_noninline_branch(s, old_cc_op);
+        old_cc_op = CC_OP_STATIC;
+        cond = TCG_COND_NEVER;
+        break;
+    }
+
+    /* Load up the arguments of the comparison.  */
+    c->is_64 = true;
+    c->g1 = c->g2 = false;
+    switch (old_cc_op) {
+    case CC_OP_LTGT0_32:
+        c->is_64 = false;
+        c->u.s32.a = tcg_temp_new_i32();
+        tcg_gen_trunc_i64_i32(c->u.s32.a, cc_dst);
+        c->u.s32.b = tcg_const_i32(0);
+        break;
+    case CC_OP_LTGT_32:
+    case CC_OP_LTUGTU_32:
+        c->is_64 = false;
+        c->u.s32.a = tcg_temp_new_i32();
+        tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
+        c->u.s32.b = tcg_temp_new_i32();
+        tcg_gen_trunc_i64_i32(c->u.s32.b, cc_dst);
+        break;
+
+    case CC_OP_LTGT0_64:
+    case CC_OP_NZ:
+    case CC_OP_ICM:
+        c->u.s64.a = cc_dst;
+        c->u.s64.b = tcg_const_i64(0);
+        c->g1 = true;
+        break;
+    case CC_OP_LTGT_64:
+    case CC_OP_LTUGTU_64:
+        c->u.s64.a = cc_src;
+        c->u.s64.b = cc_dst;
+        c->g1 = c->g2 = true;
+        break;
+
+    case CC_OP_TM_32:
+    case CC_OP_TM_64:
+        c->u.s64.a = tcg_temp_new_i64();
+        c->u.s64.b = tcg_const_i64(0);
+        tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
+        break;
 
+    case CC_OP_STATIC:
+        c->is_64 = false;
+        c->u.s32.a = cc_op;
+        c->g1 = true;
         switch (mask) {
-        case 0x8 | 0x4 | 0x2 | 0x1:
-            /* always true */
-            break;
         case 0x8 | 0x4 | 0x2: /* cc != 3 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 3, skip);
+            cond = TCG_COND_NE;
+            c->u.s32.b = tcg_const_i32(3);
             break;
         case 0x8 | 0x4 | 0x1: /* cc != 2 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 2, skip);
+            cond = TCG_COND_NE;
+            c->u.s32.b = tcg_const_i32(2);
             break;
         case 0x8 | 0x2 | 0x1: /* cc != 1 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 1, skip);
+            cond = TCG_COND_NE;
+            c->u.s32.b = tcg_const_i32(1);
             break;
-        case 0x8 | 0x2: /* cc == 0 || cc == 2 */
-            tmp = tcg_temp_new_i32();
-            tcg_gen_andi_i32(tmp, cc_op, 1);
-            tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, skip);
-            tcg_temp_free_i32(tmp);
+        case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
+            cond = TCG_COND_EQ;
+            c->g1 = false;
+            c->u.s32.a = tcg_temp_new_i32();
+            c->u.s32.b = tcg_const_i32(0);
+            tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
             break;
         case 0x8 | 0x4: /* cc < 2 */
-            tcg_gen_brcondi_i32(TCG_COND_GEU, cc_op, 2, skip);
+            cond = TCG_COND_LTU;
+            c->u.s32.b = tcg_const_i32(2);
             break;
         case 0x8: /* cc == 0 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 0, skip);
+            cond = TCG_COND_EQ;
+            c->u.s32.b = tcg_const_i32(0);
             break;
         case 0x4 | 0x2 | 0x1: /* cc != 0 */
-            tcg_gen_brcondi_i32(TCG_COND_EQ, cc_op, 0, skip);
+            cond = TCG_COND_NE;
+            c->u.s32.b = tcg_const_i32(0);
             break;
-        case 0x4 | 0x1: /* cc == 1 || cc == 3 */
-            tmp = tcg_temp_new_i32();
-            tcg_gen_andi_i32(tmp, cc_op, 1);
-            tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip);
-            tcg_temp_free_i32(tmp);
+        case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
+            cond = TCG_COND_NE;
+            c->g1 = false;
+            c->u.s32.a = tcg_temp_new_i32();
+            c->u.s32.b = tcg_const_i32(0);
+            tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
             break;
         case 0x4: /* cc == 1 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 1, skip);
+            cond = TCG_COND_EQ;
+            c->u.s32.b = tcg_const_i32(1);
             break;
         case 0x2 | 0x1: /* cc > 1 */
-            tcg_gen_brcondi_i32(TCG_COND_LEU, cc_op, 1, skip);
+            cond = TCG_COND_GTU;
+            c->u.s32.b = tcg_const_i32(1);
             break;
         case 0x2: /* cc == 2 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 2, skip);
+            cond = TCG_COND_EQ;
+            c->u.s32.b = tcg_const_i32(2);
             break;
         case 0x1: /* cc == 3 */
-            tcg_gen_brcondi_i32(TCG_COND_NE, cc_op, 3, skip);
+            cond = TCG_COND_EQ;
+            c->u.s32.b = tcg_const_i32(3);
             break;
-        default: /* cc is masked by something else */
-            tmp = tcg_const_i32(3);
-            /* 3 - cc */
-            tcg_gen_sub_i32(tmp, tmp, cc_op);
-            tmp2 = tcg_const_i32(1);
-            /* 1 << (3 - cc) */
-            tcg_gen_shl_i32(tmp2, tmp2, tmp);
-            r = tcg_const_i32(mask);
-            /* mask & (1 << (3 - cc)) */
-            tcg_gen_and_i32(r, r, tmp2);
-            tcg_temp_free_i32(tmp);
-            tcg_temp_free_i32(tmp2);
-
-            tcg_gen_brcondi_i32(TCG_COND_EQ, r, 0, skip);
-            tcg_temp_free_i32(r);
+        default:
+            /* CC is masked by something else: (8 >> cc) & mask.  */
+            cond = TCG_COND_NE;
+            c->g1 = false;
+            c->u.s32.a = tcg_const_i32(8);
+            c->u.s32.b = tcg_const_i32(0);
+            tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
+            tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
             break;
         }
         break;
+
+    default:
+        abort();
     }
+    c->cond = cond;
+}
+
+static void free_compare(DisasCompare *c)
+{
+    if (!c->g1) {
+        if (c->is_64) {
+            tcg_temp_free_i64(c->u.s64.a);
+        } else {
+            tcg_temp_free_i32(c->u.s32.a);
+        }
+    }
+    if (!c->g2) {
+        if (c->is_64) {
+            tcg_temp_free_i64(c->u.s64.b);
+        } else {
+            tcg_temp_free_i32(c->u.s32.b);
+        }
+    }
+}
+
+static void gen_jcc(DisasContext *s, uint32_t mask, int skip)
+{
+    DisasCompare c;
+    TCGCond cond;
+
+    disas_jcc(s, &c, mask);
+    cond = tcg_invert_cond(c.cond);
+
+    if (c.is_64) {
+        tcg_gen_brcond_i64(cond, c.u.s64.a, c.u.s64.b, skip);
+    } else {
+        tcg_gen_brcond_i32(cond, c.u.s32.a, c.u.s32.b, skip);
+    }
+
+    free_compare(&c);
 }
 
 static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
commit ad044d09de62c10c361003765d5039396c057abe
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Aug 15 17:16:22 2012 -0700

    target-s390: Add format based disassassmbly infrastructure
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
new file mode 100644
index 0000000..7d81928
--- /dev/null
+++ b/target-s390x/insn-data.def
@@ -0,0 +1,54 @@
+/* ADD */
+    C(0x1a00, AR,      RR_a,  Z,   r1, r2, new, r1_32, add, adds32)
+    C(0xb9f8, ARK,     RRF_a, DO,  r2, r3, new, r1_32, add, adds32)
+    C(0x5a00, A,       RX_a,  Z,   r1, m2_32s, new, r1_32, add, adds32)
+    C(0xe35a, AY,      RXY_a, LD,  r1, m2_32s, new, r1_32, add, adds32)
+    C(0xb908, AGR,     RRE,   Z,   r1, r2, r1, 0, add, adds64)
+    C(0xb918, AGFR,    RRE,   Z,   r1, r2_32s, r1, 0, add, adds64)
+    C(0xb9e8, AGRK,    RRF_a, DO,  r2, r3, r1, 0, add, adds64)
+    C(0xe308, AG,      RXY_a, Z,   r1, m2_64, r1, 0, add, adds64)
+    C(0xe318, AGF,     RXY_a, Z,   r1, m2_32s, r1, 0, add, adds64)
+/* ADD IMMEDIATE */
+    C(0xc209, AFI,     RIL_a, EI,  r1, i2, new, r1_32, add, adds32)
+    C(0xeb6a, ASI,     SIY,   GIE, m1_32s, i2, new, m1_32, add, adds32)
+    C(0xecd8, AHIK,    RIE_d, DO,  r3, i2, new, r1_32, add, adds32)
+    C(0xc208, AGFI,    RIL_a, EI,  r1, i2, r1, 0, add, adds64)
+    C(0xeb7a, AGSI,    SIY,   GIE, m1_64, i2, new, m1_64, add, adds64)
+    C(0xecd9, AGHIK,   RIE_d, DO,  r3, i2, r1, 0, add, adds64)
+/* ADD LOGICAL */
+    C(0x1e00, ALR,     RR_a,  Z,   r1, r2, new, r1_32, add, addu32)
+    C(0xb9fa, ALRK,    RRF_a, DO,  r2, r3, new, r1_32, add, addu32)
+    C(0x5e00, AL,      RX_a,  Z,   r1, m2_32u, new, r1_32, add, addu32)
+    C(0xe35e, ALY,     RXY_a, LD,  r1, m2_32u, new, r1_32, add, addu32)
+    C(0xb90a, ALGR,    RRE,   Z,   r1, r2, r1, 0, add, addu64)
+    C(0xb91a, ALGFR,   RRE,   Z,   r1, r2_32u, r1, 0, add, addu64)
+    C(0xb9ea, ALGRK,   RRF_a, DO,  r2, r3, r1, 0, add, addu64)
+    C(0xe30a, ALG,     RXY_a, Z,   r1, m2_64, r1, 0, add, addu64)
+    C(0xe31a, ALGF,    RXY_a, Z,   r1, m2_32u, r1, 0, add, addu64)
+/* ADD LOGICAL IMMEDIATE */
+    C(0xc20b, ALFI,    RIL_a, EI,  r1, i2_32u, new, r1_32, add, addu32)
+    C(0xc20a, ALGFI,   RIL_a, EI,  r1, i2_32u, r1, 0, add, addu64)
+
+/* SUBTRACT */
+    C(0x1b00, SR,      RR_a,  Z,   r1, r2, new, r1_32, sub, subs32)
+    C(0xb9f9, SRK,     RRF_a, DO,  r2, r3, new, r1_32, sub, subs32)
+    C(0x5b00, S,       RX_a,  Z,   r1, m2_32s, new, r1_32, sub, subs32)
+    C(0xe35b, SY,      RXY_a, LD,  r1, m2_32s, new, r1_32, sub, subs32)
+    C(0xb909, SGR,     RRE,   Z,   r1, r2, r1, 0, sub, subs64)
+    C(0xb919, SGFR,    RRE,   Z,   r1, r2_32s, r1, 0, sub, subs64)
+    C(0xb9e9, SGRK,    RRF_a, DO,  r2, r3, r1, 0, sub, subs64)
+    C(0xe309, SG,      RXY_a, Z,   r1, m2_64, r1, 0, sub, subs64)
+    C(0xe319, SGF,     RXY_a, Z,   r1, m2_32s, r1, 0, sub, subs64)
+/* SUBTRACT LOGICAL */
+    C(0x1f00, SLR,     RR_a,  Z,   r1, r2, new, r1_32, sub, subu32)
+    C(0xb9fb, SLRK,    RRF_a, DO,  r2, r3, new, r1_32, sub, subu32)
+    C(0x5f00, SL,      RX_a,  Z,   r1, m2_32u, new, r1_32, sub, subu32)
+    C(0xe35f, SLY,     RXY_a, LD,  r1, m2_32u, new, r1_32, sub, subu32)
+    C(0xb90b, SLGR,    RRE,   Z,   r1, r2, r1, 0, sub, subu64)
+    C(0xb91b, SLGFR,   RRE,   Z,   r1, r2_32u, r1, 0, sub, subu64)
+    C(0xb9eb, SLGRK,   RRF_a, DO,  r2, r3, r1, 0, sub, subu64)
+    C(0xe30b, SLG,     RXY_a, Z,   r1, m2_64, r1, 0, sub, subu64)
+    C(0xe31b, SLGF,    RXY_a, Z,   r1, m2_32u, r1, 0, sub, subu64)
+/* SUBTRACT LOGICAL IMMEDIATE */
+    C(0xc205, SLFI,    RIL_a, EI,  r1, i2_32u, new, r1_32, sub, subu32)
+    C(0xc204, SLGFI,   RIL_a, EI,  r1, i2_32u, r1, 0, sub, subu64)
diff --git a/target-s390x/insn-format.def b/target-s390x/insn-format.def
new file mode 100644
index 0000000..0e898b9
--- /dev/null
+++ b/target-s390x/insn-format.def
@@ -0,0 +1,55 @@
+/* Description of s390 insn formats.  */
+/* NAME   F1,          F2... */
+F0(E)
+F1(I,     I(1, 8, 8))
+F2(RI_a,  R(1, 8),     I(2,16,16))
+F2(RI_b,  R(1, 8),     I(2,16,16))
+F2(RI_c,  M(1, 8),     I(2,16,16))
+F3(RIE_a, R(1, 8),     I(2,16,16),  M(3,32))
+F4(RIE_b, R(1, 8),     R(2,12),     M(3,32),   I(4,16,16))
+F4(RIE_c, R(1, 8),     I(2,32, 8),  M(3,12),   I(4,16,16))
+F3(RIE_d, R(1, 8),     I(2,16,16),  R(3,12))
+F3(RIE_e, R(1, 8),     I(2,16,16),  R(3,12))
+F5(RIE_f, R(1, 8),     R(2,12),     I(3,16,8), I(4,24,8),  I(5,32,8))
+F2(RIL_a, R(1, 8),     I(2,16,32))
+F2(RIL_b, R(1, 8),     I(2,16,32))
+F2(RIL_c, M(1, 8),     I(2,16,32))
+F4(RIS,   R(1, 8),     I(2,32, 8),  M(3,12),   BD(4,16,20))
+/* ??? The PoO does not call out subtypes _a and _b for RR, as it does
+   for e.g. RX.  Our checking requires this for e.g. BCR.  */
+F2(RR_a,  R(1, 8),     R(2,12))
+F2(RR_b,  M(1, 8),     R(2,12))
+F2(RRE,   R(1,24),     R(2,28))
+F3(RRD,   R(1,16),     R(2,28),     R(3,24))
+F4(RRF_a, R(1,24),     R(2,28),     R(3,16),   M(4,20))
+F4(RRF_b, R(1,24),     R(2,28),     R(3,16),   M(4,20))
+F4(RRF_c, R(1,24),     R(2,28),     M(3,16),   M(4,20))
+F4(RRF_d, R(1,24),     R(2,28),     M(3,16),   M(4,20))
+F4(RRF_e, R(1,24),     R(2,28),     M(3,16),   M(4,20))
+F4(RRS,   R(1, 8),     R(2,12),     M(3,32),   BD(4,16,20))
+F3(RS_a,  R(1, 8),     BD(2,16,20), R(3,12))
+F3(RS_b,  R(1, 8),     BD(2,16,20), M(3,12))
+F3(RSI,   R(1, 8),     I(2,16,16),  R(3,12))
+F2(RSL,   L(1, 8, 4),  BD(1,16,20))
+F3(RSY_a, R(1, 8),     BDL(2),      R(3,12))
+F3(RSY_b, R(1, 8),     BDL(2),      M(3,12))
+F2(RX_a,  R(1, 8),     BXD(2))
+F2(RX_b,  M(1, 8),     BXD(2))
+F2(RXE,   R(1, 8),     BXD(2))
+F3(RXF,   R(1,32),     BXD(2),      R(3, 8))
+F2(RXY_a, R(1, 8),     BXDL(2))
+F2(RXY_b, M(1, 8),     BXDL(2))
+F1(S,     BD(2,16,20))
+F2(SI,    BD(1,16,20), I(2,8,8))
+F2(SIL,   BD(1,16,20), I(2,32,16))
+F2(SIY,   BDL(1),      I(2, 8, 8))
+F3(SS_a,  L(1, 8, 8),  BD(1,16,20), BD(2,32,36))
+F4(SS_b,  L(1, 8, 4),  BD(1,16,20), L(2,12,4),   BD(2,32,36))
+F4(SS_c,  L(1, 8, 4),  BD(1,16,20), BD(2,32,36), I(3,12, 4))
+/* ??? Odd man out.  The L1 field here is really a register, but the
+   easy way to compress the fields has R1 and B1 overlap.  */
+F4(SS_d,  L(1, 8, 4),  BD(1,16,20), BD(2,32,36), R(3,12))
+F4(SS_e,  R(1, 8),     BD(2,16,20), R(3,12),     BD(4,32,36))
+F3(SS_f,  BD(1,16,20), L(2,8,8),    BD(2,32,36))
+F2(SSE,   BD(1,16,20), BD(2,32,36))
+F3(SSF,   BD(1,16,20), BD(2,32,36), R(3,8))
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index dc0f9cc..92d49e1 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -42,12 +42,20 @@ static TCGv_ptr cpu_env;
 #define GEN_HELPER 1
 #include "helper.h"
 
+
+/* Information that (most) every instruction needs to manipulate.  */
 typedef struct DisasContext DisasContext;
+typedef struct DisasInsn DisasInsn;
+typedef struct DisasFields DisasFields;
+
 struct DisasContext {
-    uint64_t pc;
-    int is_jmp;
-    enum cc_op cc_op;
     struct TranslationBlock *tb;
+    const DisasInsn *insn;
+    DisasFields *fields;
+    uint64_t pc, next_pc;
+    enum cc_op cc_op;
+    bool singlestep_enabled;
+    int is_jmp;
 };
 
 #define DISAS_EXCP 4
@@ -295,15 +303,12 @@ static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
 
 static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
 {
-    return (uint64_t)cpu_ldl_code(env, pc);
+    return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
 }
 
 static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
 {
-    uint64_t opc;
-    opc = (uint64_t)cpu_lduw_code(env, pc) << 32;
-    opc |= (uint64_t)(uint32_t)cpu_ldl_code(env, pc + 2);
-    return opc;
+    return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
 }
 
 static inline int get_mem_index(DisasContext *s)
@@ -607,17 +612,6 @@ static void set_cc_addu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
     gen_op_update3_cc_i64(s, CC_OP_ADDU_64, v1, v2, vr);
 }
 
-static void set_cc_sub64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2, TCGv_i64 vr)
-{
-    gen_op_update3_cc_i64(s, CC_OP_SUB_64, v1, v2, vr);
-}
-
-static void set_cc_subu64(DisasContext *s, TCGv_i64 v1, TCGv_i64 v2,
-                          TCGv_i64 vr)
-{
-    gen_op_update3_cc_i64(s, CC_OP_SUBU_64, v1, v2, vr);
-}
-
 static void set_cc_abs64(DisasContext *s, TCGv_i64 v1)
 {
     gen_op_update1_cc_i64(s, CC_OP_ABS_64, v1);
@@ -644,12 +638,6 @@ static void set_cc_sub32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2, TCGv_i32 vr)
     gen_op_update3_cc_i32(s, CC_OP_SUB_32, v1, v2, vr);
 }
 
-static void set_cc_subu32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
-                          TCGv_i32 vr)
-{
-    gen_op_update3_cc_i32(s, CC_OP_SUBU_32, v1, v2, vr);
-}
-
 static void set_cc_abs32(DisasContext *s, TCGv_i32 v1)
 {
     gen_op_update1_cc_i32(s, CC_OP_ABS_32, v1);
@@ -1535,72 +1523,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         tcg_temp_free_i64(tmp3);
         tcg_temp_free_i64(tmp4);
         break;
-    case 0x8: /* AG      R1,D2(X2,B2)     [RXY] */
-    case 0xa: /* ALG      R1,D2(X2,B2)     [RXY] */
-    case 0x18: /* AGF       R1,D2(X2,B2)     [RXY] */
-    case 0x1a: /* ALGF      R1,D2(X2,B2)     [RXY] */
-        if (op == 0x1a) {
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        } else if (op == 0x18) {
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        } else {
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        }
-        tmp4 = load_reg(r1);
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_add_i64(tmp3, tmp4, tmp2);
-        store_reg(r1, tmp3);
-        switch (op) {
-        case 0x8:
-        case 0x18:
-            set_cc_add64(s, tmp4, tmp2, tmp3);
-            break;
-        case 0xa:
-        case 0x1a:
-            set_cc_addu64(s, tmp4, tmp2, tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i64(tmp4);
-        break;
-    case 0x9: /* SG      R1,D2(X2,B2)     [RXY] */
-    case 0xb: /* SLG      R1,D2(X2,B2)     [RXY] */
-    case 0x19: /* SGF      R1,D2(X2,B2)     [RXY] */
-    case 0x1b: /* SLGF     R1,D2(X2,B2)     [RXY] */
-        tmp2 = tcg_temp_new_i64();
-        if (op == 0x19) {
-            tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        } else if (op == 0x1b) {
-            tcg_gen_qemu_ld32u(tmp2, addr, get_mem_index(s));
-        } else {
-            tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
-        }
-        tmp4 = load_reg(r1);
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_sub_i64(tmp3, tmp4, tmp2);
-        store_reg(r1, tmp3);
-        switch (op) {
-        case 0x9:
-        case 0x19:
-            set_cc_sub64(s, tmp4, tmp2, tmp3);
-            break;
-        case 0xb:
-        case 0x1b:
-            set_cc_subu64(s, tmp4, tmp2, tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        tcg_temp_free_i64(tmp4);
-        break;
     case 0xf: /* LRVG     R1,D2(X2,B2)     [RXE] */
         tmp2 = tcg_temp_new_i64();
         tcg_gen_qemu_ld64(tmp2, addr, get_mem_index(s));
@@ -1723,40 +1645,6 @@ static void disas_e3(CPUS390XState *env, DisasContext* s, int op, int r1,
         store_reg32_i64(r1, tmp3);
         tcg_temp_free_i64(tmp3);
         break;
-    case 0x5a: /* AY R1,D2(X2,B2) [RXY] */
-    case 0x5b: /* SY R1,D2(X2,B2) [RXY] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp32_3 = tcg_temp_new_i32();
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld32s(tmp2, addr, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp2);
-        tcg_temp_free_i64(tmp2);
-        switch (op) {
-        case 0x5a:
-            tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
-            break;
-        case 0x5b:
-            tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_3);
-        switch (op) {
-        case 0x5a:
-            set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x5b:
-            set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0x71: /* LAY R1,D2(X2,B2) [RXY] */
         store_reg(r1, addr);
         break;
@@ -3350,68 +3238,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         store_reg(r1, tmp2);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x8: /* AGR     R1,R2     [RRE] */
-    case 0xa: /* ALGR     R1,R2     [RRE] */
-        tmp = load_reg(r1);
-        tmp2 = load_reg(r2);
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_add_i64(tmp3, tmp, tmp2);
-        store_reg(r1, tmp3);
-        switch (op) {
-        case 0x8:
-            set_cc_add64(s, tmp, tmp2, tmp3);
-            break;
-        case 0xa:
-            set_cc_addu64(s, tmp, tmp2, tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-    case 0x9: /* SGR     R1,R2     [RRE] */
-    case 0xb: /* SLGR     R1,R2     [RRE] */
-    case 0x1b: /* SLGFR     R1,R2     [RRE] */
-    case 0x19: /* SGFR     R1,R2     [RRE] */
-        tmp = load_reg(r1);
-        switch (op) {
-        case 0x1b:
-            tmp32_1 = load_reg32(r2);
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-            tcg_temp_free_i32(tmp32_1);
-            break;
-        case 0x19:
-            tmp32_1 = load_reg32(r2);
-            tmp2 = tcg_temp_new_i64();
-            tcg_gen_ext_i32_i64(tmp2, tmp32_1);
-            tcg_temp_free_i32(tmp32_1);
-            break;
-        default:
-            tmp2 = load_reg(r2);
-            break;
-        }
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_sub_i64(tmp3, tmp, tmp2);
-        store_reg(r1, tmp3);
-        switch (op) {
-        case 0x9:
-        case 0x19:
-            set_cc_sub64(s, tmp, tmp2, tmp3);
-            break;
-        case 0xb:
-        case 0x1b:
-            set_cc_subu64(s, tmp, tmp2, tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0xc: /* MSGR      R1,R2     [RRE] */
     case 0x1c: /* MSGFR      R1,R2     [RRE] */
         tmp = load_reg(r1);
@@ -3469,29 +3295,6 @@ static void disas_b9(CPUS390XState *env, DisasContext *s, int op, int r1,
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i64(tmp);
         break;
-    case 0x18: /* AGFR     R1,R2     [RRE] */
-    case 0x1a: /* ALGFR     R1,R2     [RRE] */
-        tmp32_1 = load_reg32(r2);
-        tmp2 = tcg_temp_new_i64();
-        if (op == 0x18) {
-            tcg_gen_ext_i32_i64(tmp2, tmp32_1);
-        } else {
-            tcg_gen_extu_i32_i64(tmp2, tmp32_1);
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tmp = load_reg(r1);
-        tmp3 = tcg_temp_new_i64();
-        tcg_gen_add_i64(tmp3, tmp, tmp2);
-        store_reg(r1, tmp3);
-        if (op == 0x18) {
-            set_cc_add64(s, tmp, tmp2, tmp3);
-        } else {
-            set_cc_addu64(s, tmp, tmp2, tmp3);
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
     case 0x0f: /* LRVGR    R1,R2     [RRE] */
         tcg_gen_bswap64_i64(regs[r1], regs[r2]);
         break;
@@ -3794,54 +3597,10 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
 static void disas_c2(CPUS390XState *env, DisasContext *s, int op, int r1,
                      int i2)
 {
-    TCGv_i64 tmp, tmp2, tmp3;
-    TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+    TCGv_i64 tmp;
+    TCGv_i32 tmp32_1;
 
     switch (op) {
-    case 0x4: /* SLGFI R1,I2 [RIL] */
-    case 0xa: /* ALGFI R1,I2 [RIL] */
-        tmp = load_reg(r1);
-        tmp2 = tcg_const_i64((uint64_t)(uint32_t)i2);
-        tmp3 = tcg_temp_new_i64();
-        switch (op) {
-        case 0x4:
-            tcg_gen_sub_i64(tmp3, tmp, tmp2);
-            set_cc_subu64(s, tmp, tmp2, tmp3);
-            break;
-        case 0xa:
-            tcg_gen_add_i64(tmp3, tmp, tmp2);
-            set_cc_addu64(s, tmp, tmp2, tmp3);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg(r1, tmp3);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i64(tmp3);
-        break;
-    case 0x5: /* SLFI R1,I2 [RIL] */
-    case 0xb: /* ALFI R1,I2 [RIL] */
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_const_i32(i2);
-        tmp32_3 = tcg_temp_new_i32();
-        switch (op) {
-        case 0x5:
-            tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
-            set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0xb:
-            tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
-            set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_3);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0xc: /* CGFI R1,I2 [RIL] */
         tmp = load_reg(r1);
         cmp_s64c(s, tmp, (int64_t)i2);
@@ -4059,42 +3818,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x1a: /* AR     R1,R2     [RR] */
-    case 0x1e: /* ALR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r2);
-        tmp32_3 = tcg_temp_new_i32();
-        tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_3);
-        if (opc == 0x1a) {
-            set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
-        } else {
-            set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
-    case 0x1b: /* SR     R1,R2     [RR] */
-    case 0x1f: /* SLR    R1,R2     [RR] */
-        insn = ld_code2(env, s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = load_reg32(r2);
-        tmp32_3 = tcg_temp_new_i32();
-        tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
-        store_reg32(r1, tmp32_3);
-        if (opc == 0x1b) {
-            set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
-        } else {
-            set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
-        }
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0x1c: /* MR     R1,R2     [RR] */
         /* reg(r1, r1+1) = reg(r1+1) * reg(r2) */
         insn = ld_code2(env, s->pc);
@@ -4380,51 +4103,6 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x5a: /* A      R1,D2(X2,B2)     [RX] */
-    case 0x5b: /* S      R1,D2(X2,B2)     [RX] */
-    case 0x5e: /* AL     R1,D2(X2,B2)     [RX] */
-    case 0x5f: /* SL     R1,D2(X2,B2)     [RX] */
-        insn = ld_code4(env, s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp32_1 = load_reg32(r1);
-        tmp32_2 = tcg_temp_new_i32();
-        tmp32_3 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32s(tmp, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_2, tmp);
-        switch (opc) {
-        case 0x5a:
-        case 0x5e:
-            tcg_gen_add_i32(tmp32_3, tmp32_1, tmp32_2);
-            break;
-        case 0x5b:
-        case 0x5f:
-            tcg_gen_sub_i32(tmp32_3, tmp32_1, tmp32_2);
-            break;
-        default:
-            tcg_abort();
-        }
-        store_reg32(r1, tmp32_3);
-        switch (opc) {
-        case 0x5a:
-            set_cc_add32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x5e:
-            set_cc_addu32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x5b:
-            set_cc_sub32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        case 0x5f:
-            set_cc_subu32(s, tmp32_1, tmp32_2, tmp32_3);
-            break;
-        default:
-            tcg_abort();
-        }
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i32(tmp32_1);
-        tcg_temp_free_i32(tmp32_2);
-        tcg_temp_free_i32(tmp32_3);
-        break;
     case 0x5c: /* M      R1,D2(X2,B2)        [RX] */
         /* reg(r1, r1+1) = reg(r1+1) * *(s32*)addr */
         insn = ld_code4(env, s->pc);
@@ -5131,9 +4809,699 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         gen_illegal_opcode(env, s, ilc);
         break;
     }
+}
+
+/* ====================================================================== */
+/* Define the insn format enumeration.  */
+#define F0(N)                         FMT_##N,
+#define F1(N, X1)                     F0(N)
+#define F2(N, X1, X2)                 F0(N)
+#define F3(N, X1, X2, X3)             F0(N)
+#define F4(N, X1, X2, X3, X4)         F0(N)
+#define F5(N, X1, X2, X3, X4, X5)     F0(N)
+
+typedef enum {
+#include "insn-format.def"
+} DisasFormat;
+
+#undef F0
+#undef F1
+#undef F2
+#undef F3
+#undef F4
+#undef F5
+
+/* Define a structure to hold the decoded fields.  We'll store each inside
+   an array indexed by an enum.  In order to conserve memory, we'll arrange
+   for fields that do not exist at the same time to overlap, thus the "C"
+   for compact.  For checking purposes there is an "O" for original index
+   as well that will be applied to availability bitmaps.  */
+
+enum DisasFieldIndexO {
+    FLD_O_r1,
+    FLD_O_r2,
+    FLD_O_r3,
+    FLD_O_m1,
+    FLD_O_m3,
+    FLD_O_m4,
+    FLD_O_b1,
+    FLD_O_b2,
+    FLD_O_b4,
+    FLD_O_d1,
+    FLD_O_d2,
+    FLD_O_d4,
+    FLD_O_x2,
+    FLD_O_l1,
+    FLD_O_l2,
+    FLD_O_i1,
+    FLD_O_i2,
+    FLD_O_i3,
+    FLD_O_i4,
+    FLD_O_i5
+};
+
+enum DisasFieldIndexC {
+    FLD_C_r1 = 0,
+    FLD_C_m1 = 0,
+    FLD_C_b1 = 0,
+    FLD_C_i1 = 0,
+
+    FLD_C_r2 = 1,
+    FLD_C_b2 = 1,
+    FLD_C_i2 = 1,
+
+    FLD_C_r3 = 2,
+    FLD_C_m3 = 2,
+    FLD_C_i3 = 2,
+
+    FLD_C_m4 = 3,
+    FLD_C_b4 = 3,
+    FLD_C_i4 = 3,
+    FLD_C_l1 = 3,
+
+    FLD_C_i5 = 4,
+    FLD_C_d1 = 4,
+
+    FLD_C_d2 = 5,
+
+    FLD_C_d4 = 6,
+    FLD_C_x2 = 6,
+    FLD_C_l2 = 6,
+
+    NUM_C_FIELD = 7
+};
+
+struct DisasFields {
+    unsigned op:8;
+    unsigned op2:8;
+    unsigned presentC:16;
+    unsigned int presentO;
+    int c[NUM_C_FIELD];
+};
+
+/* This is the way fields are to be accessed out of DisasFields.  */
+#define have_field(S, F)  have_field1((S), FLD_O_##F)
+#define get_field(S, F)   get_field1((S), FLD_O_##F, FLD_C_##F)
+
+static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
+{
+    return (f->presentO >> c) & 1;
+}
+
+static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
+                      enum DisasFieldIndexC c)
+{
+    assert(have_field1(f, o));
+    return f->c[c];
+}
+
+/* Describe the layout of each field in each format.  */
+typedef struct DisasField {
+    unsigned int beg:8;
+    unsigned int size:8;
+    unsigned int type:2;
+    unsigned int indexC:6;
+    enum DisasFieldIndexO indexO:8;
+} DisasField;
+
+typedef struct DisasFormatInfo {
+    DisasField op[NUM_C_FIELD];
+} DisasFormatInfo;
+
+#define R(N, B)       {  B,  4, 0, FLD_C_r##N, FLD_O_r##N }
+#define M(N, B)       {  B,  4, 0, FLD_C_m##N, FLD_O_m##N }
+#define BD(N, BB, BD) { BB,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
+                      { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
+#define BXD(N)        { 16,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
+                      { 12,  4, 0, FLD_C_x##N, FLD_O_x##N }, \
+                      { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
+#define BDL(N)        { 16,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
+                      { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
+#define BXDL(N)       { 16,  4, 0, FLD_C_b##N, FLD_O_b##N }, \
+                      { 12,  4, 0, FLD_C_x##N, FLD_O_x##N }, \
+                      { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
+#define I(N, B, S)    {  B,  S, 1, FLD_C_i##N, FLD_O_i##N }
+#define L(N, B, S)    {  B,  S, 0, FLD_C_l##N, FLD_O_l##N }
+
+#define F0(N)                     { { } },
+#define F1(N, X1)                 { { X1 } },
+#define F2(N, X1, X2)             { { X1, X2 } },
+#define F3(N, X1, X2, X3)         { { X1, X2, X3 } },
+#define F4(N, X1, X2, X3, X4)     { { X1, X2, X3, X4 } },
+#define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
+
+static const DisasFormatInfo format_info[] = {
+#include "insn-format.def"
+};
+
+#undef F0
+#undef F1
+#undef F2
+#undef F3
+#undef F4
+#undef F5
+#undef R
+#undef M
+#undef BD
+#undef BXD
+#undef BDL
+#undef BXDL
+#undef I
+#undef L
+
+/* Generally, we'll extract operands into this structures, operate upon
+   them, and store them back.  See the "in1", "in2", "prep", "wout" sets
+   of routines below for more details.  */
+typedef struct {
+    bool g_out, g_out2, g_in1, g_in2;
+    TCGv_i64 out, out2, in1, in2;
+    TCGv_i64 addr1;
+} DisasOps;
+
+/* Return values from translate_one, indicating the state of the TB.  */
+typedef enum {
+    /* Continue the TB.  */
+    NO_EXIT,
+    /* We have emitted one or more goto_tb.  No fixup required.  */
+    EXIT_GOTO_TB,
+    /* We are not using a goto_tb (for whatever reason), but have updated
+       the PC (for whatever reason), so there's no need to do it again on
+       exiting the TB.  */
+    EXIT_PC_UPDATED,
+    /* We are exiting the TB, but have neither emitted a goto_tb, nor
+       updated the PC for the next instruction to be executed.  */
+    EXIT_PC_STALE,
+    /* We are ending the TB with a noreturn function call, e.g. longjmp.
+       No following code will be executed.  */
+    EXIT_NORETURN,
+} ExitStatus;
+
+typedef enum DisasFacility {
+    FAC_Z,                  /* zarch (default) */
+    FAC_CASS,               /* compare and swap and store */
+    FAC_CASS2,              /* compare and swap and store 2*/
+    FAC_DFP,                /* decimal floating point */
+    FAC_DFPR,               /* decimal floating point rounding */
+    FAC_DO,                 /* distinct operands */
+    FAC_EE,                 /* execute extensions */
+    FAC_EI,                 /* extended immediate */
+    FAC_FPE,                /* floating point extension */
+    FAC_FPSSH,              /* floating point support sign handling */
+    FAC_FPRGR,              /* FPR-GR transfer */
+    FAC_GIE,                /* general instructions extension */
+    FAC_HFP_MA,             /* HFP multiply-and-add/subtract */
+    FAC_HW,                 /* high-word */
+    FAC_IEEEE_SIM,          /* IEEE exception sumilation */
+    FAC_LOC,                /* load/store on condition */
+    FAC_LD,                 /* long displacement */
+    FAC_PC,                 /* population count */
+    FAC_SCF,                /* store clock fast */
+    FAC_SFLE,               /* store facility list extended */
+} DisasFacility;
+
+struct DisasInsn {
+    unsigned opc:16;
+    DisasFormat fmt:6;
+    DisasFacility fac:6;
+
+    const char *name;
+
+    void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
+    void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
+    void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
+    void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
+    void (*help_cout)(DisasContext *, DisasOps *);
+    ExitStatus (*help_op)(DisasContext *, DisasOps *);
+
+    uint64_t data;
+};
+
+/* ====================================================================== */
+/* The operations.  These perform the bulk of the work for any insn,
+   usually after the operands have been loaded and output initialized.  */
+
+static ExitStatus op_add(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_add_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+static ExitStatus op_sub(DisasContext *s, DisasOps *o)
+{
+    tcg_gen_sub_i64(o->out, o->in1, o->in2);
+    return NO_EXIT;
+}
+
+/* ====================================================================== */
+/* The "Cc OUTput" generators.  Given the generated output (and in some cases
+   the original inputs), update the various cc data structures in order to
+   be able to compute the new condition code.  */
+
+static void cout_adds32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
+}
+
+static void cout_adds64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
+}
+
+static void cout_addu32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
+}
+
+static void cout_addu64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
+}
+
+static void cout_subs32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subs64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
+}
+
+static void cout_subu32(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
+}
+
+static void cout_subu64(DisasContext *s, DisasOps *o)
+{
+    gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
+}
+
+/* ====================================================================== */
+/* The "PREPeration" generators.  These initialize the DisasOps.OUT fields
+   with the TCG register to which we will write.  Used in combination with
+   the "wout" generators, in some cases we need a new temporary, and in
+   some cases we can write to a TCG global.  */
+
+static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->out = tcg_temp_new_i64();
+}
+
+static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->out = regs[get_field(f, r1)];
+    o->g_out = true;
+}
+
+/* ====================================================================== */
+/* The "Write OUTput" generators.  These generally perform some non-trivial
+   copy of data to TCG globals, or to main memory.  The trivial cases are
+   generally handled by having a "prep" generator install the TCG global
+   as the destination of the operation.  */
+
+static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_reg32_i64(get_field(f, r1), o->out);
+}
+
+static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
+}
+
+static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
+}
+
+/* ====================================================================== */
+/* The "INput 1" generators.  These load the first operand to an insn.  */
+
+static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = load_reg(get_field(f, r1));
+}
+
+static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = load_reg(get_field(f, r2));
+}
+
+static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in1 = load_reg(get_field(f, r3));
+}
+
+static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
+}
+
+static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
+}
+
+static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in1_la1(s, f, o);
+    o->in1 = tcg_temp_new_i64();
+    tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
+}
+
+/* ====================================================================== */
+/* The "INput 2" generators.  These load the second operand to an insn.  */
+
+static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = load_reg(get_field(f, r2));
+}
+
+static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = load_reg(get_field(f, r3));
+}
+
+static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_temp_new_i64();
+    tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
+}
+
+static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
+    o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
+}
+
+static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    in2_a2(s, f, o);
+    tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
+}
+
+static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_const_i64(get_field(f, i2));
+}
+
+static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
+}
+
+/* ====================================================================== */
+
+/* Find opc within the table of insns.  This is formulated as a switch
+   statement so that (1) we get compile-time notice of cut-paste errors
+   for duplicated opcodes, and (2) the compiler generates the binary
+   search tree, rather than us having to post-process the table.  */
+
+#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
+    D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
+
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
+
+enum DisasInsnEnum {
+#include "insn-data.def"
+};
+
+#undef D
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
+    .opc = OPC,                           \
+    .fmt = FMT_##FT,                      \
+    .fac = FAC_##FC,                      \
+    .name = #NM,                          \
+    .help_in1 = in1_##I1,                 \
+    .help_in2 = in2_##I2,                 \
+    .help_prep = prep_##P,                \
+    .help_wout = wout_##W,                \
+    .help_cout = cout_##CC,               \
+    .help_op = op_##OP,                   \
+    .data = D                             \
+ },
+
+/* Allow 0 to be used for NULL in the table below.  */
+#define in1_0  NULL
+#define in2_0  NULL
+#define prep_0  NULL
+#define wout_0  NULL
+#define cout_0  NULL
+#define op_0  NULL
+
+static const DisasInsn insn_info[] = {
+#include "insn-data.def"
+};
+
+#undef D
+#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
+    case OPC: return &insn_info[insn_ ## NM];
+
+static const DisasInsn *lookup_opc(uint16_t opc)
+{
+    switch (opc) {
+#include "insn-data.def"
+    default:
+        return NULL;
+    }
+}
+
+#undef D
+#undef C
+
+/* Extract a field from the insn.  The INSN should be left-aligned in
+   the uint64_t so that we can more easily utilize the big-bit-endian
+   definitions we extract from the Principals of Operation.  */
+
+static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
+{
+    uint32_t r, m;
+
+    if (f->size == 0) {
+        return;
+    }
+
+    /* Zero extract the field from the insn.  */
+    r = (insn << f->beg) >> (64 - f->size);
+
+    /* Sign-extend, or un-swap the field as necessary.  */
+    switch (f->type) {
+    case 0: /* unsigned */
+        break;
+    case 1: /* signed */
+        assert(f->size <= 32);
+        m = 1u << (f->size - 1);
+        r = (r ^ m) - m;
+        break;
+    case 2: /* dl+dh split, signed 20 bit. */
+        r = ((int8_t)r << 12) | (r >> 8);
+        break;
+    default:
+        abort();
+    }
+
+    /* Validate that the "compressed" encoding we selected above is valid.
+       I.e. we havn't make two different original fields overlap.  */
+    assert(((o->presentC >> f->indexC) & 1) == 0);
+    o->presentC |= 1 << f->indexC;
+    o->presentO |= 1 << f->indexO;
+
+    o->c[f->indexC] = r;
+}
+
+/* Lookup the insn at the current PC, extracting the operands into O and
+   returning the info struct for the insn.  Returns NULL for invalid insn.  */
+
+static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
+                                     DisasFields *f)
+{
+    uint64_t insn, pc = s->pc;
+    int op, op2;
+    const DisasInsn *info;
+
+    insn = ld_code2(env, pc);
+    op = (insn >> 8) & 0xff;
+    switch (get_ilc(op)) {
+    case 1:
+        insn = insn << 48;
+        break;
+    case 2:
+        insn = ld_code4(env, pc) << 32;
+        break;
+    case 3:
+        insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
+        break;
+    default:
+        abort();
+    }
+
+    /* We can't actually determine the insn format until we've looked up
+       the full insn opcode.  Which we can't do without locating the
+       secondary opcode.  Assume by default that OP2 is at bit 40; for
+       those smaller insns that don't actually have a secondary opcode
+       this will correctly result in OP2 = 0. */
+    switch (op) {
+    case 0x01: /* E */
+    case 0x80: /* S */
+    case 0x82: /* S */
+    case 0x93: /* S */
+    case 0xb2: /* S, RRF, RRE */
+    case 0xb3: /* RRE, RRD, RRF */
+    case 0xb9: /* RRE, RRF */
+    case 0xe5: /* SSE, SIL */
+        op2 = (insn << 8) >> 56;
+        break;
+    case 0xa5: /* RI */
+    case 0xa7: /* RI */
+    case 0xc0: /* RIL */
+    case 0xc2: /* RIL */
+    case 0xc4: /* RIL */
+    case 0xc6: /* RIL */
+    case 0xc8: /* SSF */
+    case 0xcc: /* RIL */
+        op2 = (insn << 12) >> 60;
+        break;
+    case 0xd0 ... 0xdf: /* SS */
+    case 0xe1: /* SS */
+    case 0xe2: /* SS */
+    case 0xe8: /* SS */
+    case 0xe9: /* SS */
+    case 0xea: /* SS */
+    case 0xee ... 0xf3: /* SS */
+    case 0xf8 ... 0xfd: /* SS */
+        op2 = 0;
+        break;
+    default:
+        op2 = (insn << 40) >> 56;
+        break;
+    }
+
+    memset(f, 0, sizeof(*f));
+    f->op = op;
+    f->op2 = op2;
+
+    /* Lookup the instruction.  */
+    info = lookup_opc(op << 8 | op2);
+
+    /* If we found it, extract the operands.  */
+    if (info != NULL) {
+        DisasFormat fmt = info->fmt;
+        int i;
+
+        for (i = 0; i < NUM_C_FIELD; ++i) {
+            extract_field(f, &format_info[fmt].op[i], insn);
+        }
+    }
+    return info;
+}
+
+static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
+{
+    const DisasInsn *insn;
+    ExitStatus ret = NO_EXIT;
+    DisasFields f;
+    DisasOps o;
+
+    insn = extract_insn(env, s, &f);
 
     /* Instruction length is encoded in the opcode */
-    s->pc += (ilc * 2);
+    s->next_pc = s->pc + get_ilc(f.op) * 2;
+
+    /* If not found, try the old interpreter.  This includes ILLOPC.  */
+    if (insn == NULL) {
+        disas_s390_insn(env, s);
+        switch (s->is_jmp) {
+        case DISAS_NEXT:
+            ret = NO_EXIT;
+            break;
+        case DISAS_TB_JUMP:
+            ret = EXIT_GOTO_TB;
+            break;
+        case DISAS_JUMP:
+            ret = EXIT_PC_UPDATED;
+            break;
+        case DISAS_EXCP:
+            ret = EXIT_NORETURN;
+            break;
+        default:
+            abort();
+        }
+
+        s->pc = s->next_pc;
+        return ret;
+    }
+
+    /* Set up the strutures we use to communicate with the helpers. */
+    s->insn = insn;
+    s->fields = &f;
+    o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
+    TCGV_UNUSED_I64(o.out);
+    TCGV_UNUSED_I64(o.out2);
+    TCGV_UNUSED_I64(o.in1);
+    TCGV_UNUSED_I64(o.in2);
+    TCGV_UNUSED_I64(o.addr1);
+
+    /* Implement the instruction.  */
+    if (insn->help_in1) {
+        insn->help_in1(s, &f, &o);
+    }
+    if (insn->help_in2) {
+        insn->help_in2(s, &f, &o);
+    }
+    if (insn->help_prep) {
+        insn->help_prep(s, &f, &o);
+    }
+    if (insn->help_op) {
+        ret = insn->help_op(s, &o);
+    }
+    if (insn->help_wout) {
+        insn->help_wout(s, &f, &o);
+    }
+    if (insn->help_cout) {
+        insn->help_cout(s, &o);
+    }
+
+    /* Free any temporaries created by the helpers.  */
+    if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
+        tcg_temp_free_i64(o.out);
+    }
+    if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
+        tcg_temp_free_i64(o.out2);
+    }
+    if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
+        tcg_temp_free_i64(o.in1);
+    }
+    if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
+        tcg_temp_free_i64(o.in2);
+    }
+    if (!TCGV_IS_UNUSED_I64(o.addr1)) {
+        tcg_temp_free_i64(o.addr1);
+    }
+
+    /* Advance to the next instruction.  */
+    s->pc = s->next_pc;
+    return ret;
 }
 
 static inline void gen_intermediate_code_internal(CPUS390XState *env,
@@ -5147,6 +5515,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
     int j, lj = -1;
     int num_insns, max_insns;
     CPUBreakpoint *bp;
+    ExitStatus status;
 
     pc_start = tb->pc;
 
@@ -5155,10 +5524,11 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         pc_start &= 0x7fffffff;
     }
 
-    dc.pc = pc_start;
-    dc.is_jmp = DISAS_NEXT;
     dc.tb = tb;
+    dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
+    dc.singlestep_enabled = env->singlestep_enabled;
+    dc.is_jmp = DISAS_NEXT;
 
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
 
@@ -5194,7 +5564,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             tcg_ctx.gen_opc_instr_start[lj] = 1;
             tcg_ctx.gen_opc_icount[lj] = num_insns;
         }
-        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+        if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
 
@@ -5202,36 +5572,50 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
             tcg_gen_debug_insn_start(dc.pc);
         }
 
-        disas_s390_insn(env, &dc);
-
-        num_insns++;
-        if (env->singlestep_enabled) {
-            gen_debug(&dc);
+        status = translate_one(env, &dc);
+
+        /* If we reach a page boundary, are single stepping,
+           or exhaust instruction count, stop generation.  */
+        if (status == NO_EXIT
+            && (dc.pc >= next_page_start
+                || tcg_ctx.gen_opc_ptr >= gen_opc_end
+                || num_insns >= max_insns
+                || singlestep
+                || env->singlestep_enabled)) {
+            status = EXIT_PC_STALE;
         }
-    } while (!dc.is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end
-             && dc.pc < next_page_start
-             && num_insns < max_insns && !env->singlestep_enabled
-             && !singlestep);
-
-    if (!dc.is_jmp) {
-        update_psw_addr(&dc);
-    }
-
-    if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
-        gen_op_calc_cc(&dc);
-    } else {
-        /* next TB starts off with CC_OP_DYNAMIC, so make sure the cc op type
-           is in env */
-        gen_op_set_cc_op(&dc);
-    }
+    } while (status == NO_EXIT);
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
-    /* Generate the return instruction */
-    if (dc.is_jmp != DISAS_TB_JUMP) {
-        tcg_gen_exit_tb(0);
+
+    switch (status) {
+    case EXIT_GOTO_TB:
+    case EXIT_NORETURN:
+        break;
+    case EXIT_PC_STALE:
+        update_psw_addr(&dc);
+        /* FALLTHRU */
+    case EXIT_PC_UPDATED:
+        if (singlestep && dc.cc_op != CC_OP_DYNAMIC) {
+            gen_op_calc_cc(&dc);
+        } else {
+            /* Next TB starts off with CC_OP_DYNAMIC,
+               so make sure the cc op type is in env */
+            gen_op_set_cc_op(&dc);
+        }
+        if (env->singlestep_enabled) {
+            gen_debug(&dc);
+        } else {
+            /* Generate the return instruction */
+            tcg_gen_exit_tb(0);
+        }
+        break;
+    default:
+        abort();
     }
+
     gen_icount_end(tb, num_insns);
     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
@@ -5244,6 +5628,7 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env,
         tb->size = dc.pc - pc_start;
         tb->icount = num_insns;
     }
+
 #if defined(S390X_DEBUG_DISAS)
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
commit 51855ecf1a9d5a8388778571b8ab32134e83f378
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Sep 24 12:06:15 2012 -0700

    target-s390: Fix PSW_MASK handling
    
    We were treating psw.mask as the 32-bit quantity it is in ESA mode.
    In particular, the CC field was at the wrong place.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 42e06eb..7dc4d46 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -454,18 +454,19 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 
     env->psw.addr = addr;
     env->psw.mask = mask;
-    env->cc_op = (mask >> 13) & 3;
+    env->cc_op = (mask >> 44) & 3;
 }
 
 static uint64_t get_psw_mask(CPUS390XState *env)
 {
-    uint64_t r = env->psw.mask;
+    uint64_t r;
 
     env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
 
-    r &= ~(3ULL << 13);
+    r = env->psw.mask;
+    r &= ~PSW_MASK_CC;
     assert(!(env->cc_op & ~3));
-    r |= env->cc_op << 13;
+    r |= (uint64_t)env->cc_op << 44;
 
     return r;
 }
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b8f2ca8..dc0f9cc 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -4559,6 +4559,8 @@ static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
         tcg_gen_addi_i64(tmp, tmp, 4);
         tcg_gen_qemu_ld32u(tmp3, tmp, get_mem_index(s));
+        /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK.  */
+        tcg_gen_shli_i64(tmp2, tmp2, 32);
         gen_helper_load_psw(cpu_env, tmp2, tmp3);
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
commit 2f22e2ec79c07de03016adefb166cf01745fc852
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 22 05:28:43 2012 -0700

    target-s390: Tidy unconditional BRCL
    
    Yes, we're about to rewrite all of this, but having this unconditional
    jump recompute cc_op is a large source of "false diff errors" when
    trying to examine before and after dumps.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 79ab3e5..b8f2ca8 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3706,6 +3706,11 @@ static void disas_c0(CPUS390XState *env, DisasContext *s, int op, int r1, int i2
         tcg_temp_free_i64(tmp);
         break;
     case 0x4: /* BRCL     M1,I2     [RIL] */
+        if (r1 == 15) { /* m1 == r1 */
+            gen_goto_tb(s, 0, target);
+            s->is_jmp = DISAS_TB_JUMP;
+            break;
+        }
         /* m1 & (1 << (3 - cc)) */
         tmp32_1 = tcg_const_i32(3);
         tmp32_2 = tcg_const_i32(1);
commit 9d126faf4279b324d5c4cdf09a3570d4a2041626
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 22 05:25:09 2012 -0700

    target-s390: Fix BCR
    
    There were are two exit paths for which we forgot to
    copy s->cc_op back to the tcg register.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 4898c7b..79ab3e5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1212,6 +1212,7 @@ static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
 
     if (mask == 0xf) {
         /* unconditional */
+        gen_update_cc_op(s);
         tcg_gen_mov_i64(psw_addr, target);
         tcg_gen_exit_tb(0);
     } else if (mask == 0) {
@@ -1223,6 +1224,7 @@ static void gen_bcr(DisasContext *s, uint32_t mask, TCGv_i64 target,
         tcg_gen_mov_i64(new_addr, target);
         skip = gen_new_label();
         gen_jcc(s, mask, skip);
+        gen_update_cc_op(s);
         tcg_gen_mov_i64(psw_addr, new_addr);
         tcg_temp_free_i64(new_addr);
         tcg_gen_exit_tb(0);
commit afd43fecfe7f6e863884b850f53fac4a75c28d84
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 22 05:22:18 2012 -0700

    target-s390: Fix SACF exit
    
    DISAS_EXCP is exit via exception; we wanted DISAS_JUMP.
    This matters when we start cleaning up the TB exit paths.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1df3c53..4898c7b 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2933,7 +2933,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         tcg_temp_free_i64(tmp);
         break;
     case 0x79: /* SACF    D2(B2)     [S] */
-        /* Store Clock Extended */
+        /* Set Address Space Control Fast */
         check_privileged(env, s, ilc);
         decode_rs(s, insn, &r1, &r3, &b2, &d2);
         tmp = get_address(s, 0, b2, d2);
@@ -2943,7 +2943,7 @@ static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         /* addressing mode has changed, so end the block */
         s->pc += ilc * 2;
         update_psw_addr(s);
-        s->is_jmp = DISAS_EXCP;
+        s->is_jmp = DISAS_JUMP;
         break;
     case 0x7d: /* STSI     D2,(B2)     [S] */
         check_privileged(env, s, ilc);
commit 7e68da2a9dd112a1a4ef16e8ef3dc1916529ae6b
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 19 09:14:33 2012 -0700

    target-s390: Register helpers
    
    Which highlights a lot of cc helpers that no longer exist.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index c4926c5..2498f83 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -7,21 +7,10 @@ DEF_HELPER_4(xc, i32, env, i32, i64, i64)
 DEF_HELPER_4(mvc, void, env, i32, i64, i64)
 DEF_HELPER_4(clc, i32, env, i32, i64, i64)
 DEF_HELPER_3(mvcl, i32, env, i32, i32)
-DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_NO_RWG_SE, i32, s32)
-DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_NO_RWG_SE, i32, s64)
-DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_4(clm, i32, env, i32, i32, i64)
 DEF_HELPER_4(stcm, void, env, i32, i32, i64)
 DEF_HELPER_3(mlg, void, env, i32, i64)
 DEF_HELPER_3(dlg, void, env, i32, i64)
-DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64)
-DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32)
-DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64)
-DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
-DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32)
-DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
 DEF_HELPER_4(srst, i32, env, i32, i32, i32)
 DEF_HELPER_4(clst, i32, env, i32, i32, i32)
 DEF_HELPER_4(mvpg, void, env, i64, i64, i64)
@@ -38,7 +27,6 @@ DEF_HELPER_4(stcmh, void, env, i32, i64, i32)
 DEF_HELPER_4(icmh, i32, env, i32, i64, i32)
 DEF_HELPER_3(ipm, void, env, i32, i32)
 DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
-DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
 DEF_HELPER_4(stam, void, env, i32, i64, i32)
 DEF_HELPER_4(lam, void, env, i32, i64, i32)
 DEF_HELPER_4(mvcle, i32, env, i32, i64, i32)
@@ -112,11 +100,13 @@ DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
 DEF_HELPER_4(unpk, void, env, i32, i64, i64)
 DEF_HELPER_4(tr, void, env, i32, i64, i64)
+DEF_HELPER_3(cksm, void, env, i32, i32)
+DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 
+#ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i32, i64)
 DEF_HELPER_4(diag, i64, env, i32, i64, i64)
 DEF_HELPER_3(load_psw, void, env, i64, i64)
-DEF_HELPER_1(program_interrupt, void, i32)
 DEF_HELPER_FLAGS_2(stidp, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64)
 DEF_HELPER_FLAGS_1(sck, TCG_CALL_NO_RWG, i32, i64)
@@ -144,9 +134,6 @@ DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64)
 DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_3(lra, i32, env, i64, i32)
 DEF_HELPER_3(stura, void, env, i64, i32)
-DEF_HELPER_3(cksm, void, env, i32, i32)
-
-DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE,
-                   i32, env, i32, i64, i64, i64)
+#endif
 
 #include "exec/def-helper.h"
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2745065..1df3c53 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -174,6 +174,10 @@ void s390x_translate_init(void)
                                       offsetof(CPUS390XState, fregs[i].d),
                                       cpu_reg_names[i + 16]);
     }
+
+    /* register helpers */
+#define GEN_HELPER 2
+#include "helper.h"
 }
 
 static inline TCGv_i64 load_reg(int reg)
commit 431253c28f9177a3f4783dc47b952c8fffcf3177
Author: Richard Henderson <rth at twiddle.net>
Date:   Wed Sep 5 06:57:35 2012 -0700

    target-s390: Use TCG registers for FPR
    
    At the same time, tidy other usages of tcg_gen_deposit_i64.
    In some cases we can "type cast" rather than extend, and in
    others we can allow tcg_gen_deposit_i64 itself to optimize
    the HOST_LONG_BITS==32 case.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f1e754f..2745065 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -97,7 +97,7 @@ void cpu_dump_state(CPUS390XState *env, FILE *f, fprintf_function cpu_fprintf,
     }
 
     for (i = 0; i < 16; i++) {
-        cpu_fprintf(f, "F%02d=%016" PRIx64, i, *(uint64_t *)&env->fregs[i]);
+        cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
         if ((i % 4) == 3) {
             cpu_fprintf(f, "\n");
         } else {
@@ -134,21 +134,22 @@ static TCGv_i64 cc_src;
 static TCGv_i64 cc_dst;
 static TCGv_i64 cc_vr;
 
-static char cpu_reg_names[10*3 + 6*4];
+static char cpu_reg_names[32][4];
 static TCGv_i64 regs[16];
+static TCGv_i64 fregs[16];
 
 static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
 
 void s390x_translate_init(void)
 {
     int i;
-    size_t cpu_reg_names_size = sizeof(cpu_reg_names);
-    char *p;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
-    psw_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.addr),
+    psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
+                                      offsetof(CPUS390XState, psw.addr),
                                       "psw_addr");
-    psw_mask = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, psw.mask),
+    psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
+                                      offsetof(CPUS390XState, psw.mask),
                                       "psw_mask");
 
     cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
@@ -160,13 +161,18 @@ void s390x_translate_init(void)
     cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
                                    "cc_vr");
 
-    p = cpu_reg_names;
     for (i = 0; i < 16; i++) {
-        snprintf(p, cpu_reg_names_size, "r%d", i);
+        snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
         regs[i] = tcg_global_mem_new(TCG_AREG0,
-                                     offsetof(CPUS390XState, regs[i]), p);
-        p += (i < 10) ? 3 : 4;
-        cpu_reg_names_size -= (i < 10) ? 3 : 4;
+                                     offsetof(CPUS390XState, regs[i]),
+                                     cpu_reg_names[i]);
+    }
+
+    for (i = 0; i < 16; i++) {
+        snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
+        fregs[i] = tcg_global_mem_new(TCG_AREG0,
+                                      offsetof(CPUS390XState, fregs[i].d),
+                                      cpu_reg_names[i + 16]);
     }
 }
 
@@ -180,14 +186,18 @@ static inline TCGv_i64 load_reg(int reg)
 static inline TCGv_i64 load_freg(int reg)
 {
     TCGv_i64 r = tcg_temp_new_i64();
-    tcg_gen_ld_i64(r, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
+    tcg_gen_mov_i64(r, fregs[reg]);
     return r;
 }
 
 static inline TCGv_i32 load_freg32(int reg)
 {
     TCGv_i32 r = tcg_temp_new_i32();
-    tcg_gen_ld_i32(r, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
+#if HOST_LONG_BITS == 32
+    tcg_gen_mov_i32(r, TCGV_HIGH(fregs[reg]));
+#else
+    tcg_gen_shri_i64(MAKE_TCGV_I64(GET_TCGV_I32(r)), fregs[reg], 32);
+#endif
     return r;
 }
 
@@ -212,39 +222,35 @@ static inline void store_reg(int reg, TCGv_i64 v)
 
 static inline void store_freg(int reg, TCGv_i64 v)
 {
-    tcg_gen_st_i64(v, cpu_env, offsetof(CPUS390XState, fregs[reg].d));
+    tcg_gen_mov_i64(fregs[reg], v);
 }
 
 static inline void store_reg32(int reg, TCGv_i32 v)
 {
+    /* 32 bit register writes keep the upper half */
 #if HOST_LONG_BITS == 32
     tcg_gen_mov_i32(TCGV_LOW(regs[reg]), v);
 #else
-    TCGv_i64 tmp = tcg_temp_new_i64();
-    tcg_gen_extu_i32_i64(tmp, v);
-    /* 32 bit register writes keep the upper half */
-    tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 32);
-    tcg_temp_free_i64(tmp);
+    tcg_gen_deposit_i64(regs[reg], regs[reg],
+                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 32);
 #endif
 }
 
 static inline void store_reg32_i64(int reg, TCGv_i64 v)
 {
     /* 32 bit register writes keep the upper half */
-#if HOST_LONG_BITS == 32
-    tcg_gen_mov_i32(TCGV_LOW(regs[reg]), TCGV_LOW(v));
-#else
     tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
-#endif
 }
 
 static inline void store_reg16(int reg, TCGv_i32 v)
 {
-    TCGv_i64 tmp = tcg_temp_new_i64();
-    tcg_gen_extu_i32_i64(tmp, v);
     /* 16 bit register writes keep the upper bytes */
-    tcg_gen_deposit_i64(regs[reg], regs[reg], tmp, 0, 16);
-    tcg_temp_free_i64(tmp);
+#if HOST_LONG_BITS == 32
+    tcg_gen_deposit_i32(TCGV_LOW(regs[reg]), TCGV_LOW(regs[reg]), v, 0, 16);
+#else
+    tcg_gen_deposit_i64(regs[reg], regs[reg],
+                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 0, 16);
+#endif
 }
 
 static inline void store_reg8(int reg, TCGv_i64 v)
@@ -255,7 +261,13 @@ static inline void store_reg8(int reg, TCGv_i64 v)
 
 static inline void store_freg32(int reg, TCGv_i32 v)
 {
-    tcg_gen_st_i32(v, cpu_env, offsetof(CPUS390XState, fregs[reg].l.upper));
+    /* 32 bit register writes keep the lower half */
+#if HOST_LONG_BITS == 32
+    tcg_gen_mov_i32(TCGV_HIGH(fregs[reg]), v);
+#else
+    tcg_gen_deposit_i64(fregs[reg], fregs[reg],
+                        MAKE_TCGV_I64(GET_TCGV_I32(v)), 32, 32);
+#endif
 }
 
 static inline void update_psw_addr(DisasContext *s)
commit 063eb0f3038434ab4cf9ad4bcc19a8789e15d237
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Aug 20 08:15:42 2012 -0700

    target-s390: Add missing temp_free in gen_op_calc_cc
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9e34741..f1e754f 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -757,6 +757,7 @@ static void gen_op_calc_cc(DisasContext *s)
     }
 
     tcg_temp_free_i32(local_cc_op);
+    tcg_temp_free_i64(dummy);
 
     /* We now have cc in cc_op as constant */
     set_cc_static(s);
commit 6ee77b16630bc86c1a44f9df61b072c7974ba503
Author: Richard Henderson <rth at twiddle.net>
Date:   Thu Aug 23 10:44:45 2012 -0700

    target-s390: Fix gdbstub
    
    The real gdb protocol doesn't split out pc or cc as real registers.
    Those are pseudos that are extracted as needed from the PSW.  Don't
    modify env->cc_op during read -- that way lies heisenbugs.
    
    Fill in the XXX for the fp registers.
    
    Remove duplicated defines in cpu.h.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/gdbstub.c b/gdbstub.c
index a8dd437..e62dc79 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -40,6 +40,7 @@
 #include "cpu.h"
 #include "qemu/sockets.h"
 #include "sysemu/kvm.h"
+#include "qemu/bitops.h"
 
 #ifndef TARGET_CPU_MEMORY_RW_DEBUG
 static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr,
@@ -1535,27 +1536,34 @@ static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
 }
 #elif defined (TARGET_S390X)
 
-#define NUM_CORE_REGS S390_NUM_TOTAL_REGS
+#define NUM_CORE_REGS  S390_NUM_REGS
 
 static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
 {
+    uint64_t val;
+    int cc_op;
+
     switch (n) {
-        case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break;
-        case S390_PSWA_REGNUM: GET_REGL(env->psw.addr); break;
-        case S390_R0_REGNUM ... S390_R15_REGNUM:
-            GET_REGL(env->regs[n-S390_R0_REGNUM]); break;
-        case S390_A0_REGNUM ... S390_A15_REGNUM:
-            GET_REG32(env->aregs[n-S390_A0_REGNUM]); break;
-        case S390_FPC_REGNUM: GET_REG32(env->fpc); break;
-        case S390_F0_REGNUM ... S390_F15_REGNUM:
-            /* XXX */
-            break;
-        case S390_PC_REGNUM: GET_REGL(env->psw.addr); break;
-        case S390_CC_REGNUM:
-            env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
-                                 env->cc_vr);
-            GET_REG32(env->cc_op);
-            break;
+    case S390_PSWM_REGNUM:
+        cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
+        val = deposit64(env->psw.mask, 44, 2, cc_op);
+        GET_REGL(val);
+        break;
+    case S390_PSWA_REGNUM:
+        GET_REGL(env->psw.addr);
+        break;
+    case S390_R0_REGNUM ... S390_R15_REGNUM:
+        GET_REGL(env->regs[n-S390_R0_REGNUM]);
+        break;
+    case S390_A0_REGNUM ... S390_A15_REGNUM:
+        GET_REG32(env->aregs[n-S390_A0_REGNUM]);
+        break;
+    case S390_FPC_REGNUM:
+        GET_REG32(env->fpc);
+        break;
+    case S390_F0_REGNUM ... S390_F15_REGNUM:
+        GET_REG64(env->fregs[n-S390_F0_REGNUM].ll);
+        break;
     }
 
     return 0;
@@ -1570,20 +1578,30 @@ static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
     tmp32 = ldl_p(mem_buf);
 
     switch (n) {
-        case S390_PSWM_REGNUM: env->psw.mask = tmpl; break;
-        case S390_PSWA_REGNUM: env->psw.addr = tmpl; break;
-        case S390_R0_REGNUM ... S390_R15_REGNUM:
-            env->regs[n-S390_R0_REGNUM] = tmpl; break;
-        case S390_A0_REGNUM ... S390_A15_REGNUM:
-            env->aregs[n-S390_A0_REGNUM] = tmp32; r=4; break;
-        case S390_FPC_REGNUM: env->fpc = tmp32; r=4; break;
-        case S390_F0_REGNUM ... S390_F15_REGNUM:
-            /* XXX */
-            break;
-        case S390_PC_REGNUM: env->psw.addr = tmpl; break;
-        case S390_CC_REGNUM: env->cc_op = tmp32; r=4; break;
+    case S390_PSWM_REGNUM:
+        env->psw.mask = tmpl;
+        env->cc_op = extract64(tmpl, 44, 2);
+        break;
+    case S390_PSWA_REGNUM:
+        env->psw.addr = tmpl;
+        break;
+    case S390_R0_REGNUM ... S390_R15_REGNUM:
+        env->regs[n-S390_R0_REGNUM] = tmpl;
+        break;
+    case S390_A0_REGNUM ... S390_A15_REGNUM:
+        env->aregs[n-S390_A0_REGNUM] = tmp32;
+        r = 4;
+        break;
+    case S390_FPC_REGNUM:
+        env->fpc = tmp32;
+        r = 4;
+        break;
+    case S390_F0_REGNUM ... S390_F15_REGNUM:
+        env->fregs[n-S390_F0_REGNUM].ll = tmpl;
+        break;
+    default:
+        return 0;
     }
-
     return r;
 }
 #elif defined (TARGET_LM32)
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index cd565c9..529716d 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -430,79 +430,6 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
 /* Total.  */
 #define S390_NUM_REGS 51
 
-/* Pseudo registers -- PC and condition code.  */
-#define S390_PC_REGNUM S390_NUM_REGS
-#define S390_CC_REGNUM (S390_NUM_REGS+1)
-#define S390_NUM_PSEUDO_REGS 2
-#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
-
-
-
-/* Program Status Word.  */
-#define S390_PSWM_REGNUM 0
-#define S390_PSWA_REGNUM 1
-/* General Purpose Registers.  */
-#define S390_R0_REGNUM 2
-#define S390_R1_REGNUM 3
-#define S390_R2_REGNUM 4
-#define S390_R3_REGNUM 5
-#define S390_R4_REGNUM 6
-#define S390_R5_REGNUM 7
-#define S390_R6_REGNUM 8
-#define S390_R7_REGNUM 9
-#define S390_R8_REGNUM 10
-#define S390_R9_REGNUM 11
-#define S390_R10_REGNUM 12
-#define S390_R11_REGNUM 13
-#define S390_R12_REGNUM 14
-#define S390_R13_REGNUM 15
-#define S390_R14_REGNUM 16
-#define S390_R15_REGNUM 17
-/* Access Registers.  */
-#define S390_A0_REGNUM 18
-#define S390_A1_REGNUM 19
-#define S390_A2_REGNUM 20
-#define S390_A3_REGNUM 21
-#define S390_A4_REGNUM 22
-#define S390_A5_REGNUM 23
-#define S390_A6_REGNUM 24
-#define S390_A7_REGNUM 25
-#define S390_A8_REGNUM 26
-#define S390_A9_REGNUM 27
-#define S390_A10_REGNUM 28
-#define S390_A11_REGNUM 29
-#define S390_A12_REGNUM 30
-#define S390_A13_REGNUM 31
-#define S390_A14_REGNUM 32
-#define S390_A15_REGNUM 33
-/* Floating Point Control Word.  */
-#define S390_FPC_REGNUM 34
-/* Floating Point Registers.  */
-#define S390_F0_REGNUM 35
-#define S390_F1_REGNUM 36
-#define S390_F2_REGNUM 37
-#define S390_F3_REGNUM 38
-#define S390_F4_REGNUM 39
-#define S390_F5_REGNUM 40
-#define S390_F6_REGNUM 41
-#define S390_F7_REGNUM 42
-#define S390_F8_REGNUM 43
-#define S390_F9_REGNUM 44
-#define S390_F10_REGNUM 45
-#define S390_F11_REGNUM 46
-#define S390_F12_REGNUM 47
-#define S390_F13_REGNUM 48
-#define S390_F14_REGNUM 49
-#define S390_F15_REGNUM 50
-/* Total.  */
-#define S390_NUM_REGS 51
-
-/* Pseudo registers -- PC and condition code.  */
-#define S390_PC_REGNUM S390_NUM_REGS
-#define S390_CC_REGNUM (S390_NUM_REGS+1)
-#define S390_NUM_PSEUDO_REGS 2
-#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2)
-
 /* CC optimization */
 
 enum cc_op {
commit 79be7c7b603f89da209098a03a5459beb09a579b
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Sep 1 14:13:12 2012 -0700

    target-s390: Fix disassembly of cpsdr
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/disas/s390.c b/disas/s390.c
index 73c4193..25499ba 100644
--- a/disas/s390.c
+++ b/disas/s390.c
@@ -673,7 +673,9 @@ static const struct s390_operand s390_operands[] =
    This is just a workaround for existing code e.g. glibc.  */
 #define INSTR_RRE_RR_OPT 4, { R_24,RO_28,0,0,0,0 }             /* efpc, sfpc */
 #define INSTR_RRF_F0FF   4, { F_16,F_24,F_28,0,0,0 }           /* e.g. madbr */
-#define INSTR_RRF_F0FF2  4, { F_24,F_16,F_28,0,0,0 }           /* e.g. cpsdr */
+/* QEMU-MOD */
+#define INSTR_RRF_F0FF2  4, { F_24,F_28,F_16,0,0,0 }           /* e.g. cpsdr */
+/* QEMU-END */
 #define INSTR_RRF_F0FR   4, { F_24,F_16,R_28,0,0,0 }           /* e.g. iedtr */
 #define INSTR_RRF_FUFF   4, { F_24,F_16,F_28,U4_20,0,0 }       /* e.g. didbr */
 #define INSTR_RRF_RURR   4, { R_24,R_28,R_16,U4_20,0,0 }       /* e.g. .insn */
commit 0fd81617fad2cae099348877099f6cf4c3bbc5bd
Author: Richard Henderson <rth at twiddle.net>
Date:   Fri Aug 31 12:49:47 2012 -0700

    target-s390: Disassemble more z10 and z196 opcodes
    
    Also fix disassembly for COMPARE AND BRANCH.  The table must be
    sorted by primary opcode, and several were out of place.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>

diff --git a/disas/s390.c b/disas/s390.c
index 0859dfa..73c4193 100644
--- a/disas/s390.c
+++ b/disas/s390.c
@@ -589,6 +589,16 @@ static const struct s390_operand s390_operands[] =
   { 4, 32, S390_OPERAND_CCODE },
 #define I8_32 46                  /* 8 bit signed value starting at 32 */
   { 8, 32, S390_OPERAND_SIGNED },
+#define U8_24 47                  /* 8 bit unsigned value starting at 24 */
+  { 8, 24, 0 },
+#define U8_32 48                  /* 8 bit unsigned value starting at 32 */
+  { 8, 32, 0 },
+#define I16_32 49
+  { 16, 32, S390_OPERAND_SIGNED },
+#define M4_16 50                  /* 4-bit condition-code starting at 12 */
+  { 4, 16, S390_OPERAND_CCODE },
+#define I8_16 51
+  { 8, 16, S390_OPERAND_SIGNED },
 /* QEMU-END */
 };
 
@@ -801,11 +811,35 @@ static const struct s390_operand s390_operands[] =
 #define MASK_SSF_RRDRD   { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
 
 /* QEMU-ADD: */
-#define INSTR_RIE_MRRP   6, { M4_32,R_8,R_12,J16_16,0,0 }	/* e.g. crj */
+#define INSTR_RIE_MRRP   6, { M4_32, R_8, R_12, J16_16, 0, 0 } /* e.g. crj */
 #define MASK_RIE_MRRP    { 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff }
 
-#define INSTR_RIE_MRIP   6, { M4_12,R_8,I8_32,J16_16,0,0 }      /* e.g. cij */
+#define INSTR_RIE_MRIP   6, { M4_12, R_8, I8_32, J16_16, 0, 0 } /* e.g. cij */
 #define MASK_RIE_MRIP    { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RIE_RRIII  6, { R_8, R_12, U8_16, U8_24, U8_32, 0 } /* risbg */
+#define MASK_RIE_RRIII   { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_MRI    6, { M4_32, R_8, I16_16, 0, 0, 0 }    /* e.g. cit */
+#define MASK_RIE_MRI     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_MRU    6, { M4_32, R_8, U16_16, 0, 0, 0 }    /* e.g. clfit */
+#define MASK_RIE_MRU     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+#define INSTR_RIE_RRI    6, { R_8, R_12, I16_16, 0, 0, 0 }
+#define MASK_RIE_RRI     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RXY_URRD   6, { U8_8, D20_20, X_12, B_16, 0, 0 }
+#define MASK_RXY_URRD    { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_SIL_DRI    6, { D_20, B_16, I16_32, 0, 0, 0 }
+#define MASK_SIL_DRI     { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+
+#define INSTR_RSY_MRRD   6, { M4_12, R_8, D20_20, B_16, 0, 0 }
+#define MASK_SRY_MRRD    { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+
+#define INSTR_RRF_MRR    6, { M4_16, R_24, R_28, 0, 0, 0 }
+#define MASK_RRF_MRR     { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+
+#define INSTR_SIY_DRI    6, { D20_20, B_16, I8_16, 0, 0, 0 }
+#define MASK_SIY_DRI     { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
 /* QEMU-END */
 
 /* The opcode formats table (blueprints for .insn pseudo mnemonic).  */
@@ -926,6 +960,30 @@ static const struct s390_opcode s390_opcodes[] =
   { "ldeb", OP48(0xed0000000004LL), MASK_RXE_FRRD, INSTR_RXE_FRRD, 3, 0},
   { "brxlg", OP48(0xec0000000045LL), MASK_RIE_RRP, INSTR_RIE_RRP, 2, 2},
   { "brxhg", OP48(0xec0000000044LL), MASK_RIE_RRP, INSTR_RIE_RRP, 2, 2},
+/* QEMU-ADD: */
+  { "crj",   OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "cgrj",  OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "clrj",  OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+  { "cij",   OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "cgij",  OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "clij",  OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+  { "risbg", OP48(0xec0000000055LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "risbhg", OP48(0xec000000005dLL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "risblg", OP48(0xec0000000051LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "rnsbg", OP48(0xec0000000054LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "rosbg", OP48(0xec0000000056LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "rxsbg", OP48(0xec0000000057LL), MASK_RIE_RRIII, INSTR_RIE_RRIII, 3, 6},
+  { "cit", OP48(0xec0000000072LL), MASK_RIE_MRI, INSTR_RIE_MRI, 3, 6},
+  { "cgit", OP48(0xec0000000070LL), MASK_RIE_MRI, INSTR_RIE_MRI, 3, 6},
+  { "clfit", OP48(0xec0000000073LL), MASK_RIE_MRU, INSTR_RIE_MRU, 3, 6},
+  { "clgit", OP48(0xec0000000071LL), MASK_RIE_MRU, INSTR_RIE_MRU, 3, 6},
+  { "ahik", OP48(0xec00000000d8LL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+  { "aghik", OP48(0xec00000000d9LL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+  { "alhsik", OP48(0xec00000000daLL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+  { "alghsik", OP48(0xec00000000dbLL), MASK_RIE_RRI, INSTR_RIE_RRI, 3, 6},
+/* QEMU-END */
   { "tp", OP48(0xeb00000000c0LL), MASK_RSL_R0RD, INSTR_RSL_R0RD, 3, 0},
   { "stamy", OP48(0xeb000000009bLL), MASK_RSY_AARD, INSTR_RSY_AARD, 2, 3},
   { "lamy", OP48(0xeb000000009aLL), MASK_RSY_AARD, INSTR_RSY_AARD, 2, 3},
@@ -985,6 +1043,20 @@ static const struct s390_opcode s390_opcodes[] =
   { "srag", OP48(0xeb000000000aLL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 2, 2},
   { "lmg", OP48(0xeb0000000004LL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 2, 3},
   { "lmg", OP48(0xeb0000000004LL), MASK_RSE_RRRD, INSTR_RSE_RRRD, 2, 2},
+/* QEMU-ADD: */
+  { "loc", OP48(0xeb00000000f2LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+  { "locg", OP48(0xeb00000000e2LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+  { "stoc", OP48(0xeb00000000f3LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+  { "stocg", OP48(0xeb00000000e3LL), MASK_SRY_MRRD, INSTR_RSY_MRRD, 3, 6},
+  { "srak", OP48(0xeb00000000dcLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+  { "slak", OP48(0xeb00000000ddLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+  { "srlk", OP48(0xeb00000000deLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+  { "sllk", OP48(0xeb00000000dfLL), MASK_RSY_RRRD, INSTR_RSY_RRRD, 3, 6},
+  { "asi", OP48(0xeb000000006aLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+  { "alsi", OP48(0xeb000000006eLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+  { "agsi", OP48(0xeb000000007aLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+  { "algsi", OP48(0xeb000000007eLL), MASK_SIY_DRI, INSTR_SIY_DRI, 3, 6},
+/* QEMU-END */
   { "unpka", OP8(0xeaLL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
   { "pka", OP8(0xe9LL), MASK_SS_L2RDRD, INSTR_SS_L2RDRD, 3, 0},
   { "mvcin", OP8(0xe8LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
@@ -993,6 +1065,17 @@ static const struct s390_opcode s390_opcodes[] =
   { "tprot", OP16(0xe501LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0},
   { "strag", OP48(0xe50000000002LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 2, 2},
   { "lasp", OP16(0xe500LL), MASK_SSE_RDRD, INSTR_SSE_RDRD, 3, 0},
+/* QEMU-ADD: */
+  { "mvhhi", OP16(0xe544LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "mvghi", OP16(0xe548LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "mvhi", OP16(0xe54cLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "chhsi", OP16(0xe554LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "clhhsi", OP16(0xe555LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "cghsi", OP16(0xe558LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "clghsi", OP16(0xe559LL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "chsi", OP16(0xe55cLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+  { "clfhsi", OP16(0xe55dLL), MASK_SIL_DRI, INSTR_SIL_DRI, 3, 6},
+/* QEMU-END */
   { "slb", OP48(0xe30000000099LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3},
   { "slb", OP48(0xe30000000099LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 3, 2},
   { "alc", OP48(0xe30000000098LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 3, 3},
@@ -1116,6 +1199,9 @@ static const struct s390_opcode s390_opcodes[] =
   { "lrag", OP48(0xe30000000003LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 2, 3},
   { "lrag", OP48(0xe30000000003LL), MASK_RXE_RRRD, INSTR_RXE_RRRD, 2, 2},
   { "ltg", OP48(0xe30000000002LL), MASK_RXY_RRRD, INSTR_RXY_RRRD, 2, 4},
+/* QEMU-ADD: */
+  { "pfd", OP48(0xe30000000036LL), MASK_RXY_URRD, INSTR_RXY_URRD, 3, 6},
+/* QEMU-END */
   { "unpku", OP8(0xe2LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
   { "pku", OP8(0xe1LL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
   { "edmk", OP8(0xdfLL), MASK_SS_L0RDRD, INSTR_SS_L0RDRD, 3, 0},
@@ -1135,6 +1221,32 @@ static const struct s390_opcode s390_opcodes[] =
   { "csst", OP16(0xc802LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 5},
   { "ectg", OP16(0xc801LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 5},
   { "mvcos", OP16(0xc800LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD, 2, 4},
+/* QEMU-ADD: */
+  { "exrl", OP16(0xc600ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "pfdrl", OP16(0xc602ll), MASK_RIL_UP, INSTR_RIL_UP, 3, 6},
+  { "cghrl", OP16(0xc604ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "chrl", OP16(0xc605ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "clghrl", OP16(0xc606ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "clhrl", OP16(0xc607ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "cgrl", OP16(0xc608ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "clgrl", OP16(0xc60all), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "cgfrl", OP16(0xc60cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "crl", OP16(0xc60dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "clgfrl", OP16(0xc60ell), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "clrl", OP16(0xc60fll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+
+  { "llhrl", OP16(0xc400ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lghrl", OP16(0xc404ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lhrl", OP16(0xc405ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "llghrl", OP16(0xc406ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "sthrl", OP16(0xc407ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lgrl", OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "stgrl", OP16(0xc40bll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "lrl", OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "llgfrl", OP16(0xc40ell), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+  { "strl", OP16(0xc40fll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+/* QEMU-END */
   { "clfi", OP16(0xc20fLL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
   { "clgfi", OP16(0xc20eLL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
   { "cfi", OP16(0xc20dLL), MASK_RIL_RI, INSTR_RIL_RI, 2, 4},
@@ -1265,6 +1377,29 @@ static const struct s390_opcode s390_opcodes[] =
   { "ltgr", OP16(0xb902LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
   { "lngr", OP16(0xb901LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
   { "lpgr", OP16(0xb900LL), MASK_RRE_RR, INSTR_RRE_RR, 2, 2},
+/* QEMU-ADD: */
+  { "crt", OP16(0xb972LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+  { "cgrt", OP16(0xb960LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+  { "clrt", OP16(0xb973LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+  { "clgrt", OP16(0xb961LL), MASK_RRF_M0RR, INSTR_RRF_M0RR, 3, 6},
+  { "locr", OP16(0xb9f2LL), MASK_RRF_MRR, INSTR_RRF_MRR, 3, 6},
+  { "locgr", OP16(0xb9e2LL), MASK_RRF_MRR, INSTR_RRF_MRR, 3, 6},
+  { "popcnt", OP16(0xb9e1LL), MASK_RRE_RR, INSTR_RRE_RR, 3, 6},
+  { "ngrk", OP16(0xb9e4LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "ogrk", OP16(0xb9e6LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "xgrk", OP16(0xb9e7LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "agrk", OP16(0xb9e8LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "sgrk", OP16(0xb9e9LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "algrk", OP16(0xb9eaLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "slgrk", OP16(0xb9ebLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "nrk", OP16(0xb9f4LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "ork", OP16(0xb9f6LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "xrk", OP16(0xb9f7LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "ark", OP16(0xb9f8LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "srk", OP16(0xb9f9LL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "alrk", OP16(0xb9faLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+  { "slrk", OP16(0xb9fbLL), MASK_RRF_R0RR, INSTR_RRF_R0RR, 3, 6},
+/* QEMU-END */
   { "lctl", OP8(0xb7LL), MASK_RS_CCRD, INSTR_RS_CCRD, 3, 0},
   { "stctl", OP8(0xb6LL), MASK_RS_CCRD, INSTR_RS_CCRD, 3, 0},
   { "rrxtr", OP16(0xb3ffLL), MASK_RRF_FFFU, INSTR_RRF_FFFU, 2, 5},
@@ -1426,6 +1561,20 @@ static const struct s390_opcode s390_opcodes[] =
   { "ltebr", OP16(0xb302LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
   { "lnebr", OP16(0xb301LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
   { "lpebr", OP16(0xb300LL), MASK_RRE_FF, INSTR_RRE_FF, 3, 0},
+/* QEMU-ADD: */
+  { "clfebr", OP16(0xb39cLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "clfdbr", OP16(0xb39dLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "clfxbr", OP16(0xb39eLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "clgebr", OP16(0xb3acLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "clgdbr", OP16(0xb3adLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "clgxbr", OP16(0xb3aeLL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "celfbr", OP16(0xb390LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "cdlfbr", OP16(0xb391LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "cxlfbr", OP16(0xb392LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "celgbr", OP16(0xb3a0LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "cdlgbr", OP16(0xb3a1LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+  { "cxlgbr", OP16(0xb3a2LL), MASK_RRF_UUFF, INSTR_RRF_UUFF, 3, 6},
+/* QEMU-END */
   { "trap4", OP16(0xb2ffLL), MASK_S_RD, INSTR_S_RD, 3, 0},
   { "lfas", OP16(0xb2bdLL), MASK_S_RD, INSTR_S_RD, 2, 5},
   { "srnmt", OP16(0xb2b9LL), MASK_S_RD, INSTR_S_RD, 2, 5},
@@ -1774,22 +1923,6 @@ static const struct s390_opcode s390_opcodes[] =
   { "sckpf", OP16(0x0107LL), MASK_E, INSTR_E, 3, 0},
   { "upt", OP16(0x0102LL), MASK_E, INSTR_E, 3, 0},
   { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0},
-
-/* QEMU-ADD: */
-  { "crj",   OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
-  { "cgrj",  OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
-  { "clrj",  OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
-  { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
-
-  { "cij",   OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
-  { "cgij",  OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
-  { "clij",  OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
-  { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
-
-  { "lrl",   OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
-  { "lgrl",  OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
-  { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
-/* QEMU-END */
 };
 
 static const int s390_num_opcodes =
commit 52a71bff6085398fbb8602718af228cd6339c02d
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sat Apr 14 22:48:36 2012 +0200

    prep: Use pc87312 device instead of collection of random ISA devices
    
    We can't however replace the built-in IDE controller, as the one in
    pc87312 is only single-channel and can use only IRQ 14. Therefore the
    pc87312's IDE function gets disabled via the config property.
    
    PReP emulation also gains a parallel port emulation this way.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    [AF: Use TYPE_PC87312 constant, add to ppc64-softmmu and to MAINTAINERS]
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>

diff --git a/MAINTAINERS b/MAINTAINERS
index 6d864c1..950270f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -373,6 +373,7 @@ L: qemu-ppc at nongnu.org
 S: Odd Fixes
 F: hw/ppc_prep.c
 F: hw/prep_pci.[hc]
+F: hw/pc87312.[hc]
 
 SH4 Machines
 ------------
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index d0fde7b..1f4a1cf 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_M48T59=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
 CONFIG_SERIAL=y
+CONFIG_PARALLEL=y
 CONFIG_I8254=y
 CONFIG_PCKBD=y
 CONFIG_FDC=y
@@ -16,6 +17,7 @@ CONFIG_I82374=y
 CONFIG_OPENPIC=y
 CONFIG_PREP_PCI=y
 CONFIG_I82378=y
+CONFIG_PC87312=y
 CONFIG_MACIO=y
 CONFIG_PCSPK=y
 CONFIG_CUDA=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index a1d2d4f..5ff406c 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_M48T59=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
 CONFIG_SERIAL=y
+CONFIG_PARALLEL=y
 CONFIG_I8254=y
 CONFIG_PCKBD=y
 CONFIG_FDC=y
@@ -16,6 +17,7 @@ CONFIG_I82374=y
 CONFIG_OPENPIC=y
 CONFIG_PREP_PCI=y
 CONFIG_I82378=y
+CONFIG_PC87312=y
 CONFIG_MACIO=y
 CONFIG_PCSPK=y
 CONFIG_CUDA=y
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index be2b268..59def90 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -36,6 +36,7 @@
 #include "ide.h"
 #include "loader.h"
 #include "mc146818rtc.h"
+#include "pc87312.h"
 #include "blockdev.h"
 #include "arch_init.h"
 #include "exec-memory.h"
@@ -180,7 +181,6 @@ typedef struct sysctrl_t {
     M48t59State *nvram;
     uint8_t state;
     uint8_t syscontrol;
-    uint8_t fake_io[2];
     int contiguous_map;
     int endian;
 } sysctrl_t;
@@ -191,24 +191,6 @@ enum {
 
 static sysctrl_t *sysctrl;
 
-static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
-{
-    sysctrl_t *sysctrl = opaque;
-
-    PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
-                   val);
-    sysctrl->fake_io[addr - 0x0398] = val;
-}
-
-static uint32_t PREP_io_read (void *opaque, uint32_t addr)
-{
-    sysctrl_t *sysctrl = opaque;
-
-    PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n", addr - PPC_IO_BASE,
-                   sysctrl->fake_io[addr - 0x0398]);
-    return sysctrl->fake_io[addr - 0x0398];
-}
-
 static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
 {
     sysctrl_t *sysctrl = opaque;
@@ -475,10 +457,10 @@ static void ppc_prep_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     PCIDevice *pci;
     ISABus *isa_bus;
+    ISADevice *isa;
     qemu_irq *cpu_exit_irq;
     int ppc_boot_device;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    DriveInfo *fd[MAX_FD];
 
     sysctrl = g_malloc0(sizeof(sysctrl_t));
 
@@ -606,6 +588,11 @@ static void ppc_prep_init (ram_addr_t ram_size,
     sysbus_connect_irq(&pcihost->busdev, 3, qdev_get_gpio_in(&pci->qdev, 11));
     isa_bus = DO_UPCAST(ISABus, qbus, qdev_get_child_bus(&pci->qdev, "isa.0"));
 
+    /* Super I/O (parallel + serial ports) */
+    isa = isa_create(isa_bus, TYPE_PC87312);
+    qdev_prop_set_uint8(&isa->qdev, "config", 13); /* fdc, ser0, ser1, par0 */
+    qdev_init_nofail(&isa->qdev);
+
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
     memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl,
                           "ppc-io", 0x00800000);
@@ -614,8 +601,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
     /* init basic PC hardware */
     pci_vga_init(pci_bus);
 
-    if (serial_hds[0])
-        serial_isa_init(isa_bus, 0, serial_hds[0]);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
@@ -639,17 +624,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
     isa_create_simple(isa_bus, "i8042");
 
-    //    SB16_init();
-
-    for(i = 0; i < MAX_FD; i++) {
-        fd[i] = drive_get(IF_FLOPPY, 0, i);
-    }
-    fdctrl_init_isa(isa_bus, fd);
-
-    /* Register fake IO ports for PREP */
     sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET];
-    register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
-    register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
     /* System control ports */
     register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
     register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
commit 1ae41f447d1467172b0f8290ca1b83726ea9942a
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sat Apr 14 22:48:35 2012 +0200

    prep: Add pc87312 Super I/O emulation
    
    This provides floppy and IDE controllers as well as serial and parallel
    ports. However, dynamic configuration of devices is not yet supported.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    [AF: QOM'ify, split out header, create CharDriverState if absent]
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 7f57ed5..aab0a46 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -39,6 +39,7 @@ hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
 # PPC devices
 hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
 hw-obj-$(CONFIG_I82378) += i82378.o
+hw-obj-$(CONFIG_PC87312) += pc87312.o
 # Mac shared devices
 hw-obj-$(CONFIG_MACIO) += macio.o
 hw-obj-$(CONFIG_CUDA) += cuda.o
diff --git a/hw/pc87312.c b/hw/pc87312.c
new file mode 100644
index 0000000..b5fa016
--- /dev/null
+++ b/hw/pc87312.c
@@ -0,0 +1,386 @@
+/*
+ * QEMU National Semiconductor PC87312 (Super I/O)
+ *
+ * Copyright (c) 2010-2012 Herve Poussineau
+ * Copyright (c) 2011-2012 Andreas Färber
+ *
+ * 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 "pc87312.h"
+#include "blockdev.h"
+#include "sysemu.h"
+#include "trace.h"
+
+
+#define REG_FER 0
+#define REG_FAR 1
+#define REG_PTR 2
+
+#define FER regs[REG_FER]
+#define FAR regs[REG_FAR]
+#define PTR regs[REG_PTR]
+
+#define FER_PARALLEL_EN   0x01
+#define FER_UART1_EN      0x02
+#define FER_UART2_EN      0x04
+#define FER_FDC_EN        0x08
+#define FER_FDC_4         0x10
+#define FER_FDC_ADDR      0x20
+#define FER_IDE_EN        0x40
+#define FER_IDE_ADDR      0x80
+
+#define FAR_PARALLEL_ADDR 0x03
+#define FAR_UART1_ADDR    0x0C
+#define FAR_UART2_ADDR    0x30
+#define FAR_UART_3_4      0xC0
+
+#define PTR_POWER_DOWN    0x01
+#define PTR_CLOCK_DOWN    0x02
+#define PTR_PWDN          0x04
+#define PTR_IRQ_5_7       0x08
+#define PTR_UART1_TEST    0x10
+#define PTR_UART2_TEST    0x20
+#define PTR_LOCK_CONF     0x40
+#define PTR_EPP_MODE      0x80
+
+
+/* Parallel port */
+
+static inline bool is_parallel_enabled(PC87312State *s)
+{
+    return s->FER & FER_PARALLEL_EN;
+}
+
+static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 };
+
+static inline uint32_t get_parallel_iobase(PC87312State *s)
+{
+    return parallel_base[s->FAR & FAR_PARALLEL_ADDR];
+}
+
+static const uint32_t parallel_irq[] = { 5, 7, 5, 0 };
+
+static inline uint32_t get_parallel_irq(PC87312State *s)
+{
+    int idx;
+    idx = (s->FAR & FAR_PARALLEL_ADDR);
+    if (idx == 0) {
+        return (s->PTR & PTR_IRQ_5_7) ? 7 : 5;
+    } else {
+        return parallel_irq[idx];
+    }
+}
+
+static inline bool is_parallel_epp(PC87312State *s)
+{
+    return s->PTR & PTR_EPP_MODE;
+}
+
+
+/* UARTs */
+
+static const uint32_t uart_base[2][4] = {
+    { 0x3e8, 0x338, 0x2e8, 0x220 },
+    { 0x2e8, 0x238, 0x2e0, 0x228 }
+};
+
+static inline uint32_t get_uart_iobase(PC87312State *s, int i)
+{
+    int idx;
+    idx = (s->FAR >> (2 * i + 2)) & 0x3;
+    if (idx == 0) {
+        return 0x3f8;
+    } else if (idx == 1) {
+        return 0x2f8;
+    } else {
+        return uart_base[idx & 1][(s->FAR & FAR_UART_3_4) >> 6];
+    }
+}
+
+static inline uint32_t get_uart_irq(PC87312State *s, int i)
+{
+    int idx;
+    idx = (s->FAR >> (2 * i + 2)) & 0x3;
+    return (idx & 1) ? 3 : 4;
+}
+
+static inline bool is_uart_enabled(PC87312State *s, int i)
+{
+    return s->FER & (FER_UART1_EN << i);
+}
+
+
+/* Floppy controller */
+
+static inline bool is_fdc_enabled(PC87312State *s)
+{
+    return s->FER & FER_FDC_EN;
+}
+
+static inline uint32_t get_fdc_iobase(PC87312State *s)
+{
+    return (s->FER & FER_FDC_ADDR) ? 0x370 : 0x3f0;
+}
+
+
+/* IDE controller */
+
+static inline bool is_ide_enabled(PC87312State *s)
+{
+    return s->FER & FER_IDE_EN;
+}
+
+static inline uint32_t get_ide_iobase(PC87312State *s)
+{
+    return (s->FER & FER_IDE_ADDR) ? 0x170 : 0x1f0;
+}
+
+
+static void reconfigure_devices(PC87312State *s)
+{
+    error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)",
+                 s->FER, s->FAR, s->PTR);
+}
+
+static void pc87312_soft_reset(PC87312State *s)
+{
+    static const uint8_t fer_init[] = {
+        0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4b, 0x4b,
+        0x4b, 0x4b, 0x4b, 0x4b, 0x0f, 0x0f, 0x0f, 0x0f,
+        0x49, 0x49, 0x49, 0x49, 0x07, 0x07, 0x07, 0x07,
+        0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x08, 0x00,
+    };
+    static const uint8_t far_init[] = {
+        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x00, 0x01,
+        0x01, 0x09, 0x08, 0x08, 0x10, 0x11, 0x39, 0x24,
+        0x00, 0x01, 0x01, 0x00, 0x10, 0x11, 0x39, 0x24,
+        0x10, 0x11, 0x11, 0x39, 0x24, 0x38, 0x10, 0x10,
+    };
+    static const uint8_t ptr_init[] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+    };
+
+    s->read_id_step = 0;
+    s->selected_index = REG_FER;
+
+    s->FER = fer_init[s->config & 0x1f];
+    s->FAR = far_init[s->config & 0x1f];
+    s->PTR = ptr_init[s->config & 0x1f];
+}
+
+static void pc87312_hard_reset(PC87312State *s)
+{
+    pc87312_soft_reset(s);
+}
+
+static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    PC87312State *s = opaque;
+
+    trace_pc87312_io_write(addr, val);
+
+    if ((addr & 1) == 0) {
+        /* Index register */
+        s->read_id_step = 2;
+        s->selected_index = val;
+    } else {
+        /* Data register */
+        if (s->selected_index < 3) {
+            s->regs[s->selected_index] = val;
+            reconfigure_devices(s);
+        }
+    }
+}
+
+static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr)
+{
+    PC87312State *s = opaque;
+    uint32_t val;
+
+    if ((addr & 1) == 0) {
+        /* Index register */
+        if (s->read_id_step++ == 0) {
+            val = 0x88;
+        } else if (s->read_id_step++ == 1) {
+            val = 0;
+        } else {
+            val = s->selected_index;
+        }
+    } else {
+        /* Data register */
+        if (s->selected_index < 3) {
+            val = s->regs[s->selected_index];
+        } else {
+            /* Invalid selected index */
+            val = 0;
+        }
+    }
+
+    trace_pc87312_io_read(addr, val);
+    return val;
+}
+
+static int pc87312_post_load(void *opaque, int version_id)
+{
+    PC87312State *s = opaque;
+
+    reconfigure_devices(s);
+    return 0;
+}
+
+static void pc87312_reset(DeviceState *d)
+{
+    PC87312State *s = PC87312(d);
+
+    pc87312_soft_reset(s);
+}
+
+static int pc87312_init(ISADevice *dev)
+{
+    PC87312State *s;
+    DeviceState *d;
+    ISADevice *isa;
+    ISABus *bus;
+    CharDriverState *chr;
+    DriveInfo *drive;
+    char name[5];
+    int i;
+
+    s = PC87312(dev);
+    bus = isa_bus_from_device(dev);
+    pc87312_hard_reset(s);
+
+    if (is_parallel_enabled(s)) {
+        chr = parallel_hds[0];
+        if (chr == NULL) {
+            chr = qemu_chr_new("par0", "null", NULL);
+        }
+        isa = isa_create(bus, "isa-parallel");
+        d = DEVICE(isa);
+        qdev_prop_set_uint32(d, "index", 0);
+        qdev_prop_set_uint32(d, "iobase", get_parallel_iobase(s));
+        qdev_prop_set_uint32(d, "irq", get_parallel_irq(s));
+        qdev_prop_set_chr(d, "chardev", chr);
+        qdev_init_nofail(d);
+        s->parallel.dev = isa;
+        trace_pc87312_info_parallel(get_parallel_iobase(s),
+                                    get_parallel_irq(s));
+    }
+
+    for (i = 0; i < 2; i++) {
+        if (is_uart_enabled(s, i)) {
+            chr = serial_hds[i];
+            if (chr == NULL) {
+                snprintf(name, sizeof(name), "ser%d", i);
+                chr = qemu_chr_new(name, "null", NULL);
+            }
+            isa = isa_create(bus, "isa-serial");
+            d = DEVICE(isa);
+            qdev_prop_set_uint32(d, "index", i);
+            qdev_prop_set_uint32(d, "iobase", get_uart_iobase(s, i));
+            qdev_prop_set_uint32(d, "irq", get_uart_irq(s, i));
+            qdev_prop_set_chr(d, "chardev", chr);
+            qdev_init_nofail(d);
+            s->uart[i].dev = isa;
+            trace_pc87312_info_serial(i, get_uart_iobase(s, i),
+                                      get_uart_irq(s, i));
+        }
+    }
+
+    if (is_fdc_enabled(s)) {
+        isa = isa_create(bus, "isa-fdc");
+        d = DEVICE(isa);
+        qdev_prop_set_uint32(d, "iobase", get_fdc_iobase(s));
+        qdev_prop_set_uint32(d, "irq", 6);
+        drive = drive_get(IF_FLOPPY, 0, 0);
+        if (drive != NULL) {
+            qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
+        }
+        drive = drive_get(IF_FLOPPY, 0, 1);
+        if (drive != NULL) {
+            qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
+        }
+        qdev_init_nofail(d);
+        s->fdc.dev = isa;
+        trace_pc87312_info_floppy(get_fdc_iobase(s));
+    }
+
+    if (is_ide_enabled(s)) {
+        isa = isa_create(bus, "isa-ide");
+        d = DEVICE(isa);
+        qdev_prop_set_uint32(d, "iobase", get_ide_iobase(s));
+        qdev_prop_set_uint32(d, "iobase2", get_ide_iobase(s) + 0x206);
+        qdev_prop_set_uint32(d, "irq", 14);
+        qdev_init_nofail(d);
+        s->ide.dev = isa;
+        trace_pc87312_info_ide(get_ide_iobase(s));
+    }
+
+    register_ioport_write(s->iobase, 2, 1, pc87312_ioport_write, s);
+    register_ioport_read(s->iobase, 2, 1, pc87312_ioport_read, s);
+    return 0;
+}
+
+static const VMStateDescription vmstate_pc87312 = {
+    .name = "pc87312",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = pc87312_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(read_id_step, PC87312State),
+        VMSTATE_UINT8(selected_index, PC87312State),
+        VMSTATE_UINT8_ARRAY(regs, PC87312State, 3),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property pc87312_properties[] = {
+    DEFINE_PROP_HEX32("iobase", PC87312State, iobase, 0x398),
+    DEFINE_PROP_UINT8("config", PC87312State, config, 1),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void pc87312_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
+
+    ic->init = pc87312_init;
+    dc->reset = pc87312_reset;
+    dc->vmsd = &vmstate_pc87312;
+    dc->props = pc87312_properties;
+}
+
+static const TypeInfo pc87312_type_info = {
+    .name          = TYPE_PC87312,
+    .parent        = TYPE_ISA_DEVICE,
+    .instance_size = sizeof(PC87312State),
+    .class_init    = pc87312_class_init,
+};
+
+static void pc87312_register_types(void)
+{
+    type_register_static(&pc87312_type_info);
+}
+
+type_init(pc87312_register_types)
diff --git a/hw/pc87312.h b/hw/pc87312.h
new file mode 100644
index 0000000..7ca7912
--- /dev/null
+++ b/hw/pc87312.h
@@ -0,0 +1,66 @@
+/*
+ * QEMU National Semiconductor PC87312 (Super I/O)
+ *
+ * Copyright (c) 2010-2012 Herve Poussineau
+ * Copyright (c) 2011-2012 Andreas Färber
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_PC87312_H
+#define QEMU_PC87312_H
+
+#include "isa.h"
+
+
+#define TYPE_PC87312 "pc87312"
+#define PC87312(obj) OBJECT_CHECK(PC87312State, (obj), TYPE_PC87312)
+
+typedef struct PC87312State {
+    ISADevice dev;
+
+    uint32_t iobase;
+    uint8_t config; /* initial configuration */
+
+    struct {
+        ISADevice *dev;
+    } parallel;
+
+    struct {
+        ISADevice *dev;
+    } uart[2];
+
+    struct {
+        ISADevice *dev;
+        BlockDriverState *drive[2];
+        uint32_t base;
+    } fdc;
+
+    struct {
+        ISADevice *dev;
+        uint32_t base;
+    } ide;
+
+    uint8_t read_id_step;
+    uint8_t selected_index;
+
+    uint8_t regs[3];
+} PC87312State;
+
+
+#endif
diff --git a/trace-events b/trace-events
index 6b12f83..b4ca0e9 100644
--- a/trace-events
+++ b/trace-events
@@ -694,6 +694,14 @@ mipsnet_read(uint64_t addr, uint32_t val) "read addr=0x%" PRIx64 " val=0x%x"
 mipsnet_write(uint64_t addr, uint64_t val) "write addr=0x%" PRIx64 " val=0x%" PRIx64 ""
 mipsnet_irq(uint32_t isr, uint32_t intctl) "set irq to %d (%02x)"
 
+# hw/pc87312.c
+pc87312_io_read(uint32_t addr, uint32_t val) "read addr=%x val=%x"
+pc87312_io_write(uint32_t addr, uint32_t val) "write addr=%x val=%x"
+pc87312_info_floppy(uint32_t base) "base 0x%x"
+pc87312_info_ide(uint32_t base) "base 0x%x"
+pc87312_info_parallel(uint32_t base, uint32_t irq) "base 0x%x, irq %u"
+pc87312_info_serial(int n, uint32_t base, uint32_t irq) "id=%d, base 0x%x, irq %u"
+
 # xen-all.c
 xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx"
 xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i"
commit acbb090b2400f627a801074c4e3e006c7501bb26
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Wed Aug 15 14:15:41 2012 +0200

    prep: Include devices for ppc64 as well
    
    Allows running qemu-system-ppc64 -M prep for consistency.
    
    Reported-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Acked-by: Hervé Poussineau <hpoussineau at reactos.org>

diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index e4265b4..a1d2d4f 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -12,9 +12,12 @@ CONFIG_I8254=y
 CONFIG_PCKBD=y
 CONFIG_FDC=y
 CONFIG_DMA=y
+CONFIG_I82374=y
 CONFIG_OPENPIC=y
 CONFIG_PREP_PCI=y
+CONFIG_I82378=y
 CONFIG_MACIO=y
+CONFIG_PCSPK=y
 CONFIG_CUDA=y
 CONFIG_ADB=y
 CONFIG_MAC_NVRAM=y


More information about the Spice-commits mailing list