r1948 - in trunk/src/host/qemu-neo1973: . audio darwin-user fpu hw keymaps linux-user linux-user/alpha linux-user/i386 linux-user/mips linux-user/ppc linux-user/ppc64 linux-user/x86_64 openmoko pc-bios slirp target-alpha target-arm target-i386 target-m68k target-mips target-ppc target-sh4 target-sparc tests

andrew at sita.openmoko.org andrew at sita.openmoko.org
Sat May 12 01:47:21 CEST 2007


Author: andrew
Date: 2007-05-12 01:44:50 +0200 (Sat, 12 May 2007)
New Revision: 1948

Added:
   trunk/src/host/qemu-neo1973/arm-semi.c
   trunk/src/host/qemu-neo1973/darwin-user/
   trunk/src/host/qemu-neo1973/darwin-user/commpage.c
   trunk/src/host/qemu-neo1973/darwin-user/ioctls.h
   trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h
   trunk/src/host/qemu-neo1973/darwin-user/machload.c
   trunk/src/host/qemu-neo1973/darwin-user/main.c
   trunk/src/host/qemu-neo1973/darwin-user/mmap.c
   trunk/src/host/qemu-neo1973/darwin-user/qemu.h
   trunk/src/host/qemu-neo1973/darwin-user/signal.c
   trunk/src/host/qemu-neo1973/darwin-user/syscall.c
   trunk/src/host/qemu-neo1973/darwin-user/syscalls.h
   trunk/src/host/qemu-neo1973/hostregs_helper.h
   trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
   trunk/src/host/qemu-neo1973/hw/ds1225y.c
   trunk/src/host/qemu-neo1973/hw/eepro100.c
   trunk/src/host/qemu-neo1973/hw/eeprom93xx.c
   trunk/src/host/qemu-neo1973/hw/eeprom93xx.h
   trunk/src/host/qemu-neo1973/hw/gt64xxx.c
   trunk/src/host/qemu-neo1973/hw/i2c.c
   trunk/src/host/qemu-neo1973/hw/irq.c
   trunk/src/host/qemu-neo1973/hw/irq.h
   trunk/src/host/qemu-neo1973/hw/mips_int.c
   trunk/src/host/qemu-neo1973/hw/mips_malta.c
   trunk/src/host/qemu-neo1973/hw/mips_pica61.c
   trunk/src/host/qemu-neo1973/hw/pl181.c
   trunk/src/host/qemu-neo1973/hw/ppc405.h
   trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
   trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx.c
   trunk/src/host/qemu-neo1973/hw/smbus.c
   trunk/src/host/qemu-neo1973/hw/smbus.h
   trunk/src/host/qemu-neo1973/hw/smbus_eeprom.c
   trunk/src/host/qemu-neo1973/hw/vmmouse.c
   trunk/src/host/qemu-neo1973/hw/vmware_vga.c
   trunk/src/host/qemu-neo1973/linux-user/alpha/
   trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/alpha/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/i386/
   trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/
   trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/ppc64/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/
   trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/x86_64/termbits.h
   trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc64
   trunk/src/host/qemu-neo1973/target-alpha/
   trunk/src/host/qemu-neo1973/target-alpha/cpu.h
   trunk/src/host/qemu-neo1973/target-alpha/exec.h
   trunk/src/host/qemu-neo1973/target-alpha/helper.c
   trunk/src/host/qemu-neo1973/target-alpha/op.c
   trunk/src/host/qemu-neo1973/target-alpha/op_helper.c
   trunk/src/host/qemu-neo1973/target-alpha/op_helper.h
   trunk/src/host/qemu-neo1973/target-alpha/op_helper_mem.h
   trunk/src/host/qemu-neo1973/target-alpha/op_mem.h
   trunk/src/host/qemu-neo1973/target-alpha/op_template.h
   trunk/src/host/qemu-neo1973/target-alpha/translate.c
   trunk/src/host/qemu-neo1973/target-arm/op_iwmmxt.c
   trunk/src/host/qemu-neo1973/target-mips/TODO
   trunk/src/host/qemu-neo1973/target-mips/translate_init.c
   trunk/src/host/qemu-neo1973/target-ppc/STATUS
   trunk/src/host/qemu-neo1973/target-ppc/mfrom_table.c
   trunk/src/host/qemu-neo1973/target-ppc/mfrom_table_gen.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
   trunk/src/host/qemu-neo1973/uboot_image.h
   trunk/src/host/qemu-neo1973/x_keymap.c
Removed:
   trunk/src/host/qemu-neo1973/README.distrib
   trunk/src/host/qemu-neo1973/hw/md.c
   trunk/src/host/qemu-neo1973/keymaps/zaurus
   trunk/src/host/qemu-neo1973/linux-2.6.9-qemu-fast.patch
   trunk/src/host/qemu-neo1973/linux-user/arm-semi.c
Modified:
   trunk/src/host/qemu-neo1973/Changelog
   trunk/src/host/qemu-neo1973/LICENSE
   trunk/src/host/qemu-neo1973/Makefile
   trunk/src/host/qemu-neo1973/Makefile.target
   trunk/src/host/qemu-neo1973/VERSION
   trunk/src/host/qemu-neo1973/a.out.h
   trunk/src/host/qemu-neo1973/audio/alsaaudio.c
   trunk/src/host/qemu-neo1973/audio/audio.c
   trunk/src/host/qemu-neo1973/audio/audio.h
   trunk/src/host/qemu-neo1973/audio/audio_template.h
   trunk/src/host/qemu-neo1973/audio/coreaudio.c
   trunk/src/host/qemu-neo1973/audio/mixeng.c
   trunk/src/host/qemu-neo1973/audio/mixeng.h
   trunk/src/host/qemu-neo1973/audio/ossaudio.c
   trunk/src/host/qemu-neo1973/audio/wavaudio.c
   trunk/src/host/qemu-neo1973/audio/wavcapture.c
   trunk/src/host/qemu-neo1973/block-qcow2.c
   trunk/src/host/qemu-neo1973/block-raw.c
   trunk/src/host/qemu-neo1973/block-vmdk.c
   trunk/src/host/qemu-neo1973/block.c
   trunk/src/host/qemu-neo1973/configure
   trunk/src/host/qemu-neo1973/console.c
   trunk/src/host/qemu-neo1973/cpu-all.h
   trunk/src/host/qemu-neo1973/cpu-defs.h
   trunk/src/host/qemu-neo1973/cpu-exec.c
   trunk/src/host/qemu-neo1973/dis-asm.h
   trunk/src/host/qemu-neo1973/disas.c
   trunk/src/host/qemu-neo1973/dyngen-exec.h
   trunk/src/host/qemu-neo1973/dyngen.c
   trunk/src/host/qemu-neo1973/dyngen.h
   trunk/src/host/qemu-neo1973/ecc.h
   trunk/src/host/qemu-neo1973/elf.h
   trunk/src/host/qemu-neo1973/elf_ops.h
   trunk/src/host/qemu-neo1973/exec-all.h
   trunk/src/host/qemu-neo1973/exec.c
   trunk/src/host/qemu-neo1973/fpu/softfloat-native.c
   trunk/src/host/qemu-neo1973/fpu/softfloat-native.h
   trunk/src/host/qemu-neo1973/fpu/softfloat.c
   trunk/src/host/qemu-neo1973/fpu/softfloat.h
   trunk/src/host/qemu-neo1973/gdbstub.c
   trunk/src/host/qemu-neo1973/gdbstub.h
   trunk/src/host/qemu-neo1973/hw/acpi.c
   trunk/src/host/qemu-neo1973/hw/adlib.c
   trunk/src/host/qemu-neo1973/hw/ads7846.c
   trunk/src/host/qemu-neo1973/hw/apb_pci.c
   trunk/src/host/qemu-neo1973/hw/apic.c
   trunk/src/host/qemu-neo1973/hw/arm_boot.c
   trunk/src/host/qemu-neo1973/hw/arm_gic.c
   trunk/src/host/qemu-neo1973/hw/arm_pic.c
   trunk/src/host/qemu-neo1973/hw/arm_pic.h
   trunk/src/host/qemu-neo1973/hw/arm_sysctl.c
   trunk/src/host/qemu-neo1973/hw/arm_timer.c
   trunk/src/host/qemu-neo1973/hw/cirrus_vga.c
   trunk/src/host/qemu-neo1973/hw/cs4231.c
   trunk/src/host/qemu-neo1973/hw/cuda.c
   trunk/src/host/qemu-neo1973/hw/es1370.c
   trunk/src/host/qemu-neo1973/hw/esp.c
   trunk/src/host/qemu-neo1973/hw/fdc.c
   trunk/src/host/qemu-neo1973/hw/grackle_pci.c
   trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
   trunk/src/host/qemu-neo1973/hw/i2c.h
   trunk/src/host/qemu-neo1973/hw/i8254.c
   trunk/src/host/qemu-neo1973/hw/i8259.c
   trunk/src/host/qemu-neo1973/hw/ide.c
   trunk/src/host/qemu-neo1973/hw/integratorcp.c
   trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
   trunk/src/host/qemu-neo1973/hw/m48t59.c
   trunk/src/host/qemu-neo1973/hw/m48t59.h
   trunk/src/host/qemu-neo1973/hw/max111x.c
   trunk/src/host/qemu-neo1973/hw/max7310.c
   trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
   trunk/src/host/qemu-neo1973/hw/mips_r4k.c
   trunk/src/host/qemu-neo1973/hw/mips_timer.c
   trunk/src/host/qemu-neo1973/hw/modem.c
   trunk/src/host/qemu-neo1973/hw/nand.c
   trunk/src/host/qemu-neo1973/hw/ne2000.c
   trunk/src/host/qemu-neo1973/hw/neo1973.c
   trunk/src/host/qemu-neo1973/hw/openpic.c
   trunk/src/host/qemu-neo1973/hw/parallel.c
   trunk/src/host/qemu-neo1973/hw/pc.c
   trunk/src/host/qemu-neo1973/hw/pcf5060x.c
   trunk/src/host/qemu-neo1973/hw/pci.c
   trunk/src/host/qemu-neo1973/hw/pckbd.c
   trunk/src/host/qemu-neo1973/hw/pcnet.c
   trunk/src/host/qemu-neo1973/hw/pcspk.c
   trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
   trunk/src/host/qemu-neo1973/hw/piix_pci.c
   trunk/src/host/qemu-neo1973/hw/pl011.c
   trunk/src/host/qemu-neo1973/hw/pl050.c
   trunk/src/host/qemu-neo1973/hw/pl080.c
   trunk/src/host/qemu-neo1973/hw/pl110.c
   trunk/src/host/qemu-neo1973/hw/pl190.c
   trunk/src/host/qemu-neo1973/hw/ppc.c
   trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
   trunk/src/host/qemu-neo1973/hw/ppc_prep.c
   trunk/src/host/qemu-neo1973/hw/prep_pci.c
   trunk/src/host/qemu-neo1973/hw/ps2.c
   trunk/src/host/qemu-neo1973/hw/pxa.h
   trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c
   trunk/src/host/qemu-neo1973/hw/realview.c
   trunk/src/host/qemu-neo1973/hw/rtl8139.c
   trunk/src/host/qemu-neo1973/hw/s3c.h
   trunk/src/host/qemu-neo1973/hw/s3c2410.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_lcd.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_rtc.c
   trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c
   trunk/src/host/qemu-neo1973/hw/sb16.c
   trunk/src/host/qemu-neo1973/hw/scsi-disk.c
   trunk/src/host/qemu-neo1973/hw/sd.c
   trunk/src/host/qemu-neo1973/hw/sd.h
   trunk/src/host/qemu-neo1973/hw/serial.c
   trunk/src/host/qemu-neo1973/hw/sh7750.c
   trunk/src/host/qemu-neo1973/hw/shix.c
   trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
   trunk/src/host/qemu-neo1973/hw/slavio_misc.c
   trunk/src/host/qemu-neo1973/hw/slavio_serial.c
   trunk/src/host/qemu-neo1973/hw/slavio_timer.c
   trunk/src/host/qemu-neo1973/hw/smc91c111.c
   trunk/src/host/qemu-neo1973/hw/sparc32_dma.c
   trunk/src/host/qemu-neo1973/hw/spitz.c
   trunk/src/host/qemu-neo1973/hw/sun4m.c
   trunk/src/host/qemu-neo1973/hw/sun4u.c
   trunk/src/host/qemu-neo1973/hw/tcx.c
   trunk/src/host/qemu-neo1973/hw/unin_pci.c
   trunk/src/host/qemu-neo1973/hw/usb-hid.c
   trunk/src/host/qemu-neo1973/hw/usb-msd.c
   trunk/src/host/qemu-neo1973/hw/usb-net.c
   trunk/src/host/qemu-neo1973/hw/usb-ohci.c
   trunk/src/host/qemu-neo1973/hw/usb-uhci.c
   trunk/src/host/qemu-neo1973/hw/usb.h
   trunk/src/host/qemu-neo1973/hw/versatile_pci.c
   trunk/src/host/qemu-neo1973/hw/versatilepb.c
   trunk/src/host/qemu-neo1973/hw/vga.c
   trunk/src/host/qemu-neo1973/hw/vga_int.h
   trunk/src/host/qemu-neo1973/hw/wm8750.c
   trunk/src/host/qemu-neo1973/hw/wm8753.c
   trunk/src/host/qemu-neo1973/keymaps.c
   trunk/src/host/qemu-neo1973/kqemu.c
   trunk/src/host/qemu-neo1973/linux-user/elfload.c
   trunk/src/host/qemu-neo1973/linux-user/flatload.c
   trunk/src/host/qemu-neo1973/linux-user/main.c
   trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
   trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
   trunk/src/host/qemu-neo1973/linux-user/qemu.h
   trunk/src/host/qemu-neo1973/linux-user/signal.c
   trunk/src/host/qemu-neo1973/linux-user/syscall.c
   trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
   trunk/src/host/qemu-neo1973/loader.c
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/openmoko/download.sh
   trunk/src/host/qemu-neo1973/openmoko/flash.sh
   trunk/src/host/qemu-neo1973/osdep.c
   trunk/src/host/qemu-neo1973/osdep.h
   trunk/src/host/qemu-neo1973/pc-bios/README
   trunk/src/host/qemu-neo1973/pc-bios/bios.bin
   trunk/src/host/qemu-neo1973/pc-bios/bios.diff
   trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
   trunk/src/host/qemu-neo1973/ppc.ld
   trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
   trunk/src/host/qemu-neo1973/qemu-doc.texi
   trunk/src/host/qemu-neo1973/qemu-img.c
   trunk/src/host/qemu-neo1973/qemu-tech.texi
   trunk/src/host/qemu-neo1973/sdl.c
   trunk/src/host/qemu-neo1973/slirp/bootp.c
   trunk/src/host/qemu-neo1973/slirp/tftp.c
   trunk/src/host/qemu-neo1973/slirp/tftp.h
   trunk/src/host/qemu-neo1973/slirp/udp.c
   trunk/src/host/qemu-neo1973/softmmu_header.h
   trunk/src/host/qemu-neo1973/sparc.ld
   trunk/src/host/qemu-neo1973/target-arm/cpu.h
   trunk/src/host/qemu-neo1973/target-arm/exec.h
   trunk/src/host/qemu-neo1973/target-arm/helper.c
   trunk/src/host/qemu-neo1973/target-arm/op.c
   trunk/src/host/qemu-neo1973/target-arm/translate.c
   trunk/src/host/qemu-neo1973/target-i386/cpu.h
   trunk/src/host/qemu-neo1973/target-i386/helper.c
   trunk/src/host/qemu-neo1973/target-i386/helper2.c
   trunk/src/host/qemu-neo1973/target-i386/op.c
   trunk/src/host/qemu-neo1973/target-i386/ops_sse.h
   trunk/src/host/qemu-neo1973/target-i386/translate.c
   trunk/src/host/qemu-neo1973/target-m68k/cpu.h
   trunk/src/host/qemu-neo1973/target-m68k/translate.c
   trunk/src/host/qemu-neo1973/target-mips/cpu.h
   trunk/src/host/qemu-neo1973/target-mips/exec.h
   trunk/src/host/qemu-neo1973/target-mips/fop_template.c
   trunk/src/host/qemu-neo1973/target-mips/helper.c
   trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
   trunk/src/host/qemu-neo1973/target-mips/op.c
   trunk/src/host/qemu-neo1973/target-mips/op_helper.c
   trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c
   trunk/src/host/qemu-neo1973/target-mips/op_mem.c
   trunk/src/host/qemu-neo1973/target-mips/op_template.c
   trunk/src/host/qemu-neo1973/target-mips/translate.c
   trunk/src/host/qemu-neo1973/target-ppc/cpu.h
   trunk/src/host/qemu-neo1973/target-ppc/exec.h
   trunk/src/host/qemu-neo1973/target-ppc/helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
   trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
   trunk/src/host/qemu-neo1973/target-ppc/op_mem.h
   trunk/src/host/qemu-neo1973/target-ppc/op_template.h
   trunk/src/host/qemu-neo1973/target-ppc/translate.c
   trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
   trunk/src/host/qemu-neo1973/target-sh4/cpu.h
   trunk/src/host/qemu-neo1973/target-sh4/helper.c
   trunk/src/host/qemu-neo1973/target-sh4/op.c
   trunk/src/host/qemu-neo1973/target-sh4/translate.c
   trunk/src/host/qemu-neo1973/target-sparc/cpu.h
   trunk/src/host/qemu-neo1973/target-sparc/exec.h
   trunk/src/host/qemu-neo1973/target-sparc/op.c
   trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
   trunk/src/host/qemu-neo1973/target-sparc/translate.c
   trunk/src/host/qemu-neo1973/tests/Makefile
   trunk/src/host/qemu-neo1973/tests/test-arm-iwmmxt.s
   trunk/src/host/qemu-neo1973/tests/test-i386.c
   trunk/src/host/qemu-neo1973/translate-all.c
   trunk/src/host/qemu-neo1973/vl.c
   trunk/src/host/qemu-neo1973/vl.h
   trunk/src/host/qemu-neo1973/vnc.c
Log:
Merge changes from cvs.savannah.nongnu.org:/sources/qemu.
Merge Paul Brook's I2C/SMBus framework and drop our own I2C fwk.
Rewrite interrupt handling to use the new framework.
Update MMC host to use the new APIs.  Update CPU selection to the new API.
Rewrite GPIO handling to use only the IRQ fwk.
Convert memory mapping to the Fabrice Bellard's new API.  Convert I2C slaves and S3C2410 I2C master to new API.
Correct a ton of bugs spotted during the update.  (a basic test was done but things may still be broken because the update)


Modified: trunk/src/host/qemu-neo1973/Changelog
===================================================================
--- trunk/src/host/qemu-neo1973/Changelog	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Changelog	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,5 +1,13 @@
-version 0.8.3:
+  - TFTP booting from host directory (Anthony Liguori, Erwan Velu)
+  - Tap device emulation for Solaris (Sittichai Palanisong)
+  - Monitor multiplexing to several I/O channels (Jason Wessel)
+  - ds1225y nvram support (Herve Poussineau)
+  - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
+  - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
+  - MIPS 64-bit FPU support (Thiemo Seufer)
 
+version 0.9.0:
+
   - Support for relative paths in backing files for disk images
   - Async file I/O API
   - New qcow2 disk image format
@@ -7,6 +15,14 @@
   - Linux: specific host CDROM and floppy support
   - SMM support
   - Moved PCI init, MP table init and ACPI table init to Bochs BIOS
+  - Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
+  - MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
+  - Darwin userspace emulation (Pierre d'Herbemont)
+  - m68k user support (Paul Brook)
+  - several x86 and x86_64 emulation fixes
+  - Mouse relative offset VNC extension (Anthony Liguori)
+  - PXE boot support (Anthony Liguori)
+  - '-daemonize' option (Anthony Liguori)
 
 version 0.8.2:
 
@@ -15,7 +31,7 @@
   - switch to OpenBios for SPARC targets (Blue Swirl)
   - VNC server fixes
   - MIPS FPU support (Marius Groeger)
-  - Solaris/SPARC host support (Ben Taylor)
+  - Solaris/SPARC host support (Juergen Keil)
   - PPC breakpoints and single stepping (Jason Wessel)
   - USB updates (Paul Brook)
   - UDP/TCP/telnet character devices (Jason Wessel)
@@ -34,7 +50,7 @@
   - PC speaker support (Joachim Henke)
   - IDE LBA48 support (Jens Axboe)
   - SSE3 support
-  - Solaris port (Ben Taylor)
+  - Solaris port (Juergen Keil)
   - Preliminary SH4 target (Samuel Tardieu)
   - VNC server (Anthony Liguori)
   - slirp fixes (Ed Swierk et al.)

Modified: trunk/src/host/qemu-neo1973/LICENSE
===================================================================
--- trunk/src/host/qemu-neo1973/LICENSE	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/LICENSE	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,12 +1,15 @@
-The following points clarify the QEMU licenses:
+The following points clarify the QEMU license:
 
-1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
-   system emulator are released under the GNU Lesser General Public
-   License.
+1) QEMU as a whole is released under the GNU General Public License
 
-2) The Linux user mode QEMU emulator is released under the GNU General
-   Public License.
+2) Parts of QEMU have specific licenses which are compatible with the
+GNU General Public License. Hence each source file contains its own
+licensing information.
 
+In particular, the QEMU virtual CPU core library (libqemu.a) is
+released under the GNU Lesser General Public License. Many hardware
+device emulation sources are released under the BSD license.
+
 3) QEMU is a trademark of Fabrice Bellard.
 
 Fabrice Bellard.
\ No newline at end of file

Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Makefile	2007-05-11 23:44:50 UTC (rev 1948)
@@ -8,10 +8,9 @@
 BASE_CFLAGS=
 BASE_LDFLAGS=
 
-BASE_CFLAGS += $(OS_CFLAGS)
-ifeq ($(ARCH),sparc)
-BASE_CFLAGS += -mcpu=ultrasparc
-endif
+BASE_CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
 CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 LIBS=
 TOOLS=qemu-img$(EXESUF) raw2flash$(EXESUF) flash2raw$(EXESUF)
@@ -135,7 +134,8 @@
 
 html: qemu-doc.html qemu-tech.html
 
-FILE=qemu-$(shell cat VERSION)
+VERSION ?= $(shell cat VERSION)
+FILE = qemu-$(VERSION)
 
 # tar release (use 'make -k tar' on a checkouted tree)
 tar:
@@ -149,18 +149,24 @@
 	( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
 	$(bindir)/qemu \
 	$(bindir)/qemu-system-ppc \
+	$(bindir)/qemu-system-ppc64 \
+	$(bindir)/qemu-system-ppcemb \
 	$(bindir)/qemu-system-sparc \
 	$(bindir)/qemu-system-x86_64 \
 	$(bindir)/qemu-system-mips \
 	$(bindir)/qemu-system-mipsel \
+	$(bindir)/qemu-system-mips64 \
+	$(bindir)/qemu-system-mips64el \
 	$(bindir)/qemu-system-arm \
 	$(bindir)/qemu-i386 \
         $(bindir)/qemu-arm \
         $(bindir)/qemu-armeb \
         $(bindir)/qemu-sparc \
         $(bindir)/qemu-ppc \
+        $(bindir)/qemu-ppc64 \
         $(bindir)/qemu-mips \
         $(bindir)/qemu-mipsel \
+        $(bindir)/qemu-alpha \
         $(bindir)/qemu-img \
 	$(datadir)/bios.bin \
 	$(datadir)/vgabios.bin \
@@ -169,6 +175,9 @@
 	$(datadir)/video.x \
 	$(datadir)/openbios-sparc32 \
 	$(datadir)/linux_boot.bin \
+        $(datadir)/pxe-ne2k_pci.bin \
+	$(datadir)/pxe-rtl8139.bin \
+        $(datadir)/pxe-pcnet.bin \
 	$(docdir)/qemu-doc.html \
 	$(docdir)/qemu-tech.html \
 	$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )

Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/Makefile.target	2007-05-11 23:44:50 UTC (rev 1948)
@@ -4,16 +4,26 @@
 ifeq ($(TARGET_ARCH), x86_64)
 TARGET_BASE_ARCH:=i386
 endif
+ifeq ($(TARGET_ARCH), mips64)
+TARGET_BASE_ARCH:=mips
+endif
 ifeq ($(TARGET_ARCH), ppc64)
 TARGET_BASE_ARCH:=ppc
 endif
+ifeq ($(TARGET_ARCH), ppcemb)
+TARGET_BASE_ARCH:=ppc
+endif
 ifeq ($(TARGET_ARCH), sparc64)
 TARGET_BASE_ARCH:=sparc
 endif
 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
 CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
-ifdef CONFIG_USER_ONLY
+ifdef CONFIG_DARWIN_USER
+VPATH+=:$(SRC_PATH)/darwin-user
+CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
+endif
+ifdef CONFIG_LINUX_USER
 VPATH+=:$(SRC_PATH)/linux-user
 CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
@@ -40,6 +50,11 @@
     TARGET_ARCH2=mipsel
   endif
 endif
+ifeq ($(TARGET_ARCH),mips64)
+  ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+    TARGET_ARCH2=mips64el
+  endif
+endif
 QEMU_USER=qemu-$(TARGET_ARCH2)
 # system emulator name
 ifdef CONFIG_SOFTMMU
@@ -61,17 +76,31 @@
 endif
 endif # !CONFIG_USER_ONLY
 
+ifdef CONFIG_STATIC
+BASE_LDFLAGS+=-static
+endif
+
 # We require -O2 to avoid the stack setup prologue in EXIT_TB
-OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
+OP_CFLAGS := -Wall -O2 -g -fno-strict-aliasing
 
+# cc-option
+# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
+
+cc-option = $(shell if $(CC) $(OP_CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+OP_CFLAGS+=$(call cc-option, -fno-reorder-blocks, "")
+OP_CFLAGS+=$(call cc-option, -fno-gcse, "")
+OP_CFLAGS+=$(call cc-option, -fno-tree-ch, "")
+OP_CFLAGS+=$(call cc-option, -fno-optimize-sibling-calls, "")
+OP_CFLAGS+=$(call cc-option, -fno-crossjumping, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-labels, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-jumps, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-functions, $(call cc-option, -malign-functions=0, ""))
+
 ifeq ($(ARCH),i386)
 HELPER_CFLAGS+=-fomit-frame-pointer
 OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
-ifeq ($(HAVE_GCC3_OPTIONS),yes)
-OP_CFLAGS+= -falign-functions=0 -fno-gcse
-else
-OP_CFLAGS+= -malign-functions=0
-endif
 ifdef TARGET_GPROF
 USE_I386_LD=y
 endif
@@ -81,47 +110,50 @@
 ifdef USE_I386_LD
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 else
+ifdef CONFIG_LINUX_USER
 # WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
 # that the kernel ELF loader considers as an executable. I think this
 # is the simplest way to make it self virtualizable!
 BASE_LDFLAGS+=-Wl,-shared
 endif
 endif
+endif
 
 ifeq ($(ARCH),x86_64)
-HELPER_CFLAGS+=-fomit-frame-pointer
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),ppc)
 CPPFLAGS+= -D__powerpc__
+ifdef CONFIG_LINUX_USER
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
+endif
 
 ifeq ($(ARCH),s390)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
 
 ifeq ($(ARCH),sparc)
-ifeq ($(CONFIG_SOLARIS),yes)
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
-else
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
-HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
-# -static is used to avoid g1/g3 usage by the dynamic linker
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+  BASE_CFLAGS+=-ffixed-g2 -ffixed-g3
+  OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
+  ifeq ($(CONFIG_SOLARIS),yes)
+    OP_CFLAGS+=-fno-omit-frame-pointer
+  else
+    BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
+    HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
+    # -static is used to avoid g1/g3 usage by the dynamic linker
+    BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+  endif
 endif
-endif
 
 ifeq ($(ARCH),sparc64)
-BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
-BASE_LDFLAGS+=-m64
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
-OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
+  BASE_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+  OP_CFLAGS+=-mcpu=ultrasparc -m64 -fno-delayed-branch -ffixed-i0
+  ifneq ($(CONFIG_SOLARIS),yes)
+    BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+    OP_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+  endif
 endif
 
 ifeq ($(ARCH),alpha)
@@ -149,20 +181,37 @@
 endif
 
 ifeq ($(ARCH),mips)
+OP_CFLAGS+=-mabi=32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
 endif
+endif
 
-ifeq ($(HAVE_GCC3_OPTIONS),yes)
-# very important to generate a return at the end of every operation
-OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
+ifeq ($(ARCH),mips64)
+OP_CFLAGS+=-mabi=n32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
 endif
+endif
 
 ifeq ($(CONFIG_DARWIN),yes)
 LIBS+=-lmx
 endif
 
-OP_CFLAGS+=$(OS_CFLAGS)
+ifdef CONFIG_DARWIN_USER
+# Leave some space for the regular program loading zone
+BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
+endif
 
+BASE_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
+OP_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+OP_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
 #########################################################
 
 CPPFLAGS+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
@@ -175,7 +224,13 @@
 endif
 ifdef CONFIG_SOLARIS
 LIBS+=-lsocket -lnsl -lresolv
+ifdef NEEDS_LIBSUNMATH
+LIBS+=-lsunmath
+LDFLAGS+=-L/opt/SUNWspro/prod/lib -R/opt/SUNWspro/prod/lib
+OP_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
+BASE_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
 endif
+endif
 
 # profiling code
 ifdef TARGET_GPROF
@@ -183,8 +238,10 @@
 main.o: BASE_CFLAGS+=-p
 endif
 
+ifdef CONFIG_LINUX_USER
 OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
       elfload.o linuxload.o
+LIBS+= $(AIOLIBS)
 ifdef TARGET_HAS_BFLT
 OBJS+= flatload.o
 endif
@@ -200,6 +257,12 @@
 ifeq ($(TARGET_ARCH), m68k)
 OBJS+= m68k-sim.o m68k-semi.o
 endif
+endif #CONFIG_LINUX_USER
+
+ifdef CONFIG_DARWIN_USER
+OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
+endif
+
 SRCS:= $(OBJS:.o=.c)
 OBJS+= libqemu.a
 
@@ -228,7 +291,7 @@
 LIBOBJS+= op_helper.o helper.o
 endif
 
-ifeq ($(TARGET_ARCH), mips)
+ifeq ($(TARGET_BASE_ARCH), mips)
 LIBOBJS+= op_helper.o helper.o
 endif
 
@@ -248,6 +311,10 @@
 LIBOBJS+= helper.o
 endif
 
+ifeq ($(TARGET_BASE_ARCH), alpha)
+LIBOBJS+= op_helper.o helper.o alpha_palcode.o
+endif
+
 # NOTE: the disassembler code is only needed for debugging
 LIBOBJS+=disas.o 
 ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
@@ -265,7 +332,7 @@
 ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc)
 LIBOBJS+=ppc-dis.o
 endif
-ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
+ifeq ($(findstring mips, $(TARGET_BASE_ARCH) $(ARCH)),mips)
 LIBOBJS+=mips-dis.o
 endif
 ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
@@ -300,6 +367,7 @@
 VL_OBJS+=cutils.o
 VL_OBJS+=block.o block-raw.o
 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
+VL_OBJS+=irq.o
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
 endif
@@ -333,6 +401,8 @@
 endif
 AUDIODRV+= wavcapture.o
 
+VL_OBJS += i2c.o smbus.o
+
 # SCSI layer
 VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
 
@@ -340,27 +410,36 @@
 VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o usb-net.o
 VL_OBJS+= usb-linux-gadget.o
 
+# EEPROM emulation
+VL_OBJS += eeprom93xx.o
+
 # PCI network cards
-VL_OBJS+= ne2000.o rtl8139.o pcnet.o
+VL_OBJS += eepro100.o
+VL_OBJS += ne2000.o
+VL_OBJS += pcnet.o
+VL_OBJS += rtl8139.o
 
 ifeq ($(TARGET_BASE_ARCH), i386)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-VL_OBJS+= usb-uhci.o
+VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmware_vga.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 endif
 ifeq ($(TARGET_BASE_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
-VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
+VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
-VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
+VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o ppc405_boards.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 endif
-ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_timer.o dma.o vga.o serial.o i8254.o i8259.o ide.o
-VL_OBJS+= mc146818rtc.o #pckbd.o fdc.o m48t59.o
+ifeq ($(TARGET_BASE_ARCH), mips)
+VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
+VL_OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
+VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+CPPFLAGS += -DHAS_AUDIO
 endif
 ifeq ($(TARGET_BASE_ARCH), sparc)
 ifeq ($(TARGET_ARCH), sparc64)
@@ -375,12 +454,13 @@
 endif
 ifeq ($(TARGET_BASE_ARCH), arm)
 VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
-VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
-VL_OBJS+= versatile_pci.o
+VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl181.o pl190.o
+VL_OBJS+= versatile_pci.o sd.o
 VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
-VL_OBJS+= pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o spitz.o
+VL_OBJS+= arm-semi.o
+VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
-VL_OBJS+= ads7846.o sd.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
 VL_OBJS+= s3c2410.o s3c24xx_gpio.o s3c24xx_lcd.o s3c24xx_mmci.o s3c24xx_rtc.o
 VL_OBJS+= s3c24xx_udc.o neo1973.o pcf5060x.o jbt6k74.o modem.o
 CPPFLAGS += -DHAS_AUDIO
@@ -392,7 +472,7 @@
 VL_OBJS+=gdbstub.o 
 endif
 ifdef CONFIG_SDL
-VL_OBJS+=sdl.o
+VL_OBJS+=sdl.o x_keymap.o
 endif
 VL_OBJS+=vnc.o
 ifdef CONFIG_COCOA
@@ -436,8 +516,10 @@
 endif
 
 ifeq ($(ARCH),sparc64)
-VL_LDFLAGS+=-m64
-VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
+  VL_LDFLAGS+=-m64
+  ifneq ($(CONFIG_SOLARIS),yes)
+    VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+  endif
 endif
 
 ifdef CONFIG_WIN32
@@ -445,7 +527,7 @@
 endif
 
 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
-	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+	$(CC) $(VL_LDFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
 
 cocoa.o: cocoa.m
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
@@ -528,9 +610,11 @@
 translate.o: translate.c translate_init.c
 endif
 
-ifeq ($(TARGET_ARCH), mips)
-op.o: op.c op_template.c op_mem.c
-op_helper.o: op_helper_mem.c
+ifeq ($(TARGET_BASE_ARCH), mips)
+helper.o: cpu.h exec-all.h
+op.o: op_template.c fop_template.c op_mem.c exec.h
+op_helper.o: op_helper_mem.c exec.h softmmu_template.h
+translate.o: translate_init.c exec-all.h disas.h
 endif
 
 loader.o: loader.c elf_ops.h
@@ -545,6 +629,11 @@
 tc58128.o: tc58128.c
 endif
 
+ifeq ($(TARGET_BASE_ARCH), alpha)
+op.o: op.c op_template.h op_mem.h
+op_helper.o: op_helper_mem.h
+endif
+
 $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
 
 %.o: %.c

Deleted: trunk/src/host/qemu-neo1973/README.distrib
===================================================================
--- trunk/src/host/qemu-neo1973/README.distrib	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/README.distrib	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,16 +0,0 @@
-Information about the various packages used to build the current qemu
-x86 binary distribution:
-
-* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
-  was used to get most of the binary packages.
-
-* wine-20020411 tarball
-
-  ./configure --prefix=/usr/local/wine-i386
-  
-  All exe and libs were stripped. Some compile time tools and the
-  includes were deleted.
-
-* ldconfig was launched to build the library links:
-
-  qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache

Modified: trunk/src/host/qemu-neo1973/VERSION
===================================================================
--- trunk/src/host/qemu-neo1973/VERSION	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/VERSION	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1 +1 @@
-0.8.2
\ No newline at end of file
+0.9.0
\ No newline at end of file

Modified: trunk/src/host/qemu-neo1973/a.out.h
===================================================================
--- trunk/src/host/qemu-neo1973/a.out.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/a.out.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -25,9 +25,9 @@
 struct external_filehdr {
   short f_magic;	/* magic number			*/
   short f_nscns;	/* number of sections		*/
-  unsigned long f_timdat;	/* time & date stamp		*/
-  unsigned long f_symptr;	/* file pointer to symtab	*/
-  unsigned long f_nsyms;	/* number of symtab entries	*/
+  host_ulong f_timdat;	/* time & date stamp		*/
+  host_ulong f_symptr;	/* file pointer to symtab	*/
+  host_ulong f_nsyms;	/* number of symtab entries	*/
   short f_opthdr;	/* sizeof(optional hdr)		*/
   short f_flags;	/* flags			*/
 };
@@ -72,12 +72,12 @@
 {
   unsigned short magic;		/* type of file				*/
   unsigned short vstamp;	/* version stamp			*/
-  unsigned long	tsize;		/* text size in bytes, padded to FW bdry*/
-  unsigned long	dsize;		/* initialized data "  "		*/
-  unsigned long	bsize;		/* uninitialized data "   "		*/
-  unsigned long	entry;		/* entry pt.				*/
-  unsigned long text_start;	/* base of text used for this file */
-  unsigned long data_start;	/* base of data used for this file=
+  host_ulong	tsize;		/* text size in bytes, padded to FW bdry*/
+  host_ulong	dsize;		/* initialized data "  "		*/
+  host_ulong	bsize;		/* uninitialized data "   "		*/
+  host_ulong	entry;		/* entry pt.				*/
+  host_ulong text_start;	/* base of text used for this file */
+  host_ulong data_start;	/* base of data used for this file=
  */
 }
 AOUTHDR;
@@ -103,16 +103,16 @@
 
 struct external_scnhdr {
   char		s_name[8];	/* section name			*/
-  unsigned long	s_paddr;	/* physical address, offset
+  host_ulong	s_paddr;	/* physical address, offset
 				   of last addr in scn */
-  unsigned long	s_vaddr;	/* virtual address		*/
-  unsigned long	s_size;		/* section size			*/
-  unsigned long	s_scnptr;	/* file ptr to raw data for section */
-  unsigned long	s_relptr;	/* file ptr to relocation	*/
-  unsigned long	s_lnnoptr;	/* file ptr to line numbers	*/
+  host_ulong	s_vaddr;	/* virtual address		*/
+  host_ulong	s_size;		/* section size			*/
+  host_ulong	s_scnptr;	/* file ptr to raw data for section */
+  host_ulong	s_relptr;	/* file ptr to relocation	*/
+  host_ulong	s_lnnoptr;	/* file ptr to line numbers	*/
   unsigned short s_nreloc;	/* number of relocation entries	*/
   unsigned short s_nlnno;	/* number of line number entries*/
-  unsigned long	s_flags;	/* flags			*/
+  host_ulong	s_flags;	/* flags			*/
 };
 
 #define	SCNHDR	struct external_scnhdr
@@ -136,8 +136,8 @@
  */
 struct external_lineno {
   union {
-    unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */
-    unsigned long l_paddr;	/* (physical) address of line number	*/
+    host_ulong l_symndx; /* function name symbol index, iff l_lnno 0 */
+    host_ulong l_paddr;	/* (physical) address of line number	*/
   } l_addr;
   unsigned short l_lnno;	/* line number		*/
 };
@@ -156,11 +156,11 @@
   union {
     char e_name[E_SYMNMLEN];
     struct {
-      unsigned long e_zeroes;
-      unsigned long e_offset;
+      host_ulong e_zeroes;
+      host_ulong e_offset;
     } e;
   } e;
-  unsigned long e_value;
+  host_ulong e_value;
   unsigned short e_scnum;
   unsigned short e_type;
   char e_sclass[1];
@@ -174,18 +174,18 @@
 
 union external_auxent {
   struct {
-    unsigned long x_tagndx;	/* str, un, or enum tag indx */
+    host_ulong x_tagndx;	/* str, un, or enum tag indx */
     union {
       struct {
 	unsigned short  x_lnno; /* declaration line number */
 	unsigned short  x_size; /* str/union/array size */
       } x_lnsz;
-      unsigned long x_fsize;	/* size of function */
+      host_ulong x_fsize;	/* size of function */
     } x_misc;
     union {
       struct {			/* if ISFCN, tag, or .bb */
-	unsigned long x_lnnoptr;/* ptr to fcn line # */
-	unsigned long x_endndx;	/* entry ndx past block end */
+	host_ulong x_lnnoptr;/* ptr to fcn line # */
+	host_ulong x_endndx;	/* entry ndx past block end */
       } x_fcn;
       struct {			/* if ISARY, up to 4 dimen. */
 	char x_dimen[E_DIMNUM][2];
@@ -197,22 +197,22 @@
   union {
     char x_fname[E_FILNMLEN];
     struct {
-      unsigned long x_zeroes;
-      unsigned long x_offset;
+      host_ulong x_zeroes;
+      host_ulong x_offset;
     } x_n;
   } x_file;
 
   struct {
-    unsigned long x_scnlen;	/* section length */
+    host_ulong x_scnlen;	/* section length */
     unsigned short x_nreloc;	/* # relocation entries */
     unsigned short x_nlinno;	/* # line numbers */
-    unsigned long x_checksum;	/* section COMDAT checksum */
+    host_ulong x_checksum;	/* section COMDAT checksum */
     unsigned short x_associated;/* COMDAT associated section index */
     char x_comdat[1];		/* COMDAT selection number */
   } x_scn;
 
   struct {
-    unsigned long x_tvfill;	/* tv fill value */
+    host_ulong x_tvfill;	/* tv fill value */
     unsigned short x_tvlen;	/* length of .tv */
     char x_tvran[2][2];		/* tv range */
   } x_tv;	/* info about .tv section (in auxent of symbol .tv)) */
@@ -344,7 +344,7 @@
   unsigned short e_oemid;	/* OEM identifier (for e_oeminfo), 0x0 */
   unsigned short e_oeminfo;	/* OEM information; e_oemid specific, 0x0 */
   char e_res2[10][2];		/* Reserved words, all 0x0 */
-  unsigned long e_lfanew;	/* File address of new exe header, 0x80 */
+  host_ulong e_lfanew;	/* File address of new exe header, 0x80 */
   char dos_message[16][4];	/* other stuff, always follow DOS header */
   unsigned int nt_signature;	/* required NT signature, 0x4550 */
 
@@ -352,9 +352,9 @@
 
   unsigned short f_magic;	/* magic number			*/
   unsigned short f_nscns;	/* number of sections		*/
-  unsigned long f_timdat;	/* time & date stamp		*/
-  unsigned long f_symptr;	/* file pointer to symtab	*/
-  unsigned long f_nsyms;	/* number of symtab entries	*/
+  host_ulong f_timdat;	/* time & date stamp		*/
+  host_ulong f_symptr;	/* file pointer to symtab	*/
+  host_ulong f_nsyms;	/* number of symtab entries	*/
   unsigned short f_opthdr;	/* sizeof(optional hdr)		*/
   unsigned short f_flags;	/* flags			*/
 };
@@ -370,17 +370,17 @@
 {
   unsigned short magic;		/* type of file				*/
   unsigned short vstamp;	/* version stamp			*/
-  unsigned long	tsize;		/* text size in bytes, padded to FW bdry*/
-  unsigned long	dsize;		/* initialized data "  "		*/
-  unsigned long	bsize;		/* uninitialized data "   "		*/
-  unsigned long	entry;		/* entry pt.				*/
-  unsigned long text_start;	/* base of text used for this file */
-  unsigned long data_start;	/* base of all data used for this file */
+  host_ulong	tsize;		/* text size in bytes, padded to FW bdry*/
+  host_ulong	dsize;		/* initialized data "  "		*/
+  host_ulong	bsize;		/* uninitialized data "   "		*/
+  host_ulong	entry;		/* entry pt.				*/
+  host_ulong text_start;	/* base of text used for this file */
+  host_ulong data_start;	/* base of all data used for this file */
 
   /* NT extra fields; see internal.h for descriptions */
-  unsigned long  ImageBase;
-  unsigned long  SectionAlignment;
-  unsigned long  FileAlignment;
+  host_ulong  ImageBase;
+  host_ulong  SectionAlignment;
+  host_ulong  FileAlignment;
   unsigned short  MajorOperatingSystemVersion;
   unsigned short  MinorOperatingSystemVersion;
   unsigned short  MajorImageVersion;
@@ -388,17 +388,17 @@
   unsigned short  MajorSubsystemVersion;
   unsigned short  MinorSubsystemVersion;
   char  Reserved1[4];
-  unsigned long  SizeOfImage;
-  unsigned long  SizeOfHeaders;
-  unsigned long  CheckSum;
+  host_ulong  SizeOfImage;
+  host_ulong  SizeOfHeaders;
+  host_ulong  CheckSum;
   unsigned short Subsystem;
   unsigned short DllCharacteristics;
-  unsigned long  SizeOfStackReserve;
-  unsigned long  SizeOfStackCommit;
-  unsigned long  SizeOfHeapReserve;
-  unsigned long  SizeOfHeapCommit;
-  unsigned long  LoaderFlags;
-  unsigned long  NumberOfRvaAndSizes;
+  host_ulong  SizeOfStackReserve;
+  host_ulong  SizeOfStackCommit;
+  host_ulong  SizeOfHeapReserve;
+  host_ulong  SizeOfHeapCommit;
+  host_ulong  LoaderFlags;
+  host_ulong  NumberOfRvaAndSizes;
   /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
   char  DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
 

Added: trunk/src/host/qemu-neo1973/arm-semi.c
===================================================================
--- trunk/src/host/qemu-neo1973/arm-semi.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/arm-semi.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,458 @@
+/*
+ *  Arm "Angel" semihosting syscalls
+ * 
+ *  Copyright (c) 2005, 2007 CodeSourcery.
+ *  Written by Paul Brook.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "cpu.h"
+#ifdef CONFIG_USER_ONLY
+#include "qemu.h"
+
+#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "vl.h"
+#endif
+
+#define SYS_OPEN        0x01
+#define SYS_CLOSE       0x02
+#define SYS_WRITEC      0x03
+#define SYS_WRITE0      0x04
+#define SYS_WRITE       0x05
+#define SYS_READ        0x06
+#define SYS_READC       0x07
+#define SYS_ISTTY       0x09
+#define SYS_SEEK        0x0a
+#define SYS_FLEN        0x0c
+#define SYS_TMPNAM      0x0d
+#define SYS_REMOVE      0x0e
+#define SYS_RENAME      0x0f
+#define SYS_CLOCK       0x10
+#define SYS_TIME        0x11
+#define SYS_SYSTEM      0x12
+#define SYS_ERRNO       0x13
+#define SYS_GET_CMDLINE 0x15
+#define SYS_HEAPINFO    0x16
+#define SYS_EXIT        0x18
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define GDB_O_RDONLY  0x000
+#define GDB_O_WRONLY  0x001
+#define GDB_O_RDWR    0x002
+#define GDB_O_APPEND  0x008
+#define GDB_O_CREAT   0x200
+#define GDB_O_TRUNC   0x400
+#define GDB_O_BINARY  0
+
+static int gdb_open_modeflags[12] = {
+    GDB_O_RDONLY,
+    GDB_O_RDONLY | GDB_O_BINARY,
+    GDB_O_RDWR,
+    GDB_O_RDWR | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
+    GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
+};
+
+static int open_modeflags[12] = {
+    O_RDONLY,
+    O_RDONLY | O_BINARY,
+    O_RDWR,
+    O_RDWR | O_BINARY,
+    O_WRONLY | O_CREAT | O_TRUNC,
+    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+    O_RDWR | O_CREAT | O_TRUNC,
+    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+    O_WRONLY | O_CREAT | O_APPEND,
+    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
+    O_RDWR | O_CREAT | O_APPEND,
+    O_RDWR | O_CREAT | O_APPEND | O_BINARY
+};
+
+#ifdef CONFIG_USER_ONLY
+static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
+{
+    if (code == (uint32_t)-1)
+        ts->swi_errno = errno;
+    return code;
+}
+#else
+static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
+{
+    return code;
+}
+
+static uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
+{
+    uint32_t val;
+
+    cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
+    return tswap32(val);
+}
+static uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
+{
+    uint8_t val;
+
+    cpu_memory_rw_debug(env, addr, &val, 1, 0);
+    return val;
+}
+#define tget32(p) softmmu_tget32(env, p)
+#define tget8(p) softmmu_tget8(env, p)
+
+static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
+                               int copy)
+{
+    char *p;
+    /* TODO: Make this something that isn't fixed size.  */
+    p = malloc(len);
+    if (copy)
+        cpu_memory_rw_debug(env, addr, p, len, 0);
+    return p;
+}
+#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
+static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
+{
+    char *p;
+    char *s;
+    uint8_t c;
+    /* TODO: Make this something that isn't fixed size.  */
+    s = p = malloc(1024);
+    do {
+        cpu_memory_rw_debug(env, addr, &c, 1, 0);
+        addr++;
+        *(p++) = c;
+    } while (c);
+    return s;
+}
+#define lock_user_string(p) softmmu_lock_user_string(env, p)
+static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
+                                target_ulong len)
+{
+    if (len)
+        cpu_memory_rw_debug(env, addr, p, len, 1);
+    free(p);
+}
+#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
+#endif
+
+static target_ulong arm_semi_syscall_len;
+
+static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+{
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#endif
+    if (ret == (target_ulong)-1) {
+#ifdef CONFIG_USER_ONLY
+        ts->swi_errno = err;
+#endif
+        env->regs[0] = ret;
+    } else {
+        /* Fixup syscalls that use nonstardard return conventions.  */
+        switch (env->regs[0]) {
+        case SYS_WRITE:
+        case SYS_READ:
+            env->regs[0] = arm_semi_syscall_len - ret;
+            break;
+        case SYS_SEEK:
+            env->regs[0] = 0;
+            break;
+        default:
+            env->regs[0] = ret;
+            break;
+        }
+    }
+}
+
+#define ARG(n) tget32(args + (n) * 4)
+#define SET_ARG(n, val) tput32(args + (n) * 4,val)
+uint32_t do_arm_semihosting(CPUState *env)
+{
+    target_ulong args;
+    char * s;
+    int nr;
+    uint32_t ret;
+    uint32_t len;
+#ifdef CONFIG_USER_ONLY
+    TaskState *ts = env->opaque;
+#else
+    CPUState *ts = env;
+#endif
+
+    nr = env->regs[0];
+    args = env->regs[1];
+    switch (nr) {
+    case SYS_OPEN:
+        s = lock_user_string(ARG(0));
+        if (ARG(1) >= 12)
+          return (uint32_t)-1;
+        if (strcmp(s, ":tt") == 0) {
+            if (ARG(1) < 4)
+                return STDIN_FILENO;
+            else
+                return STDOUT_FILENO;
+        }
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2),
+                           gdb_open_modeflags[ARG(1)]);
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
+        }
+        unlock_user(s, ARG(0), 0);
+        return ret;
+    case SYS_CLOSE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return set_swi_errno(ts, close(ARG(0)));
+        }
+    case SYS_WRITEC:
+        {
+          char c = tget8(args);
+          /* Write to debug console.  stderr is near enough.  */
+          if (use_gdb_syscalls()) {
+                gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
+                return env->regs[0];
+          } else {
+                return write(STDERR_FILENO, &c, 1);
+          }
+        }
+    case SYS_WRITE0:
+        s = lock_user_string(args);
+        len = strlen(s);
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
+            ret = env->regs[0];
+        } else {
+            ret = write(STDERR_FILENO, s, len);
+        }
+        unlock_user(s, args, 0);
+        return ret;
+    case SYS_WRITE:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            s = lock_user(ARG(1), len, 1);
+            ret = set_swi_errno(ts, write(ARG(0), s, len));
+            unlock_user(s, ARG(1), 0);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case SYS_READ:
+        len = ARG(2);
+        if (use_gdb_syscalls()) {
+            arm_semi_syscall_len = len;
+            gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
+            return env->regs[0];
+        } else {
+            s = lock_user(ARG(1), len, 0);
+            do
+              ret = set_swi_errno(ts, read(ARG(0), s, len));
+            while (ret == -1 && errno == EINTR);
+            unlock_user(s, ARG(1), len);
+            if (ret == (uint32_t)-1)
+                return -1;
+            return len - ret;
+        }
+    case SYS_READC:
+       /* XXX: Read from debug cosole. Not implemented.  */
+        return 0;
+    case SYS_ISTTY:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
+            return env->regs[0];
+        } else {
+            return isatty(ARG(0));
+        }
+    case SYS_SEEK:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1));
+            return env->regs[0];
+        } else {
+            ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
+            if (ret == (uint32_t)-1)
+              return -1;
+            return 0;
+        }
+    case SYS_FLEN:
+        if (use_gdb_syscalls()) {
+            /* TODO: Use stat syscall.  */
+            return -1;
+        } else {
+            struct stat buf;
+            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
+            if (ret == (uint32_t)-1)
+                return -1;
+            return buf.st_size;
+        }
+    case SYS_TMPNAM:
+        /* XXX: Not implemented.  */
+        return -1;
+    case SYS_REMOVE:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1));
+            ret = env->regs[0];
+        } else {
+            s = lock_user_string(ARG(0));
+            ret =  set_swi_errno(ts, remove(s));
+            unlock_user(s, ARG(0), 0);
+        }
+        return ret;
+    case SYS_RENAME:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
+                           ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+            return env->regs[0];
+        } else {
+            char *s2;
+            s = lock_user_string(ARG(0));
+            s2 = lock_user_string(ARG(2));
+            ret = set_swi_errno(ts, rename(s, s2));
+            unlock_user(s2, ARG(2), 0);
+            unlock_user(s, ARG(0), 0);
+            return ret;
+        }
+    case SYS_CLOCK:
+        return clock() / (CLOCKS_PER_SEC / 100);
+    case SYS_TIME:
+        return set_swi_errno(ts, time(NULL));
+    case SYS_SYSTEM:
+        if (use_gdb_syscalls()) {
+            gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1));
+            return env->regs[0];
+        } else {
+            s = lock_user_string(ARG(0));
+            ret = set_swi_errno(ts, system(s));
+            unlock_user(s, ARG(0), 0);
+        }
+    case SYS_ERRNO:
+#ifdef CONFIG_USER_ONLY
+        return ts->swi_errno;
+#else
+        return 0;
+#endif
+    case SYS_GET_CMDLINE:
+#ifdef CONFIG_USER_ONLY
+        /* Build a commandline from the original argv.  */
+        {
+            char **arg = ts->info->host_argv;
+            int len = ARG(1);
+            /* lock the buffer on the ARM side */
+            char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
+
+            s = cmdline_buffer;
+            while (*arg && len > 2) {
+                int n = strlen(*arg);
+
+                if (s != cmdline_buffer) {
+                    *(s++) = ' ';
+                    len--;
+                }
+                if (n >= len)
+                    n = len - 1;
+                memcpy(s, *arg, n);
+                s += n;
+                len -= n;
+                arg++;
+            }
+            /* Null terminate the string.  */
+            *s = 0;
+            len = s - cmdline_buffer;
+
+            /* Unlock the buffer on the ARM side.  */
+            unlock_user(cmdline_buffer, ARG(0), len);
+
+            /* Adjust the commandline length argument.  */
+            SET_ARG(1, len);
+
+            /* Return success if commandline fit into buffer.  */
+            return *arg ? -1 : 0;
+        }
+#else
+      return -1;
+#endif
+    case SYS_HEAPINFO:
+        {
+            uint32_t *ptr;
+            uint32_t limit;
+
+#ifdef CONFIG_USER_ONLY
+            /* Some C libraries assume the heap immediately follows .bss, so
+               allocate it using sbrk.  */
+            if (!ts->heap_limit) {
+                long ret;
+
+                ts->heap_base = do_brk(0);
+                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                /* Try a big heap, and reduce the size if that fails.  */
+                for (;;) {
+                    ret = do_brk(limit);
+                    if (ret != -1)
+                        break;
+                    limit = (ts->heap_base >> 1) + (limit >> 1);
+                }
+                ts->heap_limit = limit;
+            }
+              
+            ptr = lock_user(ARG(0), 16, 0);
+            ptr[0] = tswap32(ts->heap_base);
+            ptr[1] = tswap32(ts->heap_limit);
+            ptr[2] = tswap32(ts->stack_base);
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#else
+            limit = ram_size;
+            ptr = lock_user(ARG(0), 16, 0);
+            /* TODO: Make this use the limit of the loaded application.  */
+            ptr[0] = tswap32(limit / 2);
+            ptr[1] = tswap32(limit);
+            ptr[2] = tswap32(limit); /* Stack base */
+            ptr[3] = tswap32(0); /* Stack limit.  */
+            unlock_user(ptr, ARG(0), 16);
+#endif
+            return 0;
+        }
+    case SYS_EXIT:
+        exit(0);
+    default:
+        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
+        cpu_dump_state(env, stderr, fprintf, 0);
+        abort();
+    }
+}

Modified: trunk/src/host/qemu-neo1973/audio/alsaaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/alsaaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/alsaaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -157,6 +157,12 @@
     case AUD_FMT_U16:
         return SND_PCM_FORMAT_U16_LE;
 
+    case AUD_FMT_S32:
+        return SND_PCM_FORMAT_S32_LE;
+
+    case AUD_FMT_U32:
+        return SND_PCM_FORMAT_U32_LE;
+
     default:
         dolog ("Internal logic error: Bad audio format %d\n", fmt);
 #ifdef DEBUG_AUDIO
@@ -199,6 +205,26 @@
         *fmt = AUD_FMT_U16;
         break;
 
+    case SND_PCM_FORMAT_S32_LE:
+        *endianness = 0;
+        *fmt = AUD_FMT_S32;
+        break;
+
+    case SND_PCM_FORMAT_U32_LE:
+        *endianness = 0;
+        *fmt = AUD_FMT_U32;
+        break;
+
+    case SND_PCM_FORMAT_S32_BE:
+        *endianness = 1;
+        *fmt = AUD_FMT_S32;
+        break;
+
+    case SND_PCM_FORMAT_U32_BE:
+        *endianness = 1;
+        *fmt = AUD_FMT_U32;
+        break;
+
     default:
         dolog ("Unrecognized audio format %d\n", alsafmt);
         return -1;

Modified: trunk/src/host/qemu-neo1973/audio/audio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -80,7 +80,8 @@
         {
             44100,              /* freq */
             2,                  /* nchannels */
-            AUD_FMT_S16         /* fmt */
+            AUD_FMT_S16,        /* fmt */
+            AUDIO_HOST_ENDIANNESS
         }
     },
 
@@ -91,7 +92,8 @@
         {
             44100,              /* freq */
             2,                  /* nchannels */
-            AUD_FMT_S16         /* fmt */
+            AUD_FMT_S16,        /* fmt */
+            AUDIO_HOST_ENDIANNESS
         }
     },
 
@@ -166,6 +168,25 @@
 }
 #endif
 
+static inline int audio_bits_to_index (int bits)
+{
+    switch (bits) {
+    case 8:
+        return 0;
+
+    case 16:
+        return 1;
+
+    case 32:
+        return 2;
+
+    default:
+        audio_bug ("bits_to_index", 1);
+        AUD_log (NULL, "invalid bits %d\n", bits);
+        return 0;
+    }
+}
+
 void *audio_calloc (const char *funcname, int nmemb, size_t size)
 {
     int cond;
@@ -227,6 +248,12 @@
 
     case AUD_FMT_S16:
         return "S16";
+
+    case AUD_FMT_U32:
+        return "U32";
+
+    case AUD_FMT_S32:
+        return "S32";
     }
 
     dolog ("Bogus audfmt %d returning S16\n", fmt);
@@ -243,6 +270,10 @@
         *defaultp = 0;
         return AUD_FMT_U16;
     }
+    else if (!strcasecmp (s, "u32")) {
+        *defaultp = 0;
+        return AUD_FMT_U32;
+    }
     else if (!strcasecmp (s, "s8")) {
         *defaultp = 0;
         return AUD_FMT_S8;
@@ -251,6 +282,10 @@
         *defaultp = 0;
         return AUD_FMT_S16;
     }
+    else if (!strcasecmp (s, "s32")) {
+        *defaultp = 0;
+        return AUD_FMT_S32;
+    }
     else {
         dolog ("Bogus audio format `%s' using %s\n",
                s, audio_audfmt_to_string (defval));
@@ -538,6 +573,8 @@
     case AUD_FMT_U8:
     case AUD_FMT_S16:
     case AUD_FMT_U16:
+    case AUD_FMT_S32:
+    case AUD_FMT_U32:
         break;
     default:
         invalid = 1;
@@ -563,6 +600,12 @@
     case AUD_FMT_U16:
         bits = 16;
         break;
+
+    case AUD_FMT_S32:
+        sign = 1;
+    case AUD_FMT_U32:
+        bits = 32;
+        break;
     }
     return info->freq == as->freq
         && info->nchannels == as->nchannels
@@ -573,7 +616,7 @@
 
 void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
 {
-    int bits = 8, sign = 0;
+    int bits = 8, sign = 0, shift = 0;
 
     switch (as->fmt) {
     case AUD_FMT_S8:
@@ -585,14 +628,22 @@
         sign = 1;
     case AUD_FMT_U16:
         bits = 16;
+        shift = 1;
         break;
+
+    case AUD_FMT_S32:
+        sign = 1;
+    case AUD_FMT_U32:
+        bits = 32;
+        shift = 2;
+        break;
     }
 
     info->freq = as->freq;
     info->bits = bits;
     info->sign = sign;
     info->nchannels = as->nchannels;
-    info->shift = (as->nchannels == 2) + (bits == 16);
+    info->shift = (as->nchannels == 2) + shift;
     info->align = (1 << info->shift) - 1;
     info->bytes_per_second = info->freq << info->shift;
     info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
@@ -608,22 +659,49 @@
         memset (buf, 0x00, len << info->shift);
     }
     else {
-        if (info->bits == 8) {
+        switch (info->bits) {
+        case 8:
             memset (buf, 0x80, len << info->shift);
-        }
-        else {
-            int i;
-            uint16_t *p = buf;
-            int shift = info->nchannels - 1;
-            short s = INT16_MAX;
+            break;
 
-            if (info->swap_endianness) {
-                s = bswap16 (s);
+        case 16:
+            {
+                int i;
+                uint16_t *p = buf;
+                int shift = info->nchannels - 1;
+                short s = INT16_MAX;
+
+                if (info->swap_endianness) {
+                    s = bswap16 (s);
+                }
+
+                for (i = 0; i < len << shift; i++) {
+                    p[i] = s;
+                }
             }
+            break;
 
-            for (i = 0; i < len << shift; i++) {
-                p[i] = s;
+        case 32:
+            {
+                int i;
+                uint32_t *p = buf;
+                int shift = info->nchannels - 1;
+                int32_t s = INT32_MAX;
+
+                if (info->swap_endianness) {
+                    s = bswap32 (s);
+                }
+
+                for (i = 0; i < len << shift; i++) {
+                    p[i] = s;
+                }
             }
+            break;
+
+        default:
+            AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
+                     info->bits);
+            break;
         }
     }
 }
@@ -1811,7 +1889,7 @@
             [hw->info.nchannels == 2]
             [hw->info.sign]
             [hw->info.swap_endianness]
-            [hw->info.bits == 16];
+            [audio_bits_to_index (hw->info.bits)];
 
         LIST_INSERT_HEAD (&s->cap_head, cap, entries);
         LIST_INSERT_HEAD (&cap->cb_head, cb, entries);

Modified: trunk/src/host/qemu-neo1973/audio/audio.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -33,7 +33,9 @@
     AUD_FMT_U8,
     AUD_FMT_S8,
     AUD_FMT_U16,
-    AUD_FMT_S16
+    AUD_FMT_S16,
+    AUD_FMT_U32,
+    AUD_FMT_S32
 } audfmt_e;
 
 #ifdef WORDS_BIGENDIAN

Modified: trunk/src/host/qemu-neo1973/audio/audio_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/audio_template.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/audio_template.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -164,7 +164,7 @@
         [sw->info.nchannels == 2]
         [sw->info.sign]
         [sw->info.swap_endianness]
-        [sw->info.bits == 16];
+        [audio_bits_to_index (sw->info.bits)];
 
     sw->name = qemu_strdup (name);
     err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
@@ -288,7 +288,7 @@
         [hw->info.nchannels == 2]
         [hw->info.sign]
         [hw->info.swap_endianness]
-        [hw->info.bits == 16];
+        [audio_bits_to_index (hw->info.bits)];
 
     if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
         goto err1;

Modified: trunk/src/host/qemu-neo1973/audio/coreaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/coreaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/coreaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -294,7 +294,6 @@
     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
     UInt32 propertySize;
     int err;
-    int bits = 8;
     const char *typ = "playback";
     AudioValueRange frameRange;
 
@@ -305,10 +304,6 @@
         return -1;
     }
 
-    if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
-        bits = 16;
-    }
-
     audio_pcm_init_info (&hw->info, as);
 
     /* open default output device */

Modified: trunk/src/host/qemu-neo1973/audio/mixeng.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/mixeng.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/mixeng.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -82,6 +82,7 @@
 #undef IN_T
 #undef SHIFT
 
+/* Unsigned 16 bit */
 #define IN_T uint16_t
 #define IN_MIN 0
 #define IN_MAX USHRT_MAX
@@ -101,26 +102,72 @@
 #undef IN_T
 #undef SHIFT
 
-t_sample *mixeng_conv[2][2][2][2] = {
+/* Signed 32 bit */
+#define IN_T int32_t
+#define IN_MIN INT32_MIN
+#define IN_MAX INT32_MAX
+#define SIGNED
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef SIGNED
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+/* Unsigned 16 bit */
+#define IN_T uint32_t
+#define IN_MIN 0
+#define IN_MAX UINT32_MAX
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+t_sample *mixeng_conv[2][2][2][3] = {
     {
         {
             {
                 conv_natural_uint8_t_to_mono,
-                conv_natural_uint16_t_to_mono
+                conv_natural_uint16_t_to_mono,
+                conv_natural_uint32_t_to_mono
             },
             {
                 conv_natural_uint8_t_to_mono,
-                conv_swap_uint16_t_to_mono
+                conv_swap_uint16_t_to_mono,
+                conv_swap_uint32_t_to_mono,
             }
         },
         {
             {
                 conv_natural_int8_t_to_mono,
-                conv_natural_int16_t_to_mono
+                conv_natural_int16_t_to_mono,
+                conv_natural_int32_t_to_mono
             },
             {
                 conv_natural_int8_t_to_mono,
-                conv_swap_int16_t_to_mono
+                conv_swap_int16_t_to_mono,
+                conv_swap_int32_t_to_mono
             }
         }
     },
@@ -128,46 +175,54 @@
         {
             {
                 conv_natural_uint8_t_to_stereo,
-                conv_natural_uint16_t_to_stereo
+                conv_natural_uint16_t_to_stereo,
+                conv_natural_uint32_t_to_stereo
             },
             {
                 conv_natural_uint8_t_to_stereo,
-                conv_swap_uint16_t_to_stereo
+                conv_swap_uint16_t_to_stereo,
+                conv_swap_uint32_t_to_stereo
             }
         },
         {
             {
                 conv_natural_int8_t_to_stereo,
-                conv_natural_int16_t_to_stereo
+                conv_natural_int16_t_to_stereo,
+                conv_natural_int32_t_to_stereo
             },
             {
                 conv_natural_int8_t_to_stereo,
-                conv_swap_int16_t_to_stereo
+                conv_swap_int16_t_to_stereo,
+                conv_swap_int32_t_to_stereo,
             }
         }
     }
 };
 
-f_sample *mixeng_clip[2][2][2][2] = {
+f_sample *mixeng_clip[2][2][2][3] = {
     {
         {
             {
                 clip_natural_uint8_t_from_mono,
-                clip_natural_uint16_t_from_mono
+                clip_natural_uint16_t_from_mono,
+                clip_natural_uint32_t_from_mono
             },
             {
                 clip_natural_uint8_t_from_mono,
-                clip_swap_uint16_t_from_mono
+                clip_swap_uint16_t_from_mono,
+                clip_swap_uint32_t_from_mono
             }
         },
         {
             {
                 clip_natural_int8_t_from_mono,
-                clip_natural_int16_t_from_mono
+                clip_natural_int16_t_from_mono,
+                clip_natural_int32_t_from_mono
             },
             {
                 clip_natural_int8_t_from_mono,
-                clip_swap_int16_t_from_mono
+                clip_swap_int16_t_from_mono,
+                clip_swap_int32_t_from_mono
             }
         }
     },
@@ -175,21 +230,25 @@
         {
             {
                 clip_natural_uint8_t_from_stereo,
-                clip_natural_uint16_t_from_stereo
+                clip_natural_uint16_t_from_stereo,
+                clip_natural_uint32_t_from_stereo
             },
             {
                 clip_natural_uint8_t_from_stereo,
-                clip_swap_uint16_t_from_stereo
+                clip_swap_uint16_t_from_stereo,
+                clip_swap_uint32_t_from_stereo
             }
         },
         {
             {
                 clip_natural_int8_t_from_stereo,
-                clip_natural_int16_t_from_stereo
+                clip_natural_int16_t_from_stereo,
+                clip_natural_int32_t_from_stereo
             },
             {
                 clip_natural_int8_t_from_stereo,
-                clip_swap_int16_t_from_stereo
+                clip_swap_int16_t_from_stereo,
+                clip_swap_int32_t_from_stereo
             }
         }
     }

Modified: trunk/src/host/qemu-neo1973/audio/mixeng.h
===================================================================
--- trunk/src/host/qemu-neo1973/audio/mixeng.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/mixeng.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -37,8 +37,8 @@
                          int samples, volume_t *vol);
 typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
 
-extern t_sample *mixeng_conv[2][2][2][2];
-extern f_sample *mixeng_clip[2][2][2][2];
+extern t_sample *mixeng_conv[2][2][2][3];
+extern f_sample *mixeng_clip[2][2][2][3];
 
 void *st_rate_start (int inrate, int outrate);
 void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,

Modified: trunk/src/host/qemu-neo1973/audio/ossaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/ossaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/ossaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -21,10 +21,15 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#ifdef __OpenBSD__
+#include <soundcard.h>
+#else
 #include <sys/soundcard.h>
+#endif
 #include "vl.h"
 
 #define AUDIO_CAP "oss"

Modified: trunk/src/host/qemu-neo1973/audio/wavaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/wavaudio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/wavaudio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -41,7 +41,8 @@
     {
         44100,
         2,
-        AUD_FMT_S16
+        AUD_FMT_S16,
+        AUDIO_HOST_ENDIANNESS
     },
     "qemu.wav"
 };
@@ -131,6 +132,11 @@
     case AUD_FMT_U16:
         bits16 = 1;
         break;
+
+    case AUD_FMT_S32:
+    case AUD_FMT_U32:
+        dolog ("WAVE files can not handle 32bit formats\n");
+        return -1;
     }
 
     hdr[34] = bits16 ? 0x10 : 0x08;

Modified: trunk/src/host/qemu-neo1973/audio/wavcapture.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/wavcapture.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/audio/wavcapture.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -37,15 +37,15 @@
     if (wav->f) {
         le_store (rlen, rifflen, 4);
         le_store (dlen, datalen, 4);
-        
+
         qemu_fseek (wav->f, 4, SEEK_SET);
         qemu_put_buffer (wav->f, rlen, 4);
-        
+
         qemu_fseek (wav->f, 32, SEEK_CUR);
         qemu_put_buffer (wav->f, dlen, 4);
         qemu_fclose (wav->f);
     }
-    
+
     qemu_free (wav->path);
 }
 

Modified: trunk/src/host/qemu-neo1973/block-qcow2.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-qcow2.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-qcow2.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1886,6 +1886,8 @@
     int64_t table_offset;
     uint64_t data64;
     uint32_t data32;
+    int old_table_size;
+    int64_t old_table_offset;
 
     if (min_size <= s->refcount_table_size)
         return 0;
@@ -1931,10 +1933,14 @@
                     &data32, sizeof(data32)) != sizeof(data32))
         goto fail;
     qemu_free(s->refcount_table);
+    old_table_offset = s->refcount_table_offset;
+    old_table_size = s->refcount_table_size;
     s->refcount_table = new_table;
     s->refcount_table_size = new_table_size;
+    s->refcount_table_offset = table_offset;
 
     update_refcount(bs, table_offset, new_table_size2, 1);
+    free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
     return 0;
  fail:
     free_clusters(bs, table_offset, new_table_size2);

Modified: trunk/src/host/qemu-neo1973/block-raw.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-raw.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -914,8 +914,13 @@
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }
 
@@ -1278,8 +1283,13 @@
     s->hfile = CreateFile(filename, access_flags, 
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);
-    if (s->hfile == INVALID_HANDLE_VALUE) 
+    if (s->hfile == INVALID_HANDLE_VALUE) {
+        int err = GetLastError();
+
+        if (err == ERROR_ACCESS_DENIED)
+            return -EACCES;
         return -1;
+    }
     return 0;
 }
 

Modified: trunk/src/host/qemu-neo1973/block-vmdk.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vmdk.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block-vmdk.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -22,6 +22,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
 #include "vl.h"
 #include "block_int.h"
 
@@ -59,7 +60,7 @@
 #define L2_CACHE_SIZE 16
 
 typedef struct BDRVVmdkState {
-    int fd;
+    BlockDriverState *hd;
     int64_t l1_table_offset;
     int64_t l1_backup_table_offset;
     uint32_t *l1_table;
@@ -73,6 +74,7 @@
     uint32_t l2_cache_counts[L2_CACHE_SIZE];
 
     unsigned int cluster_sectors;
+    uint32_t parent_cid;
 } BDRVVmdkState;
 
 static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -89,27 +91,278 @@
         return 0;
 }
 
+#define CHECK_CID 1
+
+#define SECTOR_SIZE 512				
+#define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each
+#define HEADER_SIZE 512   			// first sector of 512 bytes 
+
+static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char desc[DESC_SIZE];
+    uint32_t cid;
+    char *p_name, *cid_str; 
+    size_t cid_str_size;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return 0;
+
+    if (parent) {
+        cid_str = "parentCID";
+        cid_str_size = sizeof("parentCID");
+    } else {
+        cid_str = "CID";
+        cid_str_size = sizeof("CID");
+    }
+
+    if ((p_name = strstr(desc,cid_str)) != 0) {
+        p_name += cid_str_size;
+        sscanf(p_name,"%x",&cid);
+    }
+
+    return cid;
+}
+
+static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
+    char *p_name, *tmp_str;
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    tmp_str = strstr(desc,"parentCID");
+    strcpy(tmp_desc, tmp_str);
+    if ((p_name = strstr(desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sprintf(p_name,"%x\n",cid);
+        strcat(desc,tmp_desc);
+    }
+
+    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+    return 0;
+}
+
+static int vmdk_is_cid_valid(BlockDriverState *bs)
+{
+#ifdef CHECK_CID
+    BDRVVmdkState *s = bs->opaque;
+    BlockDriverState *p_bs = s->hd->backing_hd;
+    uint32_t cur_pcid;
+
+    if (p_bs) {
+        cur_pcid = vmdk_read_cid(p_bs,0);
+        if (s->parent_cid != cur_pcid)
+            // CID not valid
+            return 0;
+    }
+#endif
+    // CID valid
+    return 1;
+}
+
+static int vmdk_snapshot_create(const char *filename, const char *backing_file)
+{
+    int snp_fd, p_fd;
+    uint32_t p_cid;
+    char *p_name, *gd_buf, *rgd_buf; 
+    const char *real_filename, *temp_str;
+    VMDK4Header header;
+    uint32_t gde_entries, gd_size;
+    int64_t gd_offset, rgd_offset, capacity, gt_size;
+    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
+    char *desc_template =
+    "# Disk DescriptorFile\n"
+    "version=1\n"
+    "CID=%x\n"
+    "parentCID=%x\n"
+    "createType=\"monolithicSparse\"\n"
+    "parentFileNameHint=\"%s\"\n"
+    "\n"
+    "# Extent description\n"
+    "RW %lu SPARSE \"%s\"\n"
+    "\n"
+    "# The Disk Data Base \n"
+    "#DDB\n"
+    "\n";
+
+    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
+    if (snp_fd < 0)
+        return -1;
+    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
+    if (p_fd < 0) {
+        close(snp_fd);
+        return -1;
+    }
+
+    /* read the header */
+    if (lseek(p_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
+        goto fail;
+
+    /* write the header */
+    if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, hdr, HEADER_SIZE) == -1)
+        goto fail;
+
+    memset(&header, 0, sizeof(header));
+    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
+
+    ftruncate(snp_fd, header.grain_offset << 9);
+    /* the descriptor offset = 0x200 */
+    if (lseek(p_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
+        goto fail;
+
+    if ((p_name = strstr(p_desc,"CID")) != 0) {
+        p_name += sizeof("CID");
+        sscanf(p_name,"%x",&p_cid);
+    }
+
+    real_filename = filename;
+    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, '/')) != NULL)
+        real_filename = temp_str + 1;
+    if ((temp_str = strrchr(real_filename, ':')) != NULL)
+        real_filename = temp_str + 1;
+
+    sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
+            , (uint32_t)header.capacity, real_filename);
+
+    /* write the descriptor */
+    if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
+        goto fail;
+    if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
+        goto fail;
+
+    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table
+    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table
+    capacity = header.capacity * SECTOR_SIZE;       // Extent size
+    /*
+     * Each GDE span 32M disk, means:
+     * 512 GTE per GT, each GTE points to grain
+     */
+    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
+    if (!gt_size)
+        goto fail;
+    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde 
+    gd_size = gde_entries * sizeof(uint32_t);
+
+    /* write RGD */
+    rgd_buf = qemu_malloc(gd_size);
+    if (!rgd_buf)
+        goto fail;
+    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (read(p_fd, rgd_buf, gd_size) != gd_size)
+        goto fail_rgd;
+    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
+        goto fail_rgd;
+    if (write(snp_fd, rgd_buf, gd_size) == -1)
+        goto fail_rgd;
+    qemu_free(rgd_buf);
+
+    /* write GD */
+    gd_buf = qemu_malloc(gd_size);
+    if (!gd_buf)
+        goto fail_rgd;
+    if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (read(p_fd, gd_buf, gd_size) != gd_size)
+        goto fail_gd;
+    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
+        goto fail_gd;
+    if (write(snp_fd, gd_buf, gd_size) == -1)
+        goto fail_gd;
+    qemu_free(gd_buf);
+
+    close(p_fd);
+    close(snp_fd);
+    return 0;
+
+    fail_gd:
+    qemu_free(gd_buf);
+    fail_rgd:   
+    qemu_free(rgd_buf);
+    fail:
+    close(p_fd);
+    close(snp_fd);
+    return -1;
+}
+
+static void vmdk_parent_close(BlockDriverState *bs)
+{
+    if (bs->backing_hd)
+        bdrv_close(bs->backing_hd);
+}
+
+
+static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
+{
+    BDRVVmdkState *s = bs->opaque;
+    char *p_name; 
+    char desc[DESC_SIZE];
+    char parent_img_name[1024];
+
+    /* the descriptor offset = 0x200 */
+    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+        return -1;
+
+    if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
+        char *end_name;
+        struct stat file_buf;
+
+        p_name += sizeof("parentFileNameHint") + 1;
+        if ((end_name = strchr(p_name,'\"')) == 0)
+            return -1;
+                
+        strncpy(s->hd->backing_file, p_name, end_name - p_name);
+        if (stat(s->hd->backing_file, &file_buf) != 0) {
+            path_combine(parent_img_name, sizeof(parent_img_name),
+                         filename, s->hd->backing_file);
+        } else {
+            strcpy(parent_img_name, s->hd->backing_file);
+        }
+
+        s->hd->backing_hd = bdrv_new("");
+        if (!s->hd->backing_hd) {
+            failure:
+            bdrv_close(s->hd);
+            return -1;
+        }
+        if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
+            goto failure;
+    }
+
+    return 0;
+}
+
 static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVVmdkState *s = bs->opaque;
-    int fd, i;
     uint32_t magic;
-    int l1_size;
+    int l1_size, i, ret;
 
-    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
-    if (fd < 0) {
-        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
-        if (fd < 0)
-            return -1;
-        bs->read_only = 1;
-    }
-    if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (ret < 0)
+        return ret;
+    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
         goto fail;
+
     magic = be32_to_cpu(magic);
     if (magic == VMDK3_MAGIC) {
         VMDK3Header header;
-        if (read(fd, &header, sizeof(header)) != 
-            sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         s->cluster_sectors = le32_to_cpu(header.granularity);
         s->l2_size = 1 << 9;
@@ -120,8 +373,8 @@
         s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
     } else if (magic == VMDK4_MAGIC) {
         VMDK4Header header;
-        
-        if (read(fd, &header, sizeof(header)) != sizeof(header))
+
+        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
             goto fail;
         bs->total_sectors = le64_to_cpu(header.capacity);
         s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -133,18 +386,23 @@
             / s->l1_entry_sectors;
         s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
         s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
+
+        // try to open parent images, if exist
+        if (vmdk_parent_open(bs, filename) != 0)
+            goto fail;
+        // write the CID once after the image creation
+        s->parent_cid = vmdk_read_cid(bs,1);
     } else {
         goto fail;
     }
+
     /* read the L1 table */
     l1_size = s->l1_size * sizeof(uint32_t);
     s->l1_table = qemu_malloc(l1_size);
     if (!s->l1_table)
         goto fail;
-    if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
+    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
         goto fail;
-    if (read(fd, s->l1_table, l1_size) != l1_size)
-        goto fail;
     for(i = 0; i < s->l1_size; i++) {
         le32_to_cpus(&s->l1_table[i]);
     }
@@ -153,10 +411,8 @@
         s->l1_backup_table = qemu_malloc(l1_size);
         if (!s->l1_backup_table)
             goto fail;
-        if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
+        if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
             goto fail;
-        if (read(fd, s->l1_backup_table, l1_size) != l1_size)
-            goto fail;
         for(i = 0; i < s->l1_size; i++) {
             le32_to_cpus(&s->l1_backup_table[i]);
         }
@@ -165,16 +421,43 @@
     s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
     if (!s->l2_cache)
         goto fail;
-    s->fd = fd;
     return 0;
  fail:
     qemu_free(s->l1_backup_table);
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(fd);
+    bdrv_delete(s->hd);
     return -1;
 }
 
+static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
+
+static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
+                             uint64_t offset, int allocate)
+{
+    uint64_t parent_cluster_offset;
+    BDRVVmdkState *s = bs->opaque;
+    uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
+
+    // we will be here if it's first write on non-exist grain(cluster).
+    // try to read from parent image, if exist
+    if (s->hd->backing_hd) {
+        BDRVVmdkState *ps = s->hd->backing_hd->opaque;
+
+        if (!vmdk_is_cid_valid(bs))
+            return -1;
+        parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
+        if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != 
+                                                                            ps->cluster_sectors*512)
+            return -1;
+
+        if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) != 
+                                                                            sizeof(whole_grain))
+            return -1;
+    }
+    return 0;
+}
+
 static uint64_t get_cluster_offset(BlockDriverState *bs,
                                    uint64_t offset, int allocate)
 {
@@ -212,34 +495,41 @@
         }
     }
     l2_table = s->l2_cache + (min_index * s->l2_size);
-    lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
-    if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) != 
-        s->l2_size * sizeof(uint32_t))
+    if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) != 
+                                                                        s->l2_size * sizeof(uint32_t))
         return 0;
+
     s->l2_cache_offsets[min_index] = l2_offset;
     s->l2_cache_counts[min_index] = 1;
  found:
     l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
     cluster_offset = le32_to_cpu(l2_table[l2_index]);
     if (!cluster_offset) {
+        struct stat file_buf;
+
         if (!allocate)
             return 0;
-        cluster_offset = lseek(s->fd, 0, SEEK_END);
-        ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
+        stat(s->hd->filename, &file_buf);
+        cluster_offset = file_buf.st_size;
+        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
         cluster_offset >>= 9;
         /* update L2 table */
         tmp = cpu_to_le32(cluster_offset);
         l2_table[l2_index] = tmp;
-        lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+        if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                        &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         /* update backup L2 table */
         if (s->l1_backup_table_offset != 0) {
             l2_offset = s->l1_backup_table[l1_index];
-            lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
-            if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+            if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
+                            &tmp, sizeof(tmp)) != sizeof(tmp))
                 return 0;
         }
+
+        if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
+            return 0;
     }
     cluster_offset <<= 9;
     return cluster_offset;
@@ -265,9 +555,9 @@
                     uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n, ret;
     uint64_t cluster_offset;
-    
+
     while (nb_sectors > 0) {
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
         index_in_cluster = sector_num % s->cluster_sectors;
@@ -275,11 +565,18 @@
         if (n > nb_sectors)
             n = nb_sectors;
         if (!cluster_offset) {
-            memset(buf, 0, 512 * n);
+            // try to read from parent image, if exist
+            if (s->hd->backing_hd) {
+                if (!vmdk_is_cid_valid(bs))
+                    return -1;
+                ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
+                if (ret < 0)
+                    return -1;
+            } else {
+                memset(buf, 0, 512 * n);
+            }
         } else {
-            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-            ret = read(s->fd, buf, n * 512);
-            if (ret != n * 512) 
+            if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
                 return -1;
         }
         nb_sectors -= n;
@@ -293,8 +590,9 @@
                      const uint8_t *buf, int nb_sectors)
 {
     BDRVVmdkState *s = bs->opaque;
-    int ret, index_in_cluster, n;
+    int index_in_cluster, n;
     uint64_t cluster_offset;
+    static int cid_update = 0;
 
     while (nb_sectors > 0) {
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -304,13 +602,17 @@
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
         if (!cluster_offset)
             return -1;
-        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
-        ret = write(s->fd, buf, n * 512);
-        if (ret != n * 512)
+        if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
             return -1;
         nb_sectors -= n;
         sector_num += n;
         buf += n * 512;
+
+        // update CID on the first write every time the virtual disk is opened
+        if (!cid_update) {
+            vmdk_write_cid(bs, time(NULL));
+            cid_update++;
+        }
     }
     return 0;
 }
@@ -334,7 +636,7 @@
         "# The Disk Data Base \n"
         "#DDB\n"
         "\n"
-        "ddb.virtualHWVersion = \"3\"\n"
+        "ddb.virtualHWVersion = \"4\"\n"
         "ddb.geometry.cylinders = \"%lu\"\n"
         "ddb.geometry.heads = \"16\"\n"
         "ddb.geometry.sectors = \"63\"\n"
@@ -343,6 +645,9 @@
     const char *real_filename, *temp_str;
 
     /* XXX: add support for backing file */
+    if (backing_file) {
+        return vmdk_snapshot_create(filename, backing_file);
+    }
 
     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
               0644);
@@ -421,15 +726,18 @@
 static void vmdk_close(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
+
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
-    close(s->fd);
+    bdrv_delete(s->hd);
+    // try to close parent image, if exist
+    vmdk_parent_close(s->hd);
 }
 
 static void vmdk_flush(BlockDriverState *bs)
 {
     BDRVVmdkState *s = bs->opaque;
-    fsync(s->fd);
+    bdrv_flush(s->hd);
 }
 
 BlockDriver bdrv_vmdk = {

Modified: trunk/src/host/qemu-neo1973/block.c
===================================================================
--- trunk/src/host/qemu-neo1973/block.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/block.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -322,8 +322,8 @@
                BlockDriver *drv)
 {
     int ret, open_flags;
-    char tmp_filename[1024];
-    char backing_filename[1024];
+    char tmp_filename[PATH_MAX];
+    char backing_filename[PATH_MAX];
     
     bs->read_only = 0;
     bs->is_temporary = 0;

Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/configure	2007-05-11 23:44:50 UTC (rev 1948)
@@ -50,10 +50,13 @@
   mips)
     cpu="mips"
   ;;
+  mips64)
+    cpu="mips64"
+  ;;
   s390)
     cpu="s390"
   ;;
-  sparc|sun4[muv])
+  sparc|sun4[cdmuv])
     cpu="sparc"
   ;;
   sparc64)
@@ -94,7 +97,8 @@
 check_gfx="yes"
 check_gcc="yes"
 softmmu="yes"
-user="no"
+linux_user="no"
+darwin_user="no"
 build_docs="no"
 gadgetfs="no"
 uname_release=""
@@ -127,15 +131,38 @@
 Darwin)
 bsd="yes"
 darwin="yes"
+darwin_user="yes"
+cocoa="yes"
+coreaudio="yes"
 OS_CFLAGS="-mdynamic-no-pic"
 ;;
 SunOS)
-solaris="yes"
+    solaris="yes"
+    make="gmake"
+    install="ginstall"
+    needs_libsunmath="no"
+    solarisrev=`uname -r | cut -f2 -d.`
+    if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+        if test "$solarisrev" -le 9 ; then
+            if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
+                needs_libsunmath="yes"
+            else
+                echo "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without"
+                echo "libsunmath from the Sun Studio compilers tools, due to a lack of"
+                echo "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86"
+                echo "Studio 11 can be downloaded from www.sun.com."
+                exit 1
+            fi
+        fi
+        if test "$solarisrev" -ge 9 ; then
+            kqemu="yes"
+        fi
+    fi
 ;;
 *)
 oss="yes"
 linux="yes"
-user="yes"
+linux_user="yes"
 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     kqemu="yes"
 fi
@@ -148,18 +175,6 @@
   fi
 fi
 
-if [ "$solaris" = "yes" ] ; then
-    make="gmake"
-    install="ginstall"
-    solarisrev=`uname -r | cut -f2 -d.`
-fi
-
-if [ "$bsd" = "yes" -o "$solaris" = "yes" -o "$mingw32" = "yes" ] ; then
-    AIOLIBS=
-else
-    AIOLIBS="-lrt"
-fi
-
 # find source path
 source_path=`dirname "$0"`
 if [ -z "$source_path" ]; then
@@ -222,7 +237,7 @@
   ;;
   --fmod-inc=*) fmod_inc="$optarg"
   ;;
-  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
+  --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
   ;;
   --disable-slirp) slirp="no"
   ;;
@@ -242,19 +257,64 @@
   ;;
   --enable-system) softmmu="yes"
   ;;
-  --disable-user) user="no"
+  --disable-linux-user) linux_user="no"
   ;;
-  --enable-user) user="yes"
+  --enable-linux-user) linux_user="yes"
   ;;
+  --disable-darwin-user) darwin_user="no"
+  ;;
+  --enable-darwin-user) darwin_user="yes"
+  ;;
   --enable-uname-release=*) uname_release="$optarg"
   ;;
+  --sparc_cpu=*)
+      sparc_cpu="$optarg"
+      case $sparc_cpu in
+        v7|v8) SP_CFLAGS="-m32 -mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+                 target_cpu="sparc"; cpu="sparc" ;;
+        v8plus|v8plusa) SP_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+                 target_cpu="sparc"; cpu="sparc" ;;
+        v9)    SP_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m64"
+                 target_cpu="sparc64"; cpu="sparc64" ;;
+        *)     echo "undefined SPARC architecture. Exiting";exit 1;;
+      esac
+  ;;
   esac
 done
 
+if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
+    AIOLIBS=
+else
+    AIOLIBS="-lrt"
+fi
+
 # default flags for all hosts
 CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
 LDFLAGS="$LDFLAGS -g"
 
+#
+# If cpu ~= sparc and  sparc_cpu hasn't been defined, plug in the right
+# ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
+#
+case $cpu in
+    sparc) if test -z "$sparc_cpu" ; then
+               ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__"
+               ARCH_LDFLAGS="-m32"
+           else
+               ARCH_CFLAGS="${SP_CFLAGS}"
+               ARCH_LDFLAGS="${SP_LDFLAGS}"
+           fi
+           ;;
+    sparc64) if test -z "$sparc_cpu" ; then
+               ARCH_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__"
+               ARCH_LDFLAGS="-m64"
+           else
+               ARCH_CFLAGS="${SP_CFLAGS}"
+               ARCH_LDFLAGS="${SP_LDFLAGS}"
+           fi
+           ;;
+esac
+
 if test x"$show_help" = x"yes" ; then
 cat << EOF
 
@@ -286,14 +346,17 @@
 echo "  --enable-coreaudio       enable Coreaudio audio driver"
 echo "  --enable-alsa            enable ALSA audio driver"
 echo "  --enable-fmod            enable FMOD audio driver"
-echo "  --enabled-dsound         enable DirectSound audio driver"
+echo "  --enable-dsound          enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
-echo "  --enable-user            enable all linux usermode emulation targets"
-echo "  --disable-user           disable all linux usermode emulation targets"
+echo "  --enable-linux-user      enable all linux usermode emulation targets"
+echo "  --disable-linux-user     disable all linux usermode emulation targets"
+echo "  --enable-darwin-user     enable all darwin usermode emulation targets"
+echo "  --disable-darwin-user    disable all darwin usermode emulation targets"
 echo "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
+echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -308,7 +371,7 @@
 int main(void) {}
 EOF
 
-if $cc -c -o $TMPO $TMPC 2>/dev/null ; then
+if $cc -c -o $TMPO $TMPC 2> /dev/null ; then
   : C compiler works ok
 else
     echo "ERROR: \"$cc\" either does not exist or does not work"
@@ -332,20 +395,15 @@
 #endif
 int main(){return 0;}
 EOF
-    check_cc() {
-	which "$1" >&/dev/null
-	return $?
-    }
-
-    if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
+    if "$cc" -o $TMPE $TMPC 2> /dev/null ; then
 	echo "WARNING: \"$cc\" looks like gcc 4.x"
 	found_compat_cc="no"
 	if test "$gcc3_search" = "yes" ; then
 	    echo "Looking for gcc 3.x"
 	    for compat_cc in $gcc3_list ; do
-		if check_cc "$compat_cc" ; then
+		if "$cross_prefix$compat_cc" --version > /dev/null 2>&1 ; then
 		    echo "Found \"$compat_cc\""
-		    cc="$compat_cc"
+		    cc="$cross_prefix$compat_cc"
 		    found_compat_cc="yes"
 		    break
 		fi
@@ -407,12 +465,16 @@
 if test -z "$target_list" ; then
 # these targets are portable
     if [ "$softmmu" = "yes" ] ; then
-        target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
+        target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu "
     fi
 # the following are Linux specific
-    if [ "$user" = "yes" ] ; then
-        target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user m68k-user $target_list"
+    if [ "$linux_user" = "yes" ] ; then
+        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user $target_list"
     fi
+# the following are Darwin specific
+    if [ "$darwin_user" = "yes" ] ; then
+        target_list="i386-darwin-user ppc-darwin-user $target_list"
+    fi
 else
     target_list=`echo "$target_list" | sed -e 's/,/ /g'`
 fi
@@ -433,7 +495,7 @@
 }
 EOF
 
-if $cc -o $TMPE $TMPC 2>/dev/null ; then
+if $cc -o $TMPE $TMPC 2> /dev/null ; then
 $TMPE && bigendian="yes"
 else
 echo big/little test failed
@@ -442,7 +504,7 @@
 else
 
 # if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "mips64" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
     bigendian="yes"
 fi
 
@@ -460,11 +522,6 @@
 }
 EOF
 
-have_gcc3_options="no"
-if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
-   have_gcc3_options="yes"
-fi
-
 ##########################################
 # SDL probe
 
@@ -493,14 +550,16 @@
 if test "$_sdlversion" -lt 121 ; then
 sdl_too_old=yes
 else
-sdl=yes
+ if test "$cocoa" = "no" ; then
+   sdl=yes
+ fi
 fi
 
 # static link with sdl ?
 if test "$sdl" = "yes" ; then
 aa="no"
-`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
-sdl_static_libs=`$sdl_config --static-libs`
+`$sdl_config --static-libs 2>/dev/null | grep \\\-laa > /dev/null` && aa="yes"
+sdl_static_libs=`$sdl_config --static-libs 2>/dev/null`
 if [ "$aa" = "yes" ] ; then
   sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
 fi
@@ -514,6 +573,13 @@
 fi # sdl compile test
 
 fi # cross compilation
+
+else
+ # Make sure to disable cocoa if sdl was set
+ if test "$sdl" = "yes" ; then
+   cocoa="no"
+   coreaudio="no"
+ fi
 fi # -z $sdl
 
 ##########################################
@@ -536,27 +602,28 @@
 fi
 
 # Check if tools are available to build documentation.
-if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
+if [ -x "`which texi2html 2>/dev/null`" ] && \
+   [ -x "`which pod2man 2>/dev/null`" ]; then
   build_docs="yes"
 fi
 
 if test "$mingw32" = "yes" ; then
-if test -z "$prefix" ; then
-    prefix="/c/Program Files/Qemu"
-fi
-mandir="$prefix"
-datadir="$prefix"
-docdir="$prefix"
-bindir="$prefix"
+  if test -z "$prefix" ; then
+      prefix="/c/Program Files/Qemu"
+  fi
+  mansuffix=""
+  datasuffix=""
+  docsuffix=""
+  binsuffix=""
 else
-if test -z "$prefix" ; then
-    prefix="/usr/local"
+  if test -z "$prefix" ; then
+      prefix="/usr/local"
+  fi
+  mansuffix="/share/man"
+  datasuffix="/share/qemu"
+  docsuffix="/share/doc/qemu"
+  binsuffix="/bin"
 fi
-mandir="$prefix/share/man"
-datadir="$prefix/share/qemu"
-docdir="$prefix/share/doc/qemu"
-bindir="$prefix/bin"
-fi
 
 ##########################################
 # usb_gadgetfs headers
@@ -571,10 +638,10 @@
 fi
 
 echo "Install prefix    $prefix"
-echo "BIOS directory    $datadir"
-echo "binary directory  $bindir"
+echo "BIOS directory    $prefix$datasuffix"
+echo "binary directory  $prefix$binsuffix"
 if test "$mingw32" = "no" ; then
-echo "Manual directory  $mandir"
+echo "Manual directory  $prefix$mansuffix"
 echo "ELF interp prefix $interp_prefix"
 fi
 echo "Source path       $source_path"
@@ -613,6 +680,9 @@
     fmod_support=""
 fi
 echo "FMOD support      $fmod $fmod_support"
+if test -n "$sparc_cpu"; then
+    echo "Target Sparc Arch $sparc_cpu"
+fi
 echo "kqemu support     $kqemu"
 echo "Documentation     $build_docs"
 [ ! -z "$uname_release" ] && \
@@ -634,21 +704,21 @@
 echo "/* Automatically generated by configure - do not modify */" > $config_h
 
 echo "prefix=$prefix" >> $config_mak
-echo "bindir=$bindir" >> $config_mak
-echo "mandir=$mandir" >> $config_mak
-echo "datadir=$datadir" >> $config_mak
-echo "docdir=$docdir" >> $config_mak
-echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
+echo "bindir=\${prefix}$binsuffix" >> $config_mak
+echo "mandir=\${prefix}$mansuffix" >> $config_mak
+echo "datadir=\${prefix}$datasuffix" >> $config_mak
+echo "docdir=\${prefix}$docsuffix" >> $config_mak
+echo "#define CONFIG_QEMU_SHAREDIR \"$prefix$datasuffix\"" >> $config_h
 echo "MAKE=$make" >> $config_mak
 echo "INSTALL=$install" >> $config_mak
 echo "CC=$cc" >> $config_mak
-if test "$have_gcc3_options" = "yes" ; then
-  echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
-fi
 echo "HOST_CC=$host_cc" >> $config_mak
 echo "AR=$ar" >> $config_mak
 echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
 echo "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
+echo "OS_LDFLAGS=$OS_LDFLAGS" >> $config_mak
+echo "ARCH_CFLAGS=$ARCH_CFLAGS" >> $config_mak
+echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $config_mak
 echo "CFLAGS=$CFLAGS" >> $config_mak
 echo "LDFLAGS=$LDFLAGS" >> $config_mak
 echo "EXESUF=$EXESUF" >> $config_mak
@@ -671,6 +741,9 @@
 elif test "$cpu" = "mips" ; then
   echo "ARCH=mips" >> $config_mak
   echo "#define HOST_MIPS 1" >> $config_h
+elif test "$cpu" = "mips64" ; then
+  echo "ARCH=mips64" >> $config_mak
+  echo "#define HOST_MIPS64 1" >> $config_h
 elif test "$cpu" = "s390" ; then
   echo "ARCH=s390" >> $config_mak
   echo "#define HOST_S390 1" >> $config_h
@@ -690,7 +763,7 @@
   echo "ARCH=m68k" >> $config_mak
   echo "#define HOST_M68K 1" >> $config_h
 else
-  echo "Unsupported CPU"
+  echo "Unsupported CPU = $cpu"
   exit 1
 fi
 if test "$bigendian" = "yes" ; then
@@ -701,8 +774,14 @@
 if test "$mingw32" = "yes" ; then
   echo "CONFIG_WIN32=yes" >> $config_mak
   echo "#define CONFIG_WIN32 1" >> $config_h
-elif test -f "/usr/include/byteswap.h" ; then
-  echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+else
+  cat > $TMPC << EOF
+#include <byteswap.h>
+int main(void) { return bswap_32(0); }
+EOF
+  if $cc -o $TMPE $TMPC 2> /dev/null ; then
+    echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+  fi
 fi
 if test "$darwin" = "yes" ; then
   echo "CONFIG_DARWIN=yes" >> $config_mak
@@ -711,7 +790,15 @@
 if test "$solaris" = "yes" ; then
   echo "CONFIG_SOLARIS=yes" >> $config_mak
   echo "#define HOST_SOLARIS $solarisrev" >> $config_h
+  if test "$needs_libsunmath" = "yes" ; then
+    echo "NEEDS_LIBSUNMATH=yes" >> $config_mak
+    echo "#define NEEDS_LIBSUNMATH 1" >> $config_h
+  fi
 fi
+if test -n "$sparc_cpu"; then
+  echo "CONFIG__sparc_${sparc_cpu}__=yes" >> $config_mak
+  echo "#define __sparc_${sparc_cpu}__ 1" >> $config_h
+fi
 if test "$gdbstub" = "yes" ; then
   echo "CONFIG_GDBSTUB=yes" >> $config_mak
   echo "#define CONFIG_GDBSTUB 1" >> $config_h
@@ -795,7 +882,9 @@
 [ "$target_cpu" = "sparc64" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc" ] && target_bigendian=yes
 [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
+[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
 [ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "mips64" ] && target_bigendian=yes
 [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
 [ "$target_cpu" = "m68k" ] && target_bigendian=yes
 target_softmmu="no"
@@ -807,6 +896,16 @@
   target_user_only="yes"
 fi
 
+target_linux_user="no"
+if expr $target : '.*-linux-user' > /dev/null ; then
+  target_linux_user="yes"
+fi
+
+target_darwin_user="no"
+if expr $target : '.*-darwin-user' > /dev/null ; then
+  target_darwin_user="yes"
+fi
+
 if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
         -a "$sdl" = "no" -a "$cocoa" = "no" ; then
     echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
@@ -819,7 +918,7 @@
 
 mkdir -p $target_dir
 mkdir -p $target_dir/fpu
-if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
+if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
   mkdir -p $target_dir/nwfpe
 fi
 if test "$target_user_only" = "no" ; then
@@ -874,6 +973,11 @@
   echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
   echo "#define TARGET_PPC 1" >> $config_h
   echo "#define TARGET_PPC64 1" >> $config_h
+elif test "$target_cpu" = "ppcemb" ; then
+  echo "TARGET_ARCH=ppcemb" >> $config_mak
+  echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
+  echo "#define TARGET_PPC 1" >> $config_h
+  echo "#define TARGET_PPCEMB 1" >> $config_h
 elif test "$target_cpu" = "x86_64" ; then
   echo "TARGET_ARCH=x86_64" >> $config_mak
   echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
@@ -888,6 +992,13 @@
   echo "#define TARGET_MIPS 1" >> $config_h
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
   echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
+elif test "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el" ; then
+  echo "TARGET_ARCH=mips64" >> $config_mak
+  echo "#define TARGET_ARCH \"mips64\"" >> $config_h
+  echo "#define TARGET_MIPS 1" >> $config_h
+  echo "#define TARGET_MIPS64 1" >> $config_h
+  echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
+  echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
 elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
   echo "TARGET_ARCH=sh4" >> $config_mak
   echo "#define TARGET_ARCH \"sh4\"" >> $config_h
@@ -898,6 +1009,10 @@
   echo "#define TARGET_ARCH \"m68k\"" >> $config_h
   echo "#define TARGET_M68K 1" >> $config_h
   bflt="yes"
+elif test "$target_cpu" = "alpha" ; then
+  echo "TARGET_ARCH=alpha" >> $config_mak
+  echo "#define TARGET_ARCH \"alpha\"" >> $config_h
+  echo "#define TARGET_ALPHA 1" >> $config_h
 else
   echo "Unsupported target CPU"
   exit 1
@@ -914,6 +1029,14 @@
   echo "CONFIG_USER_ONLY=yes" >> $config_mak
   echo "#define CONFIG_USER_ONLY 1" >> $config_h
 fi
+if test "$target_linux_user" = "yes" ; then
+  echo "CONFIG_LINUX_USER=yes" >> $config_mak
+  echo "#define CONFIG_LINUX_USER 1" >> $config_h
+fi
+if test "$target_darwin_user" = "yes" ; then
+  echo "CONFIG_DARWIN_USER=yes" >> $config_mak
+  echo "#define CONFIG_DARWIN_USER 1" >> $config_h
+fi
 
 if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak

Modified: trunk/src/host/qemu-neo1973/console.c
===================================================================
--- trunk/src/host/qemu-neo1973/console.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/console.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -121,6 +121,7 @@
     int total_height;
     int backscroll_height;
     int x, y;
+    int x_saved, y_saved;
     int y_displayed;
     int y_base;
     TextAttributes t_attrib_default; /* default text attributes */
@@ -131,10 +132,7 @@
     int esc_params[MAX_ESC_PARAMS];
     int nb_esc_params;
 
-    /* kbd read handler */
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
+    CharDriverState *chr;
     /* fifo for key pressed */
     QEMUFIFO out_fifo;
     uint8_t out_fifo_buf[16];
@@ -147,7 +145,7 @@
 
 void vga_hw_update(void)
 {
-    if (active_console->hw_update)
+    if (active_console && active_console->hw_update)
         active_console->hw_update(active_console->hw);
 }
 
@@ -535,21 +533,24 @@
     int y, y1;
 
     if (s == active_console) {
+        int x = s->x;
+        if (x >= s->width) {
+            x = s->width - 1;
+        }
         y1 = (s->y_base + s->y) % s->total_height;
         y = y1 - s->y_displayed;
         if (y < 0)
             y += s->total_height;
         if (y < s->height) {
-            c = &s->cells[y1 * s->width + s->x];
+            c = &s->cells[y1 * s->width + x];
             if (show) {
                 TextAttributes t_attrib = s->t_attrib_default;
                 t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
-                vga_putcharxy(s->ds, s->x, y, c->ch, &t_attrib);
+                vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
             } else {
-                vga_putcharxy(s->ds, s->x, y, c->ch, 
-                              &(c->t_attrib));
+                vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
             }
-            dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, 
+            dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT, 
                        FONT_WIDTH, FONT_HEIGHT);
         }
     }
@@ -659,10 +660,6 @@
 {
     int i;
 
-    if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
-        s->t_attrib = s->t_attrib_default;
-        return;
-    }
     for (i=0; i<s->nb_esc_params; i++) {
         switch (s->esc_params[i]) {
             case 0: /* reset all console attributes to default */
@@ -752,10 +749,21 @@
     }
 }
 
+static void console_clear_xy(TextConsole *s, int x, int y)
+{
+    int y1 = (s->y_base + y) % s->total_height;
+    TextCell *c = &s->cells[y1 * s->width + x];
+    c->ch = ' ';
+    c->t_attrib = s->t_attrib_default;
+    c++;
+    update_xy(s, x, y);
+}
+
 static void console_putchar(TextConsole *s, int ch)
 {
     TextCell *c;
-    int y1, i, x;
+    int y1, i;
+    int x, y;
 
     switch(s->state) {
     case TTY_STATE_NORM:
@@ -781,20 +789,27 @@
         case '\a':  /* alert aka. bell */
             /* TODO: has to be implemented */
             break;
+        case 14:
+            /* SI (shift in), character set 0 (ignored) */
+            break;
+        case 15:
+            /* SO (shift out), character set 1 (ignored) */
+            break;
         case 27:    /* esc (introducing an escape sequence) */
             s->state = TTY_STATE_ESC;
             break;
         default:
+            if (s->x >= s->width) {
+                /* line wrap */
+                s->x = 0;
+                console_put_lf(s);
+            }
             y1 = (s->y_base + s->y) % s->total_height;
             c = &s->cells[y1 * s->width + s->x];
             c->ch = ch;
             c->t_attrib = s->t_attrib;
             update_xy(s, s->x, s->y);
             s->x++;
-            if (s->x >= s->width) {
-                s->x = 0;
-                console_put_lf(s);
-            }
             break;
         }
         break;
@@ -818,32 +833,150 @@
             s->nb_esc_params++;
             if (ch == ';')
                 break;
+#ifdef DEBUG_CONSOLE
+            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
+                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
+#endif
             s->state = TTY_STATE_NORM;
             switch(ch) {
-            case 'D':
-                if (s->x > 0)
-                    s->x--;
+            case 'A':
+                /* move cursor up */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y -= s->esc_params[0];
+                if (s->y < 0) {
+                    s->y = 0;
+                }
                 break;
+            case 'B':
+                /* move cursor down */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->y += s->esc_params[0];
+                if (s->y >= s->height) {
+                    s->y = s->height - 1;
+                }
+                break;
             case 'C':
-                if (s->x < (s->width - 1))
-                    s->x++;
+                /* move cursor right */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x += s->esc_params[0];
+                if (s->x >= s->width) {
+                    s->x = s->width - 1;
+                }
                 break;
+            case 'D':
+                /* move cursor left */
+                if (s->esc_params[0] == 0) {
+                    s->esc_params[0] = 1;
+                }
+                s->x -= s->esc_params[0];
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'G':
+                /* move cursor to column */
+                s->x = s->esc_params[0] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                break;
+            case 'f':
+            case 'H':
+                /* move cursor to row, column */
+                s->x = s->esc_params[1] - 1;
+                if (s->x < 0) {
+                    s->x = 0;
+                }
+                s->y = s->esc_params[0] - 1;
+                if (s->y < 0) {
+                    s->y = 0;
+                }
+                break;
+            case 'J':
+                switch (s->esc_params[0]) {
+                case 0:
+                    /* clear to end of screen */
+                    for (y = s->y; y < s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x < s->x) {
+                                continue;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 1:
+                    /* clear from beginning of screen */
+                    for (y = 0; y <= s->y; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            if (y == s->y && x > s->x) {
+                                break;
+                            }
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                    break;
+                case 2:
+                    /* clear entire screen */
+                    for (y = 0; y <= s->height; y++) {
+                        for (x = 0; x < s->width; x++) {
+                            console_clear_xy(s, x, y);
+                        }
+                    }
+                break;
+                }
             case 'K':
+                switch (s->esc_params[0]) {
+                case 0:
                 /* clear to eol */
-                y1 = (s->y_base + s->y) % s->total_height;
                 for(x = s->x; x < s->width; x++) {
-                    c = &s->cells[y1 * s->width + x];
-                    c->ch = ' ';
-                    c->t_attrib = s->t_attrib_default;
-                    c++;
-                    update_xy(s, x, s->y);
+                        console_clear_xy(s, x, s->y);
                 }
                 break;
-            default:
+                case 1:
+                    /* clear from beginning of line */
+                    for (x = 0; x <= s->x; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
+                    break;
+                case 2:
+                    /* clear entire line */
+                    for(x = 0; x < s->width; x++) {
+                        console_clear_xy(s, x, s->y);
+                    }
                 break;
             }
+                break;
+            case 'm':
             console_handle_escape(s);
             break;
+            case 'n':
+                /* report cursor position */
+                /* TODO: send ESC[row;colR */
+                break;
+            case 's':
+                /* save cursor position */
+                s->x_saved = s->x;
+                s->y_saved = s->y;
+                break;
+            case 'u':
+                /* restore cursor position */
+                s->x = s->x_saved;
+                s->y = s->y_saved;
+                break;
+            default:
+#ifdef DEBUG_CONSOLE
+                fprintf(stderr, "unhandled escape character '%c'\n", ch);
+#endif
+                break;
+            }
+            break;
         }
     }
 }
@@ -884,16 +1017,6 @@
     return len;
 }
 
-static void console_chr_add_read_handler(CharDriverState *chr, 
-                                         IOCanRWHandler *fd_can_read, 
-                                         IOReadHandler *fd_read, void *opaque)
-{
-    TextConsole *s = chr->opaque;
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->fd_opaque = opaque;
-}
-
 static void console_send_event(CharDriverState *chr, int event)
 {
     TextConsole *s = chr->opaque;
@@ -915,14 +1038,14 @@
     int len;
     uint8_t buf[16];
     
-    len = s->fd_can_read(s->fd_opaque);
+    len = qemu_chr_can_read(s->chr);
     if (len > s->out_fifo.count)
         len = s->out_fifo.count;
     if (len > 0) {
         if (len > sizeof(buf))
             len = sizeof(buf);
         qemu_fifo_read(&s->out_fifo, buf, len);
-        s->fd_read(s->fd_opaque, buf, len);
+        qemu_chr_read(s->chr, buf, len);
     }
     /* characters are pending: we send them a bit later (XXX:
        horrible, should change char device API) */
@@ -973,7 +1096,7 @@
         } else {
                 *q++ = keysym;
         }
-        if (s->fd_read) {
+        if (s->chr->chr_read) {
             qemu_fifo_write(&s->out_fifo, buf, q - buf);
             kbd_send_chars(s);
         }
@@ -1049,9 +1172,9 @@
     }
     chr->opaque = s;
     chr->chr_write = console_puts;
-    chr->chr_add_read_handler = console_chr_add_read_handler;
     chr->chr_send_event = console_send_event;
 
+    s->chr = chr;
     s->out_fifo.buf = s->out_fifo_buf;
     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
     s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);

Modified: trunk/src/host/qemu-neo1973/cpu-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-all.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-all.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -20,7 +20,7 @@
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 
-#if defined(__arm__) || defined(__sparc__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
 #define WORDS_ALIGNED
 #endif
 
@@ -644,12 +644,14 @@
 #define lduw_code(p) lduw_raw(p)
 #define ldsw_code(p) ldsw_raw(p)
 #define ldl_code(p) ldl_raw(p)
+#define ldq_code(p) ldq_raw(p)
 
 #define ldub_kernel(p) ldub_raw(p)
 #define ldsb_kernel(p) ldsb_raw(p)
 #define lduw_kernel(p) lduw_raw(p)
 #define ldsw_kernel(p) ldsw_raw(p)
 #define ldl_kernel(p) ldl_raw(p)
+#define ldq_kernel(p) ldq_raw(p)
 #define ldfl_kernel(p) ldfl_raw(p)
 #define ldfq_kernel(p) ldfq_raw(p)
 #define stb_kernel(p, v) stb_raw(p, v)
@@ -746,6 +748,13 @@
 #define cpu_gen_code cpu_sh4_gen_code
 #define cpu_signal_handler cpu_sh4_signal_handler
 
+#elif defined(TARGET_ALPHA)
+#define CPUState CPUAlphaState
+#define cpu_init cpu_alpha_init
+#define cpu_exec cpu_alpha_exec
+#define cpu_gen_code cpu_alpha_gen_code
+#define cpu_signal_handler cpu_alpha_signal_handler
+
 #else
 
 #error unsupported target CPU
@@ -754,11 +763,17 @@
 
 #endif /* SINGLE_CPU_DEFINES */
 
+CPUState *cpu_copy(CPUState *env);
+
 void cpu_dump_state(CPUState *env, FILE *f, 
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags);
+void cpu_dump_statistics (CPUState *env, FILE *f,
+                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                          int flags);
 
-void cpu_abort(CPUState *env, const char *fmt, ...);
+void cpu_abort(CPUState *env, const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));
 extern CPUState *first_cpu;
 extern CPUState *cpu_single_env;
 extern int code_copy_enabled;
@@ -770,10 +785,13 @@
 #define CPU_INTERRUPT_FIQ    0x10 /* Fast interrupt pending.  */
 #define CPU_INTERRUPT_HALT   0x20 /* CPU halt wanted */
 #define CPU_INTERRUPT_SMI    0x40 /* (x86 only) SMI interrupt pending */
+#define CPU_INTERRUPT_DEBUG  0x80 /* Debug event occured.  */
 
 void cpu_interrupt(CPUState *s, int mask);
 void cpu_reset_interrupt(CPUState *env, int mask);
 
+int cpu_watchpoint_insert(CPUState *env, target_ulong addr);
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
 int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
 void cpu_single_step(CPUState *env, int enabled);
@@ -782,7 +800,7 @@
 /* Return the physical page corresponding to a virtual one. Use it
    only for debugging because no protection checks are done. Return -1
    if no page found. */
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
 
 #define CPU_LOG_TB_OUT_ASM (1 << 0) 
 #define CPU_LOG_TB_IN_ASM  (1 << 1)
@@ -848,6 +866,8 @@
                                   unsigned long size,
                                   unsigned long phys_offset);
 uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
+ram_addr_t qemu_ram_alloc(unsigned int size);
+void qemu_ram_free(ram_addr_t addr);
 int cpu_register_io_memory(int io_index,
                            CPUReadMemoryFunc **mem_read,
                            CPUWriteMemoryFunc **mem_write,
@@ -872,6 +892,7 @@
 uint32_t ldl_phys(target_phys_addr_t addr);
 uint64_t ldq_phys(target_phys_addr_t addr);
 void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
 void stb_phys(target_phys_addr_t addr, uint32_t val);
 void stw_phys(target_phys_addr_t addr, uint32_t val);
 void stl_phys(target_phys_addr_t addr, uint32_t val);
@@ -980,7 +1001,7 @@
     return val;
 }
 
-#elif defined(__sparc_v9__)
+#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
 
 static inline int64_t cpu_get_real_ticks (void)
 {
@@ -1001,10 +1022,31 @@
         return rval.i64;
 #endif
 }
+
+#elif defined(__mips__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+#if __mips_isa_rev >= 2
+    uint32_t count;
+    static uint32_t cyc_per_count = 0;
+
+    if (!cyc_per_count)
+        __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count));
+
+    __asm__ __volatile__("rdhwr %1, $2" : "=r" (count));
+    return (int64_t)(count * cyc_per_count);
 #else
+    /* FIXME */
+    static int64_t ticks = 0;
+    return ticks++;
+#endif
+}
+
+#else
 /* The host CPU doesn't have an easily accessible cycle counter.
-   Just return a monotonically increasing vlue.  This will be totally wrong,
-   but hopefully better than nothing.  */
+   Just return a monotonically increasing value.  This will be
+   totally wrong, but hopefully better than nothing.  */
 static inline int64_t cpu_get_real_ticks (void)
 {
     static int64_t ticks = 0;

Modified: trunk/src/host/qemu-neo1973/cpu-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-defs.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-defs.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -44,10 +44,12 @@
 typedef int32_t target_long;
 typedef uint32_t target_ulong;
 #define TARGET_FMT_lx "%08x"
+#define TARGET_FMT_ld "%d"
 #elif TARGET_LONG_SIZE == 8
 typedef int64_t target_long;
 typedef uint64_t target_ulong;
 #define TARGET_FMT_lx "%016" PRIx64
+#define TARGET_FMT_ld "%" PRId64
 #else
 #error TARGET_LONG_SIZE undefined
 #endif
@@ -60,8 +62,10 @@
 
 #if TARGET_PHYS_ADDR_BITS == 32
 typedef uint32_t target_phys_addr_t;
+#define TARGET_FMT_plx "%08x"
 #elif TARGET_PHYS_ADDR_BITS == 64
 typedef uint64_t target_phys_addr_t;
+#define TARGET_FMT_plx "%016" PRIx64
 #else
 #error TARGET_PHYS_ADDR_BITS undefined
 #endif
@@ -76,6 +80,7 @@
 #define EXCP_DEBUG      0x10002 /* cpu stopped after a breakpoint or singlestep */
 #define EXCP_HALTED     0x10003 /* cpu is halted (waiting for external event) */
 #define MAX_BREAKPOINTS 32
+#define MAX_WATCHPOINTS 32
 
 #define TB_JMP_CACHE_BITS 12
 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
@@ -105,6 +110,15 @@
     target_phys_addr_t addend; 
 } CPUTLBEntry;
 
+/* Alpha has 4 different running levels */
+#if defined(TARGET_ALPHA)
+#define NB_MMU_MODES 4
+#elif defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+#define NB_MMU_MODES 3
+#else
+#define NB_MMU_MODES 2
+#endif
+
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
     /* soft mmu support */                                              \
@@ -116,7 +130,7 @@
     target_ulong mem_write_vaddr; /* target virtual addr at which the   \
                                      memory was written */              \
     /* 0 = kernel, 1 = user */                                          \
-    CPUTLBEntry tlb_table[2][CPU_TLB_SIZE];                             \
+    CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
                                                                         \
     /* from this point: preserved by CPU reset */                       \
@@ -125,6 +139,13 @@
     int nb_breakpoints;                                                 \
     int singlestep_enabled;                                             \
                                                                         \
+    struct {                                                            \
+        target_ulong vaddr;                                             \
+        int is_ram;                                                     \
+    } watchpoint[MAX_WATCHPOINTS];                                      \
+    int nb_watchpoints;                                                 \
+    int watchpoint_hit;                                                 \
+                                                                        \
     void *next_cpu; /* next CPU sharing TB cache */                     \
     int cpu_index; /* CPU index (informative) */                        \
     /* user data */                                                     \

Modified: trunk/src/host/qemu-neo1973/cpu-exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/cpu-exec.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/cpu-exec.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -40,7 +40,8 @@
 //#define DEBUG_EXEC
 //#define DEBUG_SIGNAL
 
-#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) || \
+    defined(TARGET_ALPHA)
 /* XXX: unify with i386 target */
 void cpu_loop_exit(void)
 {
@@ -202,6 +203,10 @@
     flags = env->sr & (SR_MD | SR_RB);
     cs_base = 0;         /* XXXXX */
     pc = env->pc;
+#elif defined(TARGET_ALPHA)
+    flags = env->ps;
+    cs_base = 0;
+    pc = env->pc;
 #else
 #error unsupported CPU
 #endif
@@ -226,43 +231,16 @@
 
 int cpu_exec(CPUState *env1)
 {
-    int saved_T0, saved_T1;
-#if defined(reg_T2)
-    int saved_T2;
-#endif
-    CPUState *saved_env;
-#if defined(TARGET_I386)
-#ifdef reg_EAX
-    int saved_EAX;
-#endif
-#ifdef reg_ECX
-    int saved_ECX;
-#endif
-#ifdef reg_EDX
-    int saved_EDX;
-#endif
-#ifdef reg_EBX
-    int saved_EBX;
-#endif
-#ifdef reg_ESP
-    int saved_ESP;
-#endif
-#ifdef reg_EBP
-    int saved_EBP;
-#endif
-#ifdef reg_ESI
-    int saved_ESI;
-#endif
-#ifdef reg_EDI
-    int saved_EDI;
-#endif
-#elif defined(TARGET_SPARC)
+#define DECLARE_HOST_REGS 1
+#include "hostregs_helper.h"
+#if defined(TARGET_SPARC)
 #if defined(reg_REGWPTR)
     uint32_t *saved_regwptr;
 #endif
 #endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
-    int saved_i7, tmp_T0;
+    int saved_i7;
+    target_ulong tmp_T0;
 #endif
     int ret, interrupt_request;
     void (*gen_func)(void);
@@ -283,8 +261,7 @@
 #elif defined(TARGET_PPC)
     if (env1->halted) {
         if (env1->msr[MSR_EE] && 
-            (env1->interrupt_request & 
-             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
+            (env1->interrupt_request & CPU_INTERRUPT_HARD)) {
             env1->halted = 0;
         } else {
             return EXCP_HALTED;
@@ -302,7 +279,8 @@
 #elif defined(TARGET_ARM)
     if (env1->halted) {
         /* An interrupt wakes the CPU even if the I and F CPSR bits are
-           set.  */
+           set.  We use EXITTB to silently wake CPU without causing an
+           actual interrupt.  */
         if (env1->interrupt_request &
             (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) {
             env1->halted = 0;
@@ -319,49 +297,28 @@
             return EXCP_HALTED;
         }
     }
+#elif defined(TARGET_ALPHA)
+    if (env1->halted) {
+        if (env1->interrupt_request & CPU_INTERRUPT_HARD) {
+            env1->halted = 0;
+        } else {
+            return EXCP_HALTED;
+        }
+    }
 #endif
 
     cpu_single_env = env1; 
 
     /* first we save global registers */
-    saved_env = env;
+#define SAVE_HOST_REGS 1
+#include "hostregs_helper.h"
     env = env1;
-    saved_T0 = T0;
-    saved_T1 = T1;
-#if defined(reg_T2)
-    saved_T2 = T2;
-#endif
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     /* we also save i7 because longjmp may not restore it */
     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
 #endif
 
 #if defined(TARGET_I386)
-#ifdef reg_EAX
-    saved_EAX = EAX;
-#endif
-#ifdef reg_ECX
-    saved_ECX = ECX;
-#endif
-#ifdef reg_EDX
-    saved_EDX = EDX;
-#endif
-#ifdef reg_EBX
-    saved_EBX = EBX;
-#endif
-#ifdef reg_ESP
-    saved_ESP = ESP;
-#endif
-#ifdef reg_EBP
-    saved_EBP = EBP;
-#endif
-#ifdef reg_ESI
-    saved_ESI = ESI;
-#endif
-#ifdef reg_EDI
-    saved_EDI = EDI;
-#endif
-
     env_to_regs();
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -381,6 +338,8 @@
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
     /* XXXXX */
+#elif defined(TARGET_ALPHA)
+    env_to_regs();
 #else
 #error unsupported target CPU
 #endif
@@ -417,6 +376,8 @@
                                  env->exception_is_int, 
                                  env->error_code, 
                                  env->exception_next_eip, 0);
+                    /* successfully delivered */
+                    env->old_exception = -1;
 #elif defined(TARGET_PPC)
                     do_interrupt(env);
 #elif defined(TARGET_MIPS)
@@ -427,6 +388,8 @@
                     do_interrupt(env);
 #elif defined(TARGET_SH4)
 		    do_interrupt(env);
+#elif defined(TARGET_ALPHA)
+                    do_interrupt(env);
 #endif
                 }
                 env->exception_index = -1;
@@ -465,6 +428,20 @@
 #endif	    
                 interrupt_request = env->interrupt_request;
                 if (__builtin_expect(interrupt_request, 0)) {
+                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+                        env->exception_index = EXCP_DEBUG;
+                        cpu_loop_exit();
+                    }
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
+    defined(TARGET_PPC) || defined(TARGET_ALPHA)
+                    if (interrupt_request & CPU_INTERRUPT_HALT) {
+                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+                        env->halted = 1;
+                        env->exception_index = EXCP_HLT;
+                        cpu_loop_exit();
+                    }
+#endif
 #if defined(TARGET_I386)
                     if ((interrupt_request & CPU_INTERRUPT_SMI) &&
                         !(env->hflags & HF_SMM_MASK)) {
@@ -499,43 +476,27 @@
                         cpu_ppc_reset(env);
                     }
 #endif
-                    if (msr_ee != 0) {
-                        if ((interrupt_request & CPU_INTERRUPT_HARD)) {
-			    /* Raise it */
-			    env->exception_index = EXCP_EXTERNAL;
-			    env->error_code = 0;
-                            do_interrupt(env);
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        ppc_hw_interrupt(env);
+                        if (env->pending_interrupts == 0)
                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
-                            tmp_T0 = 0;
+                        tmp_T0 = 0;
 #else
-                            T0 = 0;
+                        T0 = 0;
 #endif
-                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
-                            /* Raise it */
-                            env->exception_index = EXCP_DECR;
-                            env->error_code = 0;
-                            do_interrupt(env);
-                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-#if defined(__sparc__) && !defined(HOST_SOLARIS)
-                            tmp_T0 = 0;
-#else
-                            T0 = 0;
-#endif
-                        }
                     }
 #elif defined(TARGET_MIPS)
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
                         (env->CP0_Status & (1 << CP0St_IE)) &&
-                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
-                        !(env->hflags & MIPS_HFLAG_EXL) &&
-                        !(env->hflags & MIPS_HFLAG_ERL) &&
+                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
                         !(env->hflags & MIPS_HFLAG_DM)) {
                         /* Raise it */
                         env->exception_index = EXCP_EXT_INTERRUPT;
                         env->error_code = 0;
                         do_interrupt(env);
-                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
                         tmp_T0 = 0;
 #else
@@ -563,12 +524,7 @@
 		    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
 			//do_interrupt(0, 0, 0, 0, 0);
 			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
-		    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
-			env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-			env->halted = 1;
-			env->exception_index = EXCP_HLT;
-			cpu_loop_exit();
-                    }
+		    }
 #elif defined(TARGET_ARM)
                     if (interrupt_request & CPU_INTERRUPT_FIQ
                         && !(env->uncached_cpsr & CPSR_F)) {
@@ -580,14 +536,12 @@
                         env->exception_index = EXCP_IRQ;
                         do_interrupt(env);
                     }
-                    if (interrupt_request & CPU_INTERRUPT_HALT) {
-                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
-                        env->halted = 1;
-                        env->exception_index = EXCP_HLT;
-                        cpu_loop_exit();
-                    }
 #elif defined(TARGET_SH4)
 		    /* XXXXX */
+#elif defined(TARGET_ALPHA)
+                    if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        do_interrupt(env);
+                    }
 #endif
                    /* Don't use the cached interupt_request value,
                       do_interrupt may have updated the EXITTB flag. */
@@ -656,6 +610,8 @@
                     cpu_dump_state(env, logfile, fprintf, 0);
 #elif defined(TARGET_SH4)
 		    cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_ALPHA)
+                    cpu_dump_state(env, logfile, fprintf, 0);
 #else
 #error unsupported target CPU 
 #endif
@@ -706,6 +662,7 @@
                                      : /* no outputs */
                                      : "r" (gen_func) 
                                      : "i0", "i1", "i2", "i3", "i4", "i5",
+                                       "o0", "o1", "o2", "o3", "o4", "o5",
                                        "l0", "l1", "l2", "l3", "l4", "l5",
                                        "l6", "l7");
 #elif defined(__arm__)
@@ -833,32 +790,6 @@
 #endif
     /* restore flags in standard format */
     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
-
-    /* restore global registers */
-#ifdef reg_EAX
-    EAX = saved_EAX;
-#endif
-#ifdef reg_ECX
-    ECX = saved_ECX;
-#endif
-#ifdef reg_EDX
-    EDX = saved_EDX;
-#endif
-#ifdef reg_EBX
-    EBX = saved_EBX;
-#endif
-#ifdef reg_ESP
-    ESP = saved_ESP;
-#endif
-#ifdef reg_EBP
-    EBP = saved_EBP;
-#endif
-#ifdef reg_ESI
-    ESI = saved_ESI;
-#endif
-#ifdef reg_EDI
-    EDI = saved_EDI;
-#endif
 #elif defined(TARGET_ARM)
     /* XXX: Save/restore host fpu exception state?.  */
 #elif defined(TARGET_SPARC)
@@ -873,19 +804,18 @@
               | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MIPS)
 #elif defined(TARGET_SH4)
+#elif defined(TARGET_ALPHA)
     /* XXXXX */
 #else
 #error unsupported target CPU
 #endif
+
+    /* restore global registers */
 #if defined(__sparc__) && !defined(HOST_SOLARIS)
     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
 #endif
-    T0 = saved_T0;
-    T1 = saved_T1;
-#if defined(reg_T2)
-    T2 = saved_T2;
-#endif
-    env = saved_env;
+#include "hostregs_helper.h"
+
     /* fail safe : never use cpu_single_env outside cpu_exec() */
     cpu_single_env = NULL; 
     return ret;
@@ -1261,12 +1191,69 @@
     /* never comes here */
     return 1;
 }
+
+#elif defined (TARGET_ALPHA)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+                                    int is_write, sigset_t *old_set,
+                                    void *puc)
+{
+    TranslationBlock *tb;
+    int ret;
+    
+    if (cpu_single_env)
+        env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
+           pc, address, is_write, *(unsigned long *)old_set);
+#endif
+    /* XXX: locking issue */
+    if (is_write && page_unprotect(h2g(address), pc, puc)) {
+        return 1;
+    }
+
+    /* see if it is an MMU fault */
+    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+    if (ret < 0)
+        return 0; /* not an MMU fault */
+    if (ret == 0)
+        return 1; /* the MMU fault was handled without causing real CPU fault */
+
+    /* now we have a real cpu fault */
+    tb = tb_find_pc(pc);
+    if (tb) {
+        /* the PC is inside the translated code. It means that we have
+           a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, puc);
+    }
+#if 0
+        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
+               env->nip, env->error_code, tb);
+#endif
+    /* we restore the process signal mask as the sigreturn should
+       do it (XXX: use sigsetjmp) */
+    sigprocmask(SIG_SETMASK, old_set, NULL);
+    cpu_loop_exit();
+    /* never comes here */
+    return 1;
+}
 #else
 #error unsupported target CPU
 #endif
 
 #if defined(__i386__)
 
+#if defined(__APPLE__)
+# include <sys/ucontext.h>
+
+# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
+# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
+# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
+#else
+# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
+# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
+# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
+#endif
+
 #if defined(USE_CODE_COPY)
 static void cpu_send_trap(unsigned long pc, int trap, 
                           struct ucontext *uc)
@@ -1287,9 +1274,10 @@
 }
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int trapno;
@@ -1300,8 +1288,8 @@
 #define REG_ERR    ERR
 #define REG_TRAPNO TRAPNO
 #endif
-    pc = uc->uc_mcontext.gregs[REG_EIP];
-    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
+    pc = EIP_sig(uc);
+    trapno = TRAP_sig(uc);
 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
     if (trapno == 0x00 || trapno == 0x05) {
         /* send division by zero or bound exception */
@@ -1311,15 +1299,16 @@
 #endif
         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
                                  trapno == 0xe ? 
-                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
+                                 (ERROR_sig(uc) >> 1) & 1 : 0,
                                  &uc->uc_sigmask, puc);
 }
 
 #elif defined(__x86_64__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info,
+int cpu_signal_handler(int host_signum, void *pinfo,
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
 
@@ -1381,9 +1370,10 @@
 # define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
 #endif /* __APPLE__ */
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1404,9 +1394,10 @@
 
 #elif defined(__alpha__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                            void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     uint32_t *pc = uc->uc_mcontext.sc_pc;
     uint32_t insn = *pc;
@@ -1433,9 +1424,10 @@
 }
 #elif defined(__sparc__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     uint32_t *regs = (uint32_t *)(info + 1);
     void *sigmask = (regs + 20);
     unsigned long pc;
@@ -1466,9 +1458,10 @@
 
 #elif defined(__arm__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1483,9 +1476,10 @@
 
 #elif defined(__mc68000)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1505,8 +1499,9 @@
 # define __ISR_VALID	1
 #endif
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
+int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long ip;
     int is_write = 0;
@@ -1533,9 +1528,10 @@
 
 #elif defined(__s390__)
 
-int cpu_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_signal_handler(int host_signum, void *pinfo, 
                        void *puc)
 {
+    siginfo_t *info = pinfo;
     struct ucontext *uc = puc;
     unsigned long pc;
     int is_write;
@@ -1544,10 +1540,25 @@
     /* XXX: compute is_write */
     is_write = 0;
     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
-                             is_write,
-                             &uc->uc_sigmask, puc);
+                             is_write, &uc->uc_sigmask, puc);
 }
 
+#elif defined(__mips__)
+
+int cpu_signal_handler(int host_signum, void *pinfo, 
+                       void *puc)
+{
+    siginfo_t *info = pinfo;
+    struct ucontext *uc = puc;
+    greg_t pc = uc->uc_mcontext.pc;
+    int is_write;
+    
+    /* XXX: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write, &uc->uc_sigmask, puc);
+}
+
 #else
 
 #error host CPU specific signal handler needed

Added: trunk/src/host/qemu-neo1973/darwin-user/commpage.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/commpage.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/commpage.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,358 @@
+ /*
+ *  Commpage syscalls
+ *
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/message.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <libkern/OSAtomic.h>
+
+#include "qemu.h"
+
+//#define DEBUG_COMMPAGE
+
+#ifdef DEBUG_COMMPAGE
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+/********************************************************************
+ *   Commpage definitions
+ */
+#ifdef TARGET_I386
+/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
+# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
+# define COMMPAGE_SIZE  (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
+#elif defined(TARGET_PPC)
+/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
+# define COMMPAGE_START (-8*4096)
+# define COMMPAGE_SIZE  (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
+#endif
+
+void do_compare_and_swap32(void *cpu_env, int num);
+void do_compare_and_swap64(void *cpu_env, int num);
+void do_add_atomic_word32(void *cpu_env, int num);
+void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
+void do_nanotime(void *cpu_env, int num);
+
+void unimpl_commpage(void *cpu_env, int num);
+
+typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8);
+typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
+                uint32_t arg2, uint32_t arg3,  uint32_t arg4, uint32_t arg5,
+                uint32_t arg6, uint32_t arg7, uint32_t arg8);
+
+#define HAS_PTR  0x10
+#define NO_PTR   0x20
+#define CALL_DIRECT   0x1
+#define CALL_INDIRECT 0x2
+
+#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
+    { #name, offset, nargs, options, (commpage_8args_function_t)func }
+
+struct commpage_entry {
+    char * name;
+    int offset;
+    int nargs;
+    char options;
+    commpage_8args_function_t function;
+};
+
+static inline int commpage_code_num(struct commpage_entry *entry)
+{
+    if((entry->options & HAS_PTR))
+        return entry->offset + 4;
+    else
+        return entry->offset;
+}
+
+static inline int commpage_is_indirect(struct commpage_entry *entry)
+{
+    return !(entry->options & CALL_DIRECT);
+}
+
+/********************************************************************
+ *   Commpage entry
+ */
+static struct commpage_entry commpage_entries[] =
+{
+    COMMPAGE_ENTRY(compare_and_swap32,    0, 0x080,  do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(compare_and_swap64,    0, 0x0c0,  do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(enqueue,               0, 0x100,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(dequeue,               0, 0x140,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(memory_barrier,        0, 0x180,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(add_atomic_word32,     0, 0x1a0,  do_add_atomic_word32,  CALL_INDIRECT | HAS_PTR),
+    COMMPAGE_ENTRY(add_atomic_word64,     0, 0x1c0,  unimpl_commpage,       CALL_INDIRECT | HAS_PTR),
+
+    COMMPAGE_ENTRY(mach_absolute_time,    0, 0x200,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(spinlock_try,          1, 0x220,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(spinlock_lock,         1, 0x260,  OSSpinLockLock,        CALL_DIRECT),
+    COMMPAGE_ENTRY(spinlock_unlock,       1, 0x2a0,  OSSpinLockUnlock,      CALL_DIRECT),
+    COMMPAGE_ENTRY(pthread_getspecific,   0, 0x2c0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(gettimeofday,          1, 0x2e0,  do_cgettimeofday,      CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_dcache_flush,      0, 0x4e0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(pthread_self,          0, 0x580,  unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(relinquish,            0, 0x5c0,  unimpl_commpage,       CALL_INDIRECT),
+
+#ifdef TARGET_I386
+    COMMPAGE_ENTRY(bts,                   0, 0x5e0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(btc,                   0, 0x5f0,  unimpl_commpage,       CALL_INDIRECT),
+#endif
+
+    COMMPAGE_ENTRY(bzero,                 2, 0x600,  bzero,                 CALL_DIRECT),
+    COMMPAGE_ENTRY(bcopy,                 3, 0x780,  bcopy,                 CALL_DIRECT),
+    COMMPAGE_ENTRY(memcpy,                3, 0x7a0,  memcpy,                CALL_DIRECT),
+
+#ifdef TARGET_I386
+    COMMPAGE_ENTRY(old_nanotime,          0, 0xf80,  do_nanotime,           CALL_INDIRECT),
+    COMMPAGE_ENTRY(memset_pattern,        0, 0xf80,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(long_copy,             0, 0x1200, unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(sysintegrity,          0, 0x1600, unimpl_commpage,       CALL_INDIRECT),
+
+    COMMPAGE_ENTRY(nanotime,              0, 0x1700, do_nanotime,           CALL_INDIRECT),
+#elif TARGET_PPC
+    COMMPAGE_ENTRY(compare_and_swap32b,   0, 0xf80,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(compare_and_swap64b,   0, 0xfc0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(memset_pattern,        0, 0x1000, unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(bigcopy,               0, 0x1140, unimpl_commpage,       CALL_INDIRECT),
+#endif
+};
+
+
+/********************************************************************
+ *   Commpage backdoor
+ */
+static inline void print_commpage_entry(struct commpage_entry entry)
+{
+    printf("@0x%x %s\n", entry.offset, entry.name);
+}
+
+static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
+{
+#ifdef TARGET_I386
+    char * commpage = (char*)(COMMPAGE_START+entry.offset);
+    int c = 0;
+    if(entry.options & HAS_PTR)
+    {
+        commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
+        commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
+    }
+    commpage[c++] = 0xcd;
+    commpage[c++] = 0x79; /* int 0x79 */
+    commpage[c++] = 0xc3; /* ret */
+#else
+    qerror("can't install the commpage on this arch\n");
+#endif
+}
+
+/********************************************************************
+ *   Commpage initialization
+ */
+void commpage_init(void)
+{
+#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(__powerpc__) ^ defined(TARGET_PPC))
+    int i;
+    void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
+                           PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+    if((int)commpage != COMMPAGE_START)
+        qerror("can't allocate the commpage\n");
+
+    bzero(commpage, COMMPAGE_SIZE);
+
+    /* XXX: commpage data not handled */
+
+    for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++)
+        install_commpage_backdoor_for_entry(commpage_entries[i]);
+#else
+    /* simply map our pages so they can be executed
+       XXX: we don't really want to do that since in the ppc on ppc situation we may
+       not able to run commpages host optimized instructions (like G5's on a G5),
+       hence this is sometimes a broken fix. */
+    page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
+#endif
+}
+
+/********************************************************************
+ *   Commpage implementation
+ */
+void do_compare_and_swap32(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
+    uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
+    DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
+
+    if(value && old == tswap32(*value))
+    {
+        uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
+        *value = tswap32(new);
+        /* set zf flag */
+        ((CPUX86State*)cpu_env)->eflags |= 0x40;
+    }
+    else
+    {
+        ((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
+        /* unset zf flag */
+        ((CPUX86State*)cpu_env)->eflags &= ~0x40;
+    }
+#else
+    qerror("do_compare_and_swap32 unimplemented");
+#endif
+}
+
+void do_compare_and_swap64(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    /* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
+    uint64_t old, new, swapped_val;
+    uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
+    old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
+
+    DPRINTF("commpage: compare_and_swap64(%llx,new,%p)\n", old, value);
+    swapped_val = tswap64(*value);
+
+    if(old == swapped_val)
+    {
+        new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
+        *value = tswap64(new);
+        /* set zf flag */
+        ((CPUX86State*)cpu_env)->eflags |= 0x40;
+    }
+    else
+    {
+        ((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
+        ((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
+        /* unset zf flag */
+        ((CPUX86State*)cpu_env)->eflags &= ~0x40;
+    }
+#else
+    qerror("do_compare_and_swap64 unimplemented");
+#endif
+}
+
+void do_add_atomic_word32(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
+    uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
+    uint32_t swapped_value = tswap32(*value);
+
+    DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
+
+    /* old value in EAX */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
+    *value = tswap32(swapped_value + amt);
+#else
+    qerror("do_add_atomic_word32 unimplemented");
+#endif
+}
+
+void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
+{
+#ifdef TARGET_I386
+    extern int __commpage_gettimeofday(struct timeval *);
+    DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
+    struct timeval *time = (struct timeval *)arg1;
+    int ret = __commpage_gettimeofday(time);
+    tswap32s((uint32_t*)&time->tv_sec);
+    tswap32s((uint32_t*)&time->tv_usec);
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
+#else
+    qerror("do_gettimeofday unimplemented");
+#endif
+}
+
+void do_nanotime(void *cpu_env, int num)
+{
+#ifdef TARGET_I386
+    uint64_t t = mach_absolute_time();
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
+    ((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
+#else
+    qerror("do_nanotime unimplemented");
+#endif
+}
+
+void unimpl_commpage(void *cpu_env, int num)
+{
+    qerror("qemu: commpage function 0x%x not implemented\n", num);
+}
+
+/********************************************************************
+ *   do_commpage - called by the main cpu loop
+ */
+void
+do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    int i, found = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    num = num-COMMPAGE_START-2;
+
+    for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++) {
+        if( num == commpage_code_num(&commpage_entries[i]) )
+        {
+            DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
+            found = 1;
+            if(commpage_is_indirect(&commpage_entries[i]))
+            {
+                commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
+                function(cpu_env, num, arg1, arg2, arg3,
+                    arg4, arg5, arg6, arg7, arg8);
+            }
+            else
+            {
+                commpage_entries[i].function(arg1, arg2, arg3,
+                    arg4, arg5, arg6, arg7, arg8);
+            }
+            break;
+        }
+    }
+
+    if(!found)
+    {
+        gemu_log("qemu: commpage function 0x%x not defined\n", num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(-1);
+    }
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/ioctls.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/ioctls.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/ioctls.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,4 @@
+     /* emulated ioctl list */
+
+     IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+     IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))

Added: trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/ioctls_types.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1 @@
+STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
\ No newline at end of file

Added: trunk/src/host/qemu-neo1973/darwin-user/machload.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/machload.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/machload.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,903 @@
+/*
+ *  Mach-O object file loading
+ *
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "qemu.h"
+#include "disas.h"
+
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+#include <mach-o/ppc/reloc.h>
+
+//#define DEBUG_MACHLOAD
+
+#ifdef DEBUG_MACHLOAD
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+# define check_mach_header(x) (x.magic == MH_CIGAM)
+
+extern const char *interp_prefix;
+
+/* we don't have a good implementation for this */
+#define DONT_USE_DYLD_SHARED_MAP
+
+/* Pass extra arg to DYLD for debug */
+//#define ACTIVATE_DYLD_TRACE
+
+//#define OVERRIDE_DYLINKER
+
+#ifdef OVERRIDE_DYLINKER
+# ifdef TARGET_I386
+#  define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
+# else
+#  define DYLINKER_NAME "/usr/lib/dyld"
+# endif
+#endif
+
+/* XXX: in an include */
+struct nlist_extended
+{
+    union {
+        char *n_name;
+        long  n_strx;
+    } n_un;
+    unsigned char n_type;
+    unsigned char n_sect;
+    short st_desc;
+    unsigned long st_value;
+    unsigned long st_size;
+};
+
+/* Print symbols in gdb */
+void *macho_text_sect = 0;
+int   macho_offset = 0;
+
+int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
+void qerror(const char *format, ...);
+#ifdef TARGET_I386
+typedef struct mach_i386_thread_state {
+    unsigned int    eax;
+    unsigned int    ebx;
+    unsigned int    ecx;
+    unsigned int    edx;
+    unsigned int    edi;
+    unsigned int    esi;
+    unsigned int    ebp;
+    unsigned int    esp;
+    unsigned int    ss;
+    unsigned int    eflags;
+    unsigned int    eip;
+    unsigned int    cs;
+    unsigned int    ds;
+    unsigned int    es;
+    unsigned int    fs;
+    unsigned int    gs;
+} mach_i386_thread_state_t;
+
+void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
+{
+    bswap32s((uint32_t*)&ts->eax);
+    bswap32s((uint32_t*)&ts->ebx);
+    bswap32s((uint32_t*)&ts->ecx);
+    bswap32s((uint32_t*)&ts->edx);
+    bswap32s((uint32_t*)&ts->edi);
+    bswap32s((uint32_t*)&ts->esi);
+    bswap32s((uint32_t*)&ts->ebp);
+    bswap32s((uint32_t*)&ts->esp);
+    bswap32s((uint32_t*)&ts->ss);
+    bswap32s((uint32_t*)&ts->eflags);
+    bswap32s((uint32_t*)&ts->eip);
+    bswap32s((uint32_t*)&ts->cs);
+    bswap32s((uint32_t*)&ts->ds);
+    bswap32s((uint32_t*)&ts->es);
+    bswap32s((uint32_t*)&ts->fs);
+    bswap32s((uint32_t*)&ts->gs);
+}
+#define target_thread_state mach_i386_thread_state
+#define TARGET_CPU_TYPE CPU_TYPE_I386
+#define TARGET_CPU_NAME "i386"
+#endif
+
+#ifdef TARGET_PPC
+struct mach_ppc_thread_state {
+    unsigned int srr0;      /* Instruction address register (PC) */
+    unsigned int srr1;    /* Machine state register (supervisor) */
+    unsigned int r0;
+    unsigned int r1;
+    unsigned int r2;
+    unsigned int r3;
+    unsigned int r4;
+    unsigned int r5;
+    unsigned int r6;
+    unsigned int r7;
+    unsigned int r8;
+    unsigned int r9;
+    unsigned int r10;
+    unsigned int r11;
+    unsigned int r12;
+    unsigned int r13;
+    unsigned int r14;
+    unsigned int r15;
+    unsigned int r16;
+    unsigned int r17;
+    unsigned int r18;
+    unsigned int r19;
+    unsigned int r20;
+    unsigned int r21;
+    unsigned int r22;
+    unsigned int r23;
+    unsigned int r24;
+    unsigned int r25;
+    unsigned int r26;
+    unsigned int r27;
+    unsigned int r28;
+    unsigned int r29;
+    unsigned int r30;
+    unsigned int r31;
+
+    unsigned int cr;        /* Condition register */
+    unsigned int xer;    /* User's integer exception register */
+    unsigned int lr;    /* Link register */
+    unsigned int ctr;    /* Count register */
+    unsigned int mq;    /* MQ register (601 only) */
+
+    unsigned int vrsave;    /* Vector Save Register */
+};
+
+void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
+{
+    bswap32s((uint32_t*)&ts->srr0);
+    bswap32s((uint32_t*)&ts->srr1);
+    bswap32s((uint32_t*)&ts->r0);
+    bswap32s((uint32_t*)&ts->r1);
+    bswap32s((uint32_t*)&ts->r2);
+    bswap32s((uint32_t*)&ts->r3);
+    bswap32s((uint32_t*)&ts->r4);
+    bswap32s((uint32_t*)&ts->r5);
+    bswap32s((uint32_t*)&ts->r6);
+    bswap32s((uint32_t*)&ts->r7);
+    bswap32s((uint32_t*)&ts->r8);
+    bswap32s((uint32_t*)&ts->r9);
+    bswap32s((uint32_t*)&ts->r10);
+    bswap32s((uint32_t*)&ts->r11);
+    bswap32s((uint32_t*)&ts->r12);
+    bswap32s((uint32_t*)&ts->r13);
+    bswap32s((uint32_t*)&ts->r14);
+    bswap32s((uint32_t*)&ts->r15);
+    bswap32s((uint32_t*)&ts->r16);
+    bswap32s((uint32_t*)&ts->r17);
+    bswap32s((uint32_t*)&ts->r18);
+    bswap32s((uint32_t*)&ts->r19);
+    bswap32s((uint32_t*)&ts->r20);
+    bswap32s((uint32_t*)&ts->r21);
+    bswap32s((uint32_t*)&ts->r22);
+    bswap32s((uint32_t*)&ts->r23);
+    bswap32s((uint32_t*)&ts->r24);
+    bswap32s((uint32_t*)&ts->r25);
+    bswap32s((uint32_t*)&ts->r26);
+    bswap32s((uint32_t*)&ts->r27);
+    bswap32s((uint32_t*)&ts->r28);
+    bswap32s((uint32_t*)&ts->r29);
+    bswap32s((uint32_t*)&ts->r30);
+    bswap32s((uint32_t*)&ts->r31);
+
+    bswap32s((uint32_t*)&ts->cr);
+    bswap32s((uint32_t*)&ts->xer);
+    bswap32s((uint32_t*)&ts->lr);
+    bswap32s((uint32_t*)&ts->ctr);
+    bswap32s((uint32_t*)&ts->mq);
+
+    bswap32s((uint32_t*)&ts->vrsave);
+}
+
+#define target_thread_state mach_ppc_thread_state
+#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
+#define TARGET_CPU_NAME "PowerPC"
+#endif
+
+struct target_thread_command {
+    unsigned long    cmd;    /* LC_THREAD or  LC_UNIXTHREAD */
+    unsigned long    cmdsize;    /* total size of this command */
+    unsigned long flavor;    /* flavor of thread state */
+    unsigned long count;        /* count of longs in thread state */
+    struct target_thread_state state;  /* thread state for this flavor */
+};
+
+void bswap_tc(struct target_thread_command *tc)
+{
+    bswap32s((uint32_t*)(&tc->flavor));
+    bswap32s((uint32_t*)&tc->count);
+#if defined(TARGET_I386)
+    bswap_i386_thread_state(&tc->state);
+#elif defined(TARGET_PPC)
+    bswap_ppc_thread_state(&tc->state);
+#else
+# error unknown TARGET_CPU_TYPE
+#endif
+}
+
+void bswap_mh(struct mach_header *mh)
+{
+    bswap32s((uint32_t*)(&mh->magic));
+    bswap32s((uint32_t*)&mh->cputype);
+    bswap32s((uint32_t*)&mh->cpusubtype);
+    bswap32s((uint32_t*)&mh->filetype);
+    bswap32s((uint32_t*)&mh->ncmds);
+    bswap32s((uint32_t*)&mh->sizeofcmds);
+    bswap32s((uint32_t*)&mh->flags);
+}
+
+void bswap_lc(struct load_command *lc)
+{
+    bswap32s((uint32_t*)&lc->cmd);
+    bswap32s((uint32_t*)&lc->cmdsize);
+}
+
+
+void bswap_fh(struct fat_header *fh)
+{
+    bswap32s((uint32_t*)&fh->magic);
+    bswap32s((uint32_t*)&fh->nfat_arch);
+}
+
+void bswap_fa(struct fat_arch *fa)
+{
+    bswap32s((uint32_t*)&fa->cputype);
+    bswap32s((uint32_t*)&fa->cpusubtype);
+    bswap32s((uint32_t*)&fa->offset);
+    bswap32s((uint32_t*)&fa->size);
+    bswap32s((uint32_t*)&fa->align);
+}
+
+void bswap_segcmd(struct segment_command *sc)
+{
+    bswap32s((uint32_t*)&sc->vmaddr);
+    bswap32s((uint32_t*)&sc->vmsize);
+    bswap32s((uint32_t*)&sc->fileoff);
+    bswap32s((uint32_t*)&sc->filesize);
+    bswap32s((uint32_t*)&sc->maxprot);
+    bswap32s((uint32_t*)&sc->initprot);
+    bswap32s((uint32_t*)&sc->nsects);
+    bswap32s((uint32_t*)&sc->flags);
+}
+
+void bswap_symtabcmd(struct symtab_command *stc)
+{
+    bswap32s((uint32_t*)&stc->cmd);
+    bswap32s((uint32_t*)&stc->cmdsize);
+    bswap32s((uint32_t*)&stc->symoff);
+    bswap32s((uint32_t*)&stc->nsyms);
+    bswap32s((uint32_t*)&stc->stroff);
+    bswap32s((uint32_t*)&stc->strsize);
+}
+
+void bswap_sym(struct nlist *n)
+{
+    bswap32s((uint32_t*)&n->n_un.n_strx);
+    bswap16s((uint16_t*)&n->n_desc);
+    bswap32s((uint32_t*)&n->n_value);
+}
+
+int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
+{
+    int entry;
+    if(need_bswap)
+        bswap_tc(tc);
+#if defined(TARGET_I386)
+    entry = tc->state.eip;
+    DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
+            tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
+            tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
+            tc->state.fs, tc->state.gs );
+#define reg_copy(reg)   regs->reg = tc->state.reg
+    if(regs)
+    {
+        reg_copy(eax);
+        reg_copy(ebx);
+        reg_copy(ecx);
+        reg_copy(edx);
+
+        reg_copy(edi);
+        reg_copy(esi);
+
+        reg_copy(ebp);
+        reg_copy(esp);
+
+        reg_copy(eflags);
+        reg_copy(eip);
+    /*
+        reg_copy(ss);
+        reg_copy(cs);
+        reg_copy(ds);
+        reg_copy(es);
+        reg_copy(fs);
+        reg_copy(gs);*/
+    }
+#undef reg_copy
+#elif defined(TARGET_PPC)
+    entry =  tc->state.srr0;
+#endif
+    DPRINTF("load_thread: entry 0x%x\n", entry);
+    return entry;
+}
+
+int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
+{
+    int size;
+    char * dylinker_name;
+    size = dc->cmdsize - sizeof(struct dylinker_command);
+
+    if(need_bswap)
+        dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
+    else
+        dylinker_name = (char*)((dc->name.offset)+(int)dc);
+
+#ifdef OVERRIDE_DYLINKER
+    dylinker_name = DYLINKER_NAME;
+#else
+    if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
+        qerror("can't allocate the new dylinker name\n");
+#endif
+
+    DPRINTF("dylinker_name %s\n", dylinker_name);
+    return load_object(dylinker_name, NULL, NULL);
+}
+
+int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
+{
+    unsigned long addr = sc->vmaddr;
+    unsigned long size = sc->filesize;
+    unsigned long error = 0;
+
+    if(need_bswap)
+        bswap_segcmd(sc);
+
+    if(sc->vmaddr == 0)
+    {
+        DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
+        return -1;
+    }
+
+    if (strcmp(sc->segname, "__PAGEZERO") == 0)
+    {
+        DPRINTF("load_segment: __PAGEZERO returning\n");
+        return -1;
+    }
+
+    /* Right now mmap memory */
+    /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
+    DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
+
+    if(sc->filesize > 0)
+    {
+        int opt = 0;
+
+        if(fixed)
+            opt |= MAP_FIXED;
+
+        DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
+
+        addr = target_mmap(sc->vmaddr+slide, sc->filesize,  sc->initprot, opt, fd, mh_pos + sc->fileoff);
+
+        if(addr==-1)
+            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
+
+        error = addr-sc->vmaddr;
+    }
+    else
+    {
+        addr = sc->vmaddr+slide;
+        error = slide;
+    }
+
+    if(sc->vmsize > sc->filesize)
+    {
+        addr += sc->filesize;
+        size = sc->vmsize-sc->filesize;
+        addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+        if(addr==-1)
+            qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
+    }
+
+    return error;
+}
+
+void *load_data(int fd, long offset, unsigned int size)
+{
+    char *data;
+
+    data = malloc(size);
+    if (!data)
+        return NULL;
+    lseek(fd, offset, SEEK_SET);
+    if (read(fd, data, size) != size) {
+        free(data);
+        return NULL;
+    }
+    return data;
+}
+
+/* load a mach-o object file */
+int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
+{
+    int need_bswap = 0;
+    int entry_point = 0;
+    int dyld_entry_point = 0;
+    int slide, mmapfixed;
+    int fd;
+    struct load_command *lcmds, *lc;
+    int is_fat = 0;
+    unsigned int i, magic;
+    int mach_hdr_pos = 0;
+    struct mach_header mach_hdr;
+
+    /* for symbol lookup whith -d flag. */
+    struct symtab_command *    symtabcmd = 0;
+    struct nlist_extended *symtab, *sym;
+    struct nlist     *symtab_std, *syment;
+    char            *strtab;
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0)
+        qerror("can't open file '%s'", filename);
+
+    /* Read magic header.  */
+    if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
+        qerror("unable to read Magic of '%s'", filename);
+
+    /* Check Mach identification.  */
+    if(magic == MH_MAGIC)
+    {
+        is_fat = 0;
+        need_bswap = 0;
+    } else if (magic == MH_CIGAM)
+    {
+        is_fat = 0;
+        need_bswap = 1;
+    } else if (magic == FAT_MAGIC)
+    {
+        is_fat = 1;
+        need_bswap = 0;
+    } else if (magic == FAT_CIGAM)
+    {
+        is_fat = 1;
+        need_bswap = 1;
+    }
+    else
+        qerror("Not a Mach-O file.", filename);
+
+    DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
+    if(is_fat)
+    {
+        int found = 0;
+        struct fat_header fh;
+        struct fat_arch *fa;
+
+        lseek(fd, 0, SEEK_SET);
+
+        /* Read Fat header.  */
+        if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
+            qerror("unable to read file header");
+
+        if(need_bswap)
+            bswap_fh(&fh);
+
+        /* Read Fat Arch.  */
+        fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
+
+        if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
+            qerror("unable to read file header");
+
+        for( i = 0; i < fh.nfat_arch; i++, fa++)
+        {
+            if(need_bswap)
+                bswap_fa(fa);
+            if(fa->cputype == TARGET_CPU_TYPE)
+            {
+                mach_hdr_pos = fa->offset;
+                lseek(fd, mach_hdr_pos, SEEK_SET);
+
+                /* Read Mach header.  */
+
+                if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
+                    qerror("unable to read file header");
+
+                if(mach_hdr.magic == MH_MAGIC)
+                    need_bswap = 0;
+                else if (mach_hdr.magic == MH_CIGAM)
+                    need_bswap = 1;
+                else
+                    qerror("Invalid mach header in Fat Mach-O File");
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
+    }
+    else
+    {
+        lseek(fd, 0, SEEK_SET);
+        /* Read Mach header */
+        if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
+            qerror("%s: unable to read file header", filename);
+    }
+
+    if(need_bswap)
+        bswap_mh(&mach_hdr);
+
+    if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
+        qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
+
+
+    switch(mach_hdr.filetype)
+    {
+        case MH_EXECUTE:  break;
+        case MH_FVMLIB:
+        case MH_DYLIB:
+        case MH_DYLINKER: break;
+        default:
+            qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
+    }
+
+    /* read segment headers */
+    lcmds = malloc(mach_hdr.sizeofcmds);
+
+    if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
+            qerror("%s: unable to read load_command", filename);
+    slide = 0;
+    mmapfixed = 0;
+    for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
+    {
+
+        if(need_bswap)
+            bswap_lc(lc);
+        switch(lc->cmd)
+        {
+            case LC_SEGMENT:
+                /* The main_exe can't be relocated */
+                if(mach_hdr.filetype == MH_EXECUTE)
+                    mmapfixed = 1;
+
+                slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
+
+                /* other segment must be mapped according to slide exactly, if load_segment did something */
+                if(slide != -1)
+                    mmapfixed = 1;
+                else
+                    slide = 0; /* load_segment didn't map the segment */
+
+                if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
+                    qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
+
+                if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
+                {
+                    /* Text section */
+                    if(mach_hdr.filetype == MH_EXECUTE)
+                    {
+                        /* return the mach_header */
+                        *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
+                    }
+                    else
+                    {
+                        /* it is dyld save the section for gdb, we will be interested in dyld symbol
+                           while debuging */
+                        macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
+                        macho_offset = slide;
+                    }
+                }
+                break;
+            case LC_LOAD_DYLINKER:
+                dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
+                break;
+            case LC_LOAD_DYLIB:
+                /* dyld will do that for us */
+                break;
+            case LC_THREAD:
+            case LC_UNIXTHREAD:
+                {
+                struct target_pt_regs * _regs;
+                if(mach_hdr.filetype == MH_DYLINKER)
+                    _regs = regs;
+                else
+                    _regs = 0;
+                entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
+                }
+                break;
+            case LC_SYMTAB:
+                /* Save the symtab and strtab */
+                symtabcmd = (struct symtab_command *)lc;
+                break;
+            case LC_ID_DYLINKER:
+            case LC_ID_DYLIB:
+            case LC_UUID:
+            case LC_DYSYMTAB:
+            case LC_TWOLEVEL_HINTS:
+            case LC_PREBIND_CKSUM:
+            case LC_SUB_LIBRARY:
+                break;
+            default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
+        }
+        lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
+    }
+
+    if(symtabcmd)
+    {
+        if(need_bswap)
+            bswap_symtabcmd(symtabcmd);
+
+        symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
+        strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
+
+        symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
+
+        if(need_bswap)
+        {
+            for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
+                bswap_sym(syment);
+        }
+
+        for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
+        {
+            struct nlist *sym_follow, *sym_next = 0;
+            unsigned int j;
+            memset(sym, 0, sizeof(*sym));
+
+            sym->n_type = syment->n_type;
+            if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
+                continue;
+
+            memcpy(sym, syment, sizeof(*syment));
+
+            /* Find the following symbol in order to get the current symbol size */
+            for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
+                if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
+                    continue;
+                if(!sym_next) {
+                    sym_next = sym_follow;
+                    continue;
+                }
+                if(!(sym_next->n_value > sym_follow->n_value))
+                    continue;
+                sym_next = sym_follow;
+            }
+            if(sym_next)
+                sym->st_size = sym_next->n_value - sym->st_value;
+            else
+                sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
+
+            sym->st_value += slide;
+        }
+
+        free((void*)symtab_std);
+
+        {
+            DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
+            struct syminfo *s;
+            s = malloc(sizeof(*s));
+            s->disas_symtab = symtab;
+            s->disas_strtab = strtab;
+            s->disas_num_syms = symtabcmd->nsyms;
+            s->next = syminfos;
+            syminfos = s;
+        }
+    }
+    close(fd);
+    if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
+        return dyld_entry_point;
+    else
+        return entry_point+slide;
+}
+
+extern unsigned long stack_size;
+
+unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
+{
+    unsigned long stack_base, error, size;
+    int i;
+    int * stack;
+    int argc, envc;
+
+    /* Create enough stack to hold everything.  If we don't use
+     * it for args, we'll use it for something else...
+     */
+    size = stack_size;
+
+    error = target_mmap(0,
+                        size + qemu_host_page_size,
+                        PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANONYMOUS,
+                        -1, 0);
+    if (error == -1)
+        qerror("stk mmap");
+
+    /* we reserve one extra page at the top of the stack as guard */
+    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
+
+    stack_base = error + size;
+    stack = (void*)stack_base;
+/*
+ *    | STRING AREA |
+ *    +-------------+
+ *    |      0      |
+*    +-------------+
+ *    |  apple[n]   |
+ *    +-------------+
+ *           :
+ *    +-------------+
+ *    |  apple[0]   |
+ *    +-------------+
+ *    |      0      |
+ *    +-------------+
+ *    |    env[n]   |
+ *    +-------------+
+ *           :
+ *           :
+ *    +-------------+
+ *    |    env[0]   |
+ *    +-------------+
+ *    |      0      |
+ *    +-------------+
+ *    | arg[argc-1] |
+ *    +-------------+
+ *           :
+ *           :
+ *    +-------------+
+ *    |    arg[0]   |
+ *    +-------------+
+ *    |     argc    |
+ *    +-------------+
+ * sp->    |      mh     | address of where the a.out's file offset 0 is in memory
+ *    +-------------+
+*/
+    /* Construct the stack Stack grows down */
+    stack--;
+
+    /* XXX: string should go up there */
+
+    *stack = 0;
+    stack--;
+
+    /* Push the absolute path of our executable */
+    DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
+    stl(stack, (int) argv[0]);
+
+    stack--;
+
+    stl(stack, 0);
+    stack--;
+
+    /* Get envc */
+    for(envc = 0; env[envc]; envc++);
+
+    for(i = envc-1; i >= 0; i--)
+    {
+        DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
+        stl(stack, (int)env[i]);
+        stack--;
+
+        /* XXX: remove that when string will be on top of the stack */
+        page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
+    }
+
+    /* Add on the stack the interp_prefix choosen if so */
+    if(interp_prefix[0])
+    {
+        char *dyld_root;
+        asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
+        page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
+
+        stl(stack, (int)dyld_root);
+        stack--;
+    }
+
+#ifdef DONT_USE_DYLD_SHARED_MAP
+    {
+        char *shared_map_mode;
+        asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
+        page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
+
+        stl(stack, (int)shared_map_mode);
+        stack--;
+    }
+#endif
+
+#ifdef ACTIVATE_DYLD_TRACE
+    char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
+    "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
+    "DYLD_PRINT_INITIALIZERS=yes",
+    "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
+
+    char ** extra_env = malloc(sizeof(extra_env_static));
+    bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
+    page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
+
+    for(i = 0; i<9; i++)
+    {
+        DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
+        stl(stack, (int) extra_env[i]);
+        stack--;
+    }
+#endif
+
+    stl(stack, 0);
+    stack--;
+
+    /* Get argc */
+    for(argc = 0; argv[argc]; argc++);
+
+    for(i = argc-1; i >= 0; i--)
+    {
+        DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
+        stl(stack, (int) argv[i]);
+        stack--;
+
+        /* XXX: remove that when string will be on top of the stack */
+        page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
+    }
+
+    DPRINTF("pushing argc %d \n", argc);
+    stl(stack, argc);
+    stack--;
+
+    DPRINTF("pushing mh 0x%x \n", (int)mh);
+    stl(stack, (int) mh);
+
+    /* Stack points on the mh */
+    return (unsigned long)stack;
+}
+
+int mach_exec(const char * filename, char ** argv, char ** envp,
+             struct target_pt_regs * regs)
+{
+    int entrypoint, stack;
+    void * mh; /* the Mach Header that will be  used by dyld */
+
+    DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
+
+    entrypoint = load_object(filename, regs, &mh);
+    stack = setup_arg_pages(mh, argv, envp);
+#if defined(TARGET_I386)
+    regs->eip = entrypoint;
+    regs->esp = stack;
+#elif defined(TARGET_PPC)
+    regs->nip = entrypoint;
+    regs->gpr[1] = stack;
+#endif
+    DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
+
+    if(!entrypoint)
+        qerror("%s: no entry point!\n", filename);
+
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/main.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,918 @@
+/*
+ *  qemu user main
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+#include "qemu.h"
+
+#define DEBUG_LOGFILE "/tmp/qemu.log"
+
+#ifdef __APPLE__
+#include <crt_externs.h>
+# define environ  (*_NSGetEnviron())
+#endif
+
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+
+const char *interp_prefix = "";
+
+asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
+
+/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
+   we allocate a bigger stack. Need a better solution, for example
+   by remapping the process stack directly at the right place */
+unsigned long stack_size = 512 * 1024;
+
+void qerror(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "\n");
+    exit(1);
+}
+
+void gemu_log(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+void cpu_outb(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
+}
+
+void cpu_outw(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
+}
+
+void cpu_outl(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
+}
+
+int cpu_inb(CPUState *env, int addr)
+{
+    fprintf(stderr, "inb: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inw(CPUState *env, int addr)
+{
+    fprintf(stderr, "inw: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inl(CPUState *env, int addr)
+{
+    fprintf(stderr, "inl: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_get_pic_interrupt(CPUState *env)
+{
+    return -1;
+}
+#ifdef TARGET_PPC
+
+static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+{
+    /* TO FIX */
+    return 0;
+}
+
+uint32_t cpu_ppc_load_tbl (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) >> 32;
+}
+
+static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+}
+
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+}
+
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+    /* TO FIX */
+    return -1;
+}
+
+void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_loop(CPUPPCState *env)
+{
+    int trapnr;
+    uint32_t ret;
+    target_siginfo_t info;
+
+    for(;;) {
+        trapnr = cpu_ppc_exec(env);
+        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
+            trapnr != EXCP_TRACE) {
+            if (loglevel > 0) {
+                cpu_dump_state(env, logfile, fprintf, 0);
+            }
+        }
+        switch(trapnr) {
+        case EXCP_NONE:
+            break;
+        case EXCP_SYSCALL_USER:
+            /* system call */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
+            else if(((int)env->gpr[0])<0)
+                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]);
+            else
+                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                        env->gpr[5], env->gpr[6], env->gpr[7],
+                                        env->gpr[8], env->gpr[9], env->gpr[10]);
+
+            /* Unix syscall error signaling */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+            {
+                if( (int)ret < 0 )
+                    env->nip += 0;
+                else
+                    env->nip += 4;
+            }
+
+            /* Return value */
+            env->gpr[3] = ret;
+            break;
+        case EXCP_RESET:
+            /* Should not happen ! */
+            fprintf(stderr, "RESET asked... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                abort();
+        case EXCP_MACHINE_CHECK:
+            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_OBJERR;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+        case EXCP_DSI:
+#ifndef DAR
+/* To deal with multiple qemu header version as host for the darwin-user code */
+# define DAR SPR_DAR
+#endif
+            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
+            if (loglevel) {
+                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
+                        env->spr[DAR]);
+            }
+            /* Handle this via the gdb */
+            gdb_handlesig (env, SIGSEGV);
+
+            info.si_addr = (void*)env->nip;
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_ISI:
+            fprintf(stderr, "Invalid instruction fetch\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid instruction fetch\n");
+            /* Handle this via the gdb */
+            gdb_handlesig (env, SIGSEGV);
+
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_EXTERNAL:
+            /* Should not happen ! */
+            fprintf(stderr, "External interruption... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "External interruption... Stop emulation\n");
+                abort();
+        case EXCP_ALIGN:
+            fprintf(stderr, "Invalid unaligned memory access\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid unaligned memory access\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_ADRALN;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_PROGRAM:
+            switch (env->error_code & ~0xF) {
+                case EXCP_FP:
+                    fprintf(stderr, "Program exception\n");
+                    if (loglevel)
+                        fprintf(logfile, "Program exception\n");
+                        /* Set FX */
+                        env->fpscr[7] |= 0x8;
+                    /* Finally, update FEX */
+                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
+                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
+                        env->fpscr[7] |= 0x4;
+                        info.si_signo = SIGFPE;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_FP_OX:
+                            info.si_code = FPE_FLTOVF;
+                            break;
+                        case EXCP_FP_UX:
+                            info.si_code = FPE_FLTUND;
+                            break;
+                        case EXCP_FP_ZX:
+                        case EXCP_FP_VXZDZ:
+                            info.si_code = FPE_FLTDIV;
+                            break;
+                        case EXCP_FP_XX:
+                            info.si_code = FPE_FLTRES;
+                            break;
+                        case EXCP_FP_VXSOFT:
+                            info.si_code = FPE_FLTINV;
+                            break;
+                        case EXCP_FP_VXNAN:
+                        case EXCP_FP_VXISI:
+                        case EXCP_FP_VXIDI:
+                        case EXCP_FP_VXIMZ:
+                        case EXCP_FP_VXVC:
+                        case EXCP_FP_VXSQRT:
+                        case EXCP_FP_VXCVI:
+                            info.si_code = FPE_FLTSUB;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown floating point exception "
+                                    "(%02x)\n", env->error_code);
+                            if (loglevel) {
+                                fprintf(logfile, "Unknown floating point exception "
+                                        "(%02x)\n", env->error_code & 0xF);
+                            }
+                    }
+                        break;
+                case EXCP_INVAL:
+                    fprintf(stderr, "Invalid instruction\n");
+                    if (loglevel)
+                        fprintf(logfile, "Invalid instruction\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_INVAL_INVAL:
+                            info.si_code = ILL_ILLOPC;
+                            break;
+                        case EXCP_INVAL_LSWX:
+                            info.si_code = ILL_ILLOPN;
+                            break;
+                        case EXCP_INVAL_SPR:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        case EXCP_INVAL_FP:
+                            info.si_code = ILL_COPROC;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown invalid operation (%02x)\n",
+                                    env->error_code & 0xF);
+                            if (loglevel) {
+                                fprintf(logfile, "Unknown invalid operation (%02x)\n",
+                                        env->error_code & 0xF);
+                            }
+                                info.si_code = ILL_ILLADR;
+                            break;
+                    }
+                        /* Handle this via the gdb */
+                        gdb_handlesig (env, SIGSEGV);
+                    break;
+                case EXCP_PRIV:
+                    fprintf(stderr, "Privilege violation\n");
+                    if (loglevel)
+                        fprintf(logfile, "Privilege violation\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_PRIV_OPC:
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                        case EXCP_PRIV_REG:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown privilege violation (%02x)\n",
+                                    env->error_code & 0xF);
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                    }
+                        break;
+                case EXCP_TRAP:
+                    fprintf(stderr, "Tried to call a TRAP\n");
+                    if (loglevel)
+                        fprintf(logfile, "Tried to call a TRAP\n");
+                        abort();
+                default:
+                    /* Should not happen ! */
+                    fprintf(stderr, "Unknown program exception (%02x)\n",
+                            env->error_code);
+                    if (loglevel) {
+                        fprintf(logfile, "Unknwon program exception (%02x)\n",
+                                env->error_code);
+                    }
+                        abort();
+            }
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_NO_FP:
+            fprintf(stderr, "No floating point allowed\n");
+            if (loglevel)
+                fprintf(logfile, "No floating point allowed\n");
+                info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_COPROC;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_DECR:
+            /* Should not happen ! */
+            fprintf(stderr, "Decrementer exception\n");
+            if (loglevel)
+                fprintf(logfile, "Decrementer exception\n");
+            abort();
+        case EXCP_TRACE:
+            /* Pass to gdb: we use this to trace execution */
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        case EXCP_FP_ASSIST:
+            /* Should not happen ! */
+            fprintf(stderr, "Floating point assist exception\n");
+            if (loglevel)
+                fprintf(logfile, "Floating point assist exception\n");
+            abort();
+        case EXCP_MTMSR:
+            /* We reloaded the msr, just go on */
+            if (msr_pr == 0) {
+                fprintf(stderr, "Tried to go into supervisor mode !\n");
+                if (loglevel)
+                    fprintf(logfile, "Tried to go into supervisor mode !\n");
+                abort();
+            }
+            break;
+        case EXCP_BRANCH:
+            /* We stopped because of a jump... */
+            break;
+        case EXCP_INTERRUPT:
+            /* Don't know why this should ever happen... */
+            fprintf(stderr, "EXCP_INTERRUPT\n");
+            break;
+        case EXCP_DEBUG:
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                    trapnr);
+            if (loglevel) {
+                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
+                        "0x%02x - aborting\n", trapnr, env->error_code);
+            }
+                abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif
+
+
+#ifdef TARGET_I386
+
+/***********************************************************/
+/* CPUX86 core interface */
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+    return cpu_get_real_ticks();
+}
+
+void
+write_dt(void *ptr, unsigned long addr, unsigned long limit,
+                     int flags)
+{
+    unsigned int e1, e2;
+    e1 = (addr << 16) | (limit & 0xffff);
+    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
+    e2 |= flags;
+    stl((uint8_t *)ptr, e1);
+    stl((uint8_t *)ptr + 4, e2);
+}
+
+static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+                     unsigned long addr, unsigned int sel)
+{
+    unsigned int e1, e2;
+    e1 = (addr & 0xffff) | (sel << 16);
+    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+    stl((uint8_t *)ptr, e1);
+    stl((uint8_t *)ptr + 4, e2);
+}
+
+#define GDT_TABLE_SIZE 14
+#define LDT_TABLE_SIZE 15
+#define IDT_TABLE_SIZE 256
+#define TSS_SIZE 104
+uint64_t gdt_table[GDT_TABLE_SIZE];
+uint64_t ldt_table[LDT_TABLE_SIZE];
+uint64_t idt_table[IDT_TABLE_SIZE];
+uint32_t tss[TSS_SIZE];
+
+/* only dpl matters as we do only user space emulation */
+static void set_idt(int n, unsigned int dpl)
+{
+    set_gate(idt_table + n, 0, dpl, 0, 0);
+}
+
+/* ABI convention: after a syscall if there was an error the CF flag is set */
+static inline void set_error(CPUX86State *env, int ret)
+{
+    if(ret<0)
+        env->eflags = env->eflags | 0x1;
+    else
+        env->eflags &= ~0x1;
+    env->regs[R_EAX] = ret;
+}
+
+void cpu_loop(CPUX86State *env)
+{
+    int trapnr;
+    int ret;
+    uint8_t *pc;
+    target_siginfo_t info;
+
+    for(;;) {
+        trapnr = cpu_x86_exec(env);
+        uint32_t *params = (uint32_t *)env->regs[R_ESP];
+        switch(trapnr) {
+        case 0x79: /* Our commpage hack back door exit is here */
+            do_commpage(env,  env->eip,   *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            break;
+        case 0x81: /* mach syscall */
+        {
+            ret = do_mach_syscall(env,  env->regs[R_EAX],
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            set_error(env, ret);
+            break;
+        }
+        case 0x90: /* unix backdoor */
+        {
+            /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
+            int saved_stack = env->regs[R_ESP];
+            env->regs[R_ESP] = env->regs[R_ECX];
+
+            ret = do_unix_syscall(env, env->regs[R_EAX]);
+
+            env->regs[R_ECX] = env->regs[R_ESP];
+            env->regs[R_ESP] = saved_stack;
+
+            set_error(env, ret);
+            break;
+        }
+        case 0x80: /* unix syscall */
+        {
+            ret = do_unix_syscall(env, env->regs[R_EAX]/*,
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8)*/);
+            set_error(env, ret);
+            break;
+        }
+        case 0x82: /* thread syscall */
+        {
+            ret = do_thread_syscall(env,  env->regs[R_EAX],
+                                          *(params + 1), *(params + 2),
+                                          *(params + 3), *(params + 4),
+                                          *(params + 5), *(params + 6),
+                                          *(params + 7), *(params + 8));
+            set_error(env, ret);
+            break;
+        }
+        case EXCP0B_NOSEG:
+        case EXCP0C_STACK:
+            info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGBUS);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP0D_GPF:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = SEGV_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP0E_PAGE:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            if (!(env->error_code & 1))
+                info.si_code = SEGV_MAPERR;
+            else
+                info.si_code = SEGV_ACCERR;
+            info.si_addr = (void*)env->cr[2];
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP00_DIVZ:
+            /* division by zero */
+            info.si_signo = SIGFPE;
+            info.si_errno = 0;
+            info.si_code = FPE_INTDIV;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGFPE);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP01_SSTP:
+        case EXCP03_INT3:
+            info.si_signo = SIGTRAP;
+            info.si_errno = 0;
+            info.si_code = TRAP_BRKPT;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGTRAP);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP04_INTO:
+        case EXCP05_BOUND:
+            info.si_signo = SIGSEGV;
+            info.si_errno = 0;
+            info.si_code = SEGV_NOOP;
+            info.si_addr = 0;
+            gdb_handlesig (env, SIGSEGV);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP06_ILLOP:
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_ILLOPN;
+            info.si_addr = (void*)env->eip;
+            gdb_handlesig (env, SIGILL);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
+        case EXCP_DEBUG:
+            {
+                int sig;
+
+                sig = gdb_handlesig (env, SIGTRAP);
+                if (sig)
+                  {
+                    info.si_signo = sig;
+                    info.si_errno = 0;
+                    info.si_code = TRAP_BRKPT;
+                    queue_signal(info.si_signo, &info);
+                  }
+            }
+            break;
+        default:
+            pc = (void*)(env->segs[R_CS].base + env->eip);
+            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+                    (long)pc, trapnr);
+            abort();
+        }
+        process_pending_signals(env);
+    }
+}
+#endif
+
+void usage(void)
+{
+    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
+           "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
+           "Darwin CPU emulator (compiled for %s emulation)\n"
+           "\n"
+           "-h           print this help\n"
+           "-L path      set the %s library path (default='%s')\n"
+           "-s size      set the stack size in bytes (default=%ld)\n"
+           "\n"
+           "debug options:\n"
+#ifdef USE_CODE_COPY
+           "-no-code-copy   disable code copy acceleration\n"
+#endif
+           "-d options   activate log (logfile='%s')\n"
+           "-g wait for gdb on port 1234\n"
+           "-p pagesize  set the host page size to 'pagesize'\n",
+           TARGET_ARCH,
+           TARGET_ARCH,
+           interp_prefix,
+           stack_size,
+           DEBUG_LOGFILE);
+    _exit(1);
+}
+
+/* XXX: currently only used for async signals (see signal.c) */
+CPUState *global_env;
+/* used only if single thread */
+CPUState *cpu_single_env = NULL;
+
+/* used to free thread contexts */
+TaskState *first_task_state;
+
+int main(int argc, char **argv)
+{
+    const char *filename;
+    struct target_pt_regs regs1, *regs = &regs1;
+    TaskState ts1, *ts = &ts1;
+    CPUState *env;
+    int optind;
+    short use_gdbstub = 0;
+    const char *r;
+
+    if (argc <= 1)
+        usage();
+
+    /* init debug */
+    cpu_set_log_filename(DEBUG_LOGFILE);
+
+    optind = 1;
+    for(;;) {
+        if (optind >= argc)
+            break;
+        r = argv[optind];
+        if (r[0] != '-')
+            break;
+        optind++;
+        r++;
+        if (!strcmp(r, "-")) {
+            break;
+        } else if (!strcmp(r, "d")) {
+            int mask;
+            CPULogItem *item;
+
+        if (optind >= argc)
+        break;
+
+        r = argv[optind++];
+            mask = cpu_str_to_log_mask(r);
+            if (!mask) {
+                printf("Log items (comma separated):\n");
+                for(item = cpu_log_items; item->mask != 0; item++) {
+                    printf("%-10s %s\n", item->name, item->help);
+                }
+                exit(1);
+            }
+            cpu_set_log(mask);
+        } else if (!strcmp(r, "s")) {
+            r = argv[optind++];
+            stack_size = strtol(r, (char **)&r, 0);
+            if (stack_size <= 0)
+                usage();
+            if (*r == 'M')
+                stack_size *= 1024 * 1024;
+            else if (*r == 'k' || *r == 'K')
+                stack_size *= 1024;
+        } else if (!strcmp(r, "L")) {
+            interp_prefix = argv[optind++];
+        } else if (!strcmp(r, "p")) {
+            qemu_host_page_size = atoi(argv[optind++]);
+            if (qemu_host_page_size == 0 ||
+                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
+                fprintf(stderr, "page size must be a power of two\n");
+                exit(1);
+            }
+        } else
+        if (!strcmp(r, "g")) {
+            use_gdbstub = 1;
+        } else
+#ifdef USE_CODE_COPY
+        if (!strcmp(r, "no-code-copy")) {
+            code_copy_enabled = 0;
+        } else
+#endif
+        {
+            usage();
+        }
+    }
+    if (optind >= argc)
+        usage();
+    filename = argv[optind];
+
+    /* Zero out regs */
+    memset(regs, 0, sizeof(struct target_pt_regs));
+
+    /* NOTE: we need to init the CPU at this stage to get
+       qemu_host_page_size */
+    env = cpu_init();
+
+    printf("Starting %s with qemu\n----------------\n", filename);
+
+    commpage_init();
+
+    if (mach_exec(filename, argv+optind, environ, regs) != 0) {
+    printf("Error loading %s\n", filename);
+    _exit(1);
+    }
+
+    syscall_init();
+    signal_init();
+    global_env = env;
+
+    /* build Task State */
+    memset(ts, 0, sizeof(TaskState));
+    env->opaque = ts;
+    ts->used = 1;
+    env->user_mode_only = 1;
+
+#if defined(TARGET_I386)
+    cpu_x86_set_cpl(env, 3);
+
+    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+    env->hflags |= HF_PE_MASK;
+
+    if (env->cpuid_features & CPUID_SSE) {
+        env->cr[4] |= CR4_OSFXSR_MASK;
+        env->hflags |= HF_OSFXSR_MASK;
+    }
+
+    /* flags setup : we activate the IRQs by default as in user mode */
+    env->eflags |= IF_MASK;
+
+    /* darwin register setup */
+    env->regs[R_EAX] = regs->eax;
+    env->regs[R_EBX] = regs->ebx;
+    env->regs[R_ECX] = regs->ecx;
+    env->regs[R_EDX] = regs->edx;
+    env->regs[R_ESI] = regs->esi;
+    env->regs[R_EDI] = regs->edi;
+    env->regs[R_EBP] = regs->ebp;
+    env->regs[R_ESP] = regs->esp;
+    env->eip = regs->eip;
+
+    /* Darwin LDT setup */
+    /* 2 - User code segment
+       3 - User data segment
+       4 - User cthread */
+    bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
+    env->ldt.base = (uint32_t) ldt_table;
+    env->ldt.limit = sizeof(ldt_table) - 1;
+
+    write_dt(ldt_table + 2, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+    write_dt(ldt_table + 3, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+    write_dt(ldt_table + 4, 0, 0xfffff,
+             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+
+    /* Darwin GDT setup.
+     * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
+       now everything is done via  int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
+    bzero(gdt_table, sizeof(gdt_table));
+    env->gdt.base = (uint32_t)gdt_table;
+    env->gdt.limit = sizeof(gdt_table) - 1;
+
+    /* Set up a back door to handle sysenter syscalls (unix) */
+    char * syscallbackdoor = malloc(64);
+    page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
+
+    int i = 0;
+    syscallbackdoor[i++] = 0xcd;
+    syscallbackdoor[i++] = 0x90; /* int 0x90 */
+    syscallbackdoor[i++] = 0x0F;
+    syscallbackdoor[i++] = 0x35; /* sysexit */
+
+    /* Darwin sysenter/sysexit setup */
+    env->sysenter_cs = 0x1; //XXX
+    env->sysenter_eip = (int)syscallbackdoor;
+    env->sysenter_esp = (int)malloc(64);
+
+    /* Darwin TSS setup
+       This must match up with GDT[4] */
+    env->tr.base = (uint32_t) tss;
+    env->tr.limit = sizeof(tss) - 1;
+    env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
+    stw(tss + 2, 0x10);  // ss0 = 0x10 = GDT[2] = Kernel Data Segment
+
+    /* Darwin interrupt setup */
+    bzero(idt_table, sizeof(idt_table));
+    env->idt.base = (uint32_t) idt_table;
+    env->idt.limit = sizeof(idt_table) - 1;
+    set_idt(0, 0);
+    set_idt(1, 0);
+    set_idt(2, 0);
+    set_idt(3, 3);
+    set_idt(4, 3);
+    set_idt(5, 3);
+    set_idt(6, 0);
+    set_idt(7, 0);
+    set_idt(8, 0);
+    set_idt(9, 0);
+    set_idt(10, 0);
+    set_idt(11, 0);
+    set_idt(12, 0);
+    set_idt(13, 0);
+    set_idt(14, 0);
+    set_idt(15, 0);
+    set_idt(16, 0);
+    set_idt(17, 0);
+    set_idt(18, 0);
+    set_idt(19, 0);
+    /* Syscalls are done via
+        int 0x80 (unix) (rarely used)
+        int 0x81 (mach)
+        int 0x82 (thread)
+        int 0x83 (diag) (not handled here)
+        sysenter/sysexit (unix) -> we redirect that to int 0x90 */
+    set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
+    set_idt(0x80, 3); /* Unix Syscall */
+    set_idt(0x81, 3); /* Mach Syscalls */
+    set_idt(0x82, 3); /* thread Syscalls */
+
+    set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
+
+
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    cpu_x86_load_seg(env, R_DS, __USER_DS);
+    cpu_x86_load_seg(env, R_ES, __USER_DS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_FS, __USER_DS);
+    cpu_x86_load_seg(env, R_GS, __USER_DS);
+
+#elif defined(TARGET_PPC)
+    {
+        int i;
+        env->nip = regs->nip;
+        for(i = 0; i < 32; i++) {
+            env->gpr[i] = regs->gpr[i];
+        }
+    }
+#else
+#error unsupported target CPU
+#endif
+
+    if (use_gdbstub) {
+        printf("Waiting for gdb Connection on port 1234...\n");
+        gdbserver_start (1234);
+        gdb_handlesig(env, 0);
+    }
+
+    cpu_loop(env);
+    /* never exits */
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/mmap.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/mmap.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/mmap.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,411 @@
+/*
+ *  mmap support for qemu
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "qemu.h"
+
+//#define DEBUG_MMAP
+
+/* NOTE: all the constants are the HOST ones */
+int target_mprotect(unsigned long start, unsigned long len, int prot)
+{
+    unsigned long end, host_start, host_end, addr;
+    int prot1, ret;
+
+#ifdef DEBUG_MMAP
+    printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
+           prot & PROT_READ ? 'r' : '-',
+           prot & PROT_WRITE ? 'w' : '-',
+           prot & PROT_EXEC ? 'x' : '-');
+#endif
+
+    if ((start & ~TARGET_PAGE_MASK) != 0)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    end = start + len;
+    if (end < start)
+        return -EINVAL;
+    if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+        return -EINVAL;
+    if (len == 0)
+        return 0;
+
+    host_start = start & qemu_host_page_mask;
+    host_end = HOST_PAGE_ALIGN(end);
+    if (start > host_start) {
+        /* handle host page containing start */
+        prot1 = prot;
+        for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+            prot1 |= page_get_flags(addr);
+        }
+        if (host_end == host_start + qemu_host_page_size) {
+            for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+                prot1 |= page_get_flags(addr);
+            }
+            end = host_end;
+        }
+        ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
+        if (ret != 0)
+            return ret;
+        host_start += qemu_host_page_size;
+    }
+    if (end < host_end) {
+        prot1 = prot;
+        for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+            prot1 |= page_get_flags(addr);
+        }
+        ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
+                       prot1 & PAGE_BITS);
+        if (ret != 0)
+            return ret;
+        host_end -= qemu_host_page_size;
+    }
+
+    /* handle the pages in the middle */
+    if (host_start < host_end) {
+        ret = mprotect((void *)host_start, host_end - host_start, prot);
+        if (ret != 0)
+            return ret;
+    }
+    page_set_flags(start, start + len, prot | PAGE_VALID);
+    return 0;
+}
+
+/* map an incomplete host page */
+int mmap_frag(unsigned long host_start,
+               unsigned long start, unsigned long end,
+               int prot, int flags, int fd, unsigned long offset)
+{
+    unsigned long host_end, ret, addr;
+    int prot1, prot_new;
+
+    host_end = host_start + qemu_host_page_size;
+
+    /* get the protection of the target pages outside the mapping */
+    prot1 = 0;
+    for(addr = host_start; addr < host_end; addr++) {
+        if (addr < start || addr >= end)
+            prot1 |= page_get_flags(addr);
+    }
+
+    if (prot1 == 0) {
+        /* no page was there, so we allocate one */
+        ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
+                         flags | MAP_ANONYMOUS, -1, 0);
+        if (ret == -1)
+            return ret;
+    }
+    prot1 &= PAGE_BITS;
+
+    prot_new = prot | prot1;
+    if (!(flags & MAP_ANONYMOUS)) {
+        /* msync() won't work here, so we return an error if write is
+           possible while it is a shared mapping */
+#ifndef __APPLE__
+        if ((flags & MAP_TYPE) == MAP_SHARED &&
+#else
+        if ((flags &  MAP_SHARED) &&
+#endif
+            (prot & PROT_WRITE))
+            return -EINVAL;
+
+        /* adjust protection to be able to read */
+        if (!(prot1 & PROT_WRITE))
+            mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
+
+        /* read the corresponding file data */
+        pread(fd, (void *)start, end - start, offset);
+
+        /* put final protection */
+        if (prot_new != (prot1 | PROT_WRITE))
+            mprotect((void *)host_start, qemu_host_page_size, prot_new);
+    } else {
+        /* just update the protection */
+        if (prot_new != prot1) {
+            mprotect((void *)host_start, qemu_host_page_size, prot_new);
+        }
+    }
+    return 0;
+}
+
+/* NOTE: all the constants are the HOST ones */
+long target_mmap(unsigned long start, unsigned long len, int prot,
+                 int flags, int fd, unsigned long offset)
+{
+    unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
+#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
+    static unsigned long last_start = 0x40000000;
+#endif
+
+#ifdef DEBUG_MMAP
+    {
+        printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
+               start, len,
+               prot & PROT_READ ? 'r' : '-',
+               prot & PROT_WRITE ? 'w' : '-',
+               prot & PROT_EXEC ? 'x' : '-');
+        if (flags & MAP_FIXED)
+            printf("MAP_FIXED ");
+        if (flags & MAP_ANONYMOUS)
+            printf("MAP_ANON ");
+#ifndef MAP_TYPE
+# define MAP_TYPE 0x3
+#endif
+        switch(flags & MAP_TYPE) {
+        case MAP_PRIVATE:
+            printf("MAP_PRIVATE ");
+            break;
+        case MAP_SHARED:
+            printf("MAP_SHARED ");
+            break;
+        default:
+            printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
+            break;
+        }
+        printf("fd=%d offset=%lx\n", fd, offset);
+    }
+#endif
+
+    if (offset & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+
+    len = TARGET_PAGE_ALIGN(len);
+    if (len == 0)
+        return start;
+    host_start = start & qemu_host_page_mask;
+
+    if (!(flags & MAP_FIXED)) {
+#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
+        /* tell the kenel to search at the same place as i386 */
+        if (host_start == 0) {
+            host_start = last_start;
+            last_start += HOST_PAGE_ALIGN(len);
+        }
+#endif
+        if (qemu_host_page_size != qemu_real_host_page_size) {
+            /* NOTE: this code is only for debugging with '-p' option */
+            /* reserve a memory area */
+            host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
+            host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
+                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+            if (host_start == -1)
+                return host_start;
+            host_end = host_start + host_len;
+            start = HOST_PAGE_ALIGN(host_start);
+            end = start + HOST_PAGE_ALIGN(len);
+            if (start > host_start)
+                munmap((void *)host_start, start - host_start);
+            if (end < host_end)
+                munmap((void *)end, host_end - end);
+            /* use it as a fixed mapping */
+            flags |= MAP_FIXED;
+        } else {
+            /* if not fixed, no need to do anything */
+            host_offset = offset & qemu_host_page_mask;
+            host_len = len + offset - host_offset;
+            start = (long)mmap((void *)host_start, host_len,
+                               prot, flags, fd, host_offset);
+            if (start == -1)
+                return start;
+            /* update start so that it points to the file position at 'offset' */
+            if (!(flags & MAP_ANONYMOUS))
+                start += offset - host_offset;
+            goto the_end1;
+        }
+    }
+
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    end = start + len;
+    host_end = HOST_PAGE_ALIGN(end);
+
+    /* worst case: we cannot map the file because the offset is not
+       aligned, so we read it */
+    if (!(flags & MAP_ANONYMOUS) &&
+        (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
+        /* msync() won't work here, so we return an error if write is
+           possible while it is a shared mapping */
+#ifndef __APPLE__
+        if ((flags & MAP_TYPE) == MAP_SHARED &&
+#else
+        if ((flags & MAP_SHARED) &&
+#endif
+            (prot & PROT_WRITE))
+            return -EINVAL;
+        retaddr = target_mmap(start, len, prot | PROT_WRITE,
+                              MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
+                              -1, 0);
+        if (retaddr == -1)
+            return retaddr;
+        pread(fd, (void *)start, len, offset);
+        if (!(prot & PROT_WRITE)) {
+            ret = target_mprotect(start, len, prot);
+            if (ret != 0)
+                return ret;
+        }
+        goto the_end;
+    }
+
+    /* handle the start of the mapping */
+    if (start > host_start) {
+        if (host_end == host_start + qemu_host_page_size) {
+            /* one single host page */
+            ret = mmap_frag(host_start, start, end,
+                            prot, flags, fd, offset);
+            if (ret == -1)
+                return ret;
+            goto the_end1;
+        }
+        ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
+                        prot, flags, fd, offset);
+        if (ret == -1)
+            return ret;
+        host_start += qemu_host_page_size;
+    }
+    /* handle the end of the mapping */
+    if (end < host_end) {
+        ret = mmap_frag(host_end - qemu_host_page_size,
+                        host_end - qemu_host_page_size, host_end,
+                        prot, flags, fd,
+                        offset + host_end - qemu_host_page_size - start);
+        if (ret == -1)
+            return ret;
+        host_end -= qemu_host_page_size;
+    }
+
+    /* map the middle (easier) */
+    if (host_start < host_end) {
+        unsigned long offset1;
+	if (flags & MAP_ANONYMOUS)
+	  offset1 = 0;
+	else
+	  offset1 = offset + host_start - start;
+        ret = (long)mmap((void *)host_start, host_end - host_start,
+                         prot, flags, fd, offset1);
+        if (ret == -1)
+            return ret;
+    }
+ the_end1:
+    page_set_flags(start, start + len, prot | PAGE_VALID);
+ the_end:
+#ifdef DEBUG_MMAP
+    printf("target_mmap: ret=0x%lx\n", (long)start);
+    page_dump(stdout);
+    printf("\n");
+#endif
+    return start;
+}
+
+int target_munmap(unsigned long start, unsigned long len)
+{
+    unsigned long end, host_start, host_end, addr;
+    int prot, ret;
+
+#ifdef DEBUG_MMAP
+    printf("munmap: start=0x%lx len=0x%lx\n", start, len);
+#endif
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    if (len == 0)
+        return -EINVAL;
+    end = start + len;
+    host_start = start & qemu_host_page_mask;
+    host_end = HOST_PAGE_ALIGN(end);
+
+    if (start > host_start) {
+        /* handle host page containing start */
+        prot = 0;
+        for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+            prot |= page_get_flags(addr);
+        }
+        if (host_end == host_start + qemu_host_page_size) {
+            for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+                prot |= page_get_flags(addr);
+            }
+            end = host_end;
+        }
+        if (prot != 0)
+            host_start += qemu_host_page_size;
+    }
+    if (end < host_end) {
+        prot = 0;
+        for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+            prot |= page_get_flags(addr);
+        }
+        if (prot != 0)
+            host_end -= qemu_host_page_size;
+    }
+
+    /* unmap what we can */
+    if (host_start < host_end) {
+        ret = munmap((void *)host_start, host_end - host_start);
+        if (ret != 0)
+            return ret;
+    }
+
+    page_set_flags(start, start + len, 0);
+    return 0;
+}
+
+/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
+   blocks which have been allocated starting on a host page */
+long target_mremap(unsigned long old_addr, unsigned long old_size,
+                   unsigned long new_size, unsigned long flags,
+                   unsigned long new_addr)
+{
+#ifndef __APPLE__
+    /* XXX: use 5 args syscall */
+    new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
+    if (new_addr == -1)
+        return new_addr;
+    prot = page_get_flags(old_addr);
+    page_set_flags(old_addr, old_addr + old_size, 0);
+    page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
+    return new_addr;
+#else
+    qerror("target_mremap: unsupported\n");
+#endif
+
+}
+
+int target_msync(unsigned long start, unsigned long len, int flags)
+{
+    unsigned long end;
+
+    if (start & ~TARGET_PAGE_MASK)
+        return -EINVAL;
+    len = TARGET_PAGE_ALIGN(len);
+    end = start + len;
+    if (end < start)
+        return -EINVAL;
+    if (end == start)
+        return 0;
+
+    start &= qemu_host_page_mask;
+    return msync((void *)start, end - start, flags);
+}
+

Added: trunk/src/host/qemu-neo1973/darwin-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/qemu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/qemu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,179 @@
+#ifndef GEMU_H
+#define GEMU_H
+
+#include "thunk.h"
+
+#include <signal.h>
+#include <string.h>
+
+#include "cpu.h"
+
+#include "gdbstub.h"
+
+typedef siginfo_t target_siginfo_t;
+#define target_sigaction	sigaction
+#ifdef TARGET_I386
+struct target_pt_regs {
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	int  xds;
+	int  xes;
+	long orig_eax;
+	long eip;
+	int  xcs;
+	long eflags;
+	long esp;
+	int  xss;
+};
+struct	target_sigcontext {
+    int			sc_onstack;
+    int			sc_mask;
+    int	sc_eax;
+    int	sc_ebx;
+    int	sc_ecx;
+    int	sc_edx;
+    int	sc_edi;
+    int	sc_esi;
+    int	sc_ebp;
+    int	sc_esp;
+    int	sc_ss;
+    int	sc_eflags;
+    int	sc_eip;
+    int	sc_cs;
+    int	sc_ds;
+    int	sc_es;
+    int	sc_fs;
+    int	sc_gs;
+};
+
+#define __USER_CS	(0x17)
+#define __USER_DS	(0x1F)
+
+#elif defined(TARGET_PPC)
+struct target_pt_regs {
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long orig_gpr3;	/* Used for restarting system calls */
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long mq;		/* 601 only (not used at present) */
+					/* Used on APUS to hold IPL value. */
+	unsigned long trap;		/* Reason for being here */
+	unsigned long dar;		/* Fault registers */
+	unsigned long dsisr;
+	unsigned long result; 		/* Result of a system call */
+};
+
+struct target_sigcontext {
+    int		sc_onstack;     /* sigstack state to restore */
+    int		sc_mask;        /* signal mask to restore */
+    int		sc_ir;			/* pc */
+    int		sc_psw;         /* processor status word */
+    int		sc_sp;      	/* stack pointer if sc_regs == NULL */
+    void	*sc_regs;		/* (kernel private) saved state */
+};
+
+#endif
+
+typedef struct TaskState {
+    struct TaskState *next;
+    int used; /* non zero if used */
+    uint8_t stack[0];
+} __attribute__((aligned(16))) TaskState;
+
+void syscall_init(void);
+long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+long do_unix_syscall(void *cpu_env, int num);
+int do_sigaction(int sig, const struct sigaction *act,
+                 struct sigaction *oact);
+int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
+
+void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
+void qerror(const char *fmt, ...);
+
+void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
+
+extern CPUState *global_env;
+void cpu_loop(CPUState *env);
+void init_paths(const char *prefix);
+const char *path(const char *pathname);
+
+extern int loglevel;
+extern FILE *logfile;
+
+/* commpage.c */
+void commpage_init();
+void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
+
+/* signal.c */
+void process_pending_signals(void *cpu_env);
+void signal_init(void);
+int queue_signal(int sig, target_siginfo_t *info);
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
+long do_sigreturn(CPUState *env, int num);
+
+/* machload.c */
+int mach_exec(const char * filename, char ** argv, char ** envp,
+			  struct target_pt_regs * regs);
+
+/* mmap.c */
+int target_mprotect(unsigned long start, unsigned long len, int prot);
+long target_mmap(unsigned long start, unsigned long len, int prot,
+                 int flags, int fd, unsigned long offset);
+int target_munmap(unsigned long start, unsigned long len);
+long target_mremap(unsigned long old_addr, unsigned long old_size,
+                   unsigned long new_size, unsigned long flags,
+                   unsigned long new_addr);
+int target_msync(unsigned long start, unsigned long len, int flags);
+
+/* user access */
+
+/* XXX: todo protect every memory access */
+#define lock_user(x,y,z)    (void*)(x)
+#define unlock_user(x,y,z)
+
+/* Mac OS X ABI arguments processing */
+#ifdef TARGET_I386
+static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
+{
+    uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
+    *i+=4;
+    return tswap32(*args);
+}
+static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
+{
+    uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
+    *i+=8;
+    return tswap64(*args);
+}
+#elif defined(TARGET_PPC)
+static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
+{
+    /* XXX: won't work when args goes on stack after gpr10 */
+    uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
+    *i+=4;
+    return tswap32(args);
+}
+static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
+{
+    /* XXX: won't work when args goes on stack after gpr10 */
+    uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
+    *i+=(8 << 8) + 8;
+    return tswap64(args);
+}
+#endif
+
+#endif

Added: trunk/src/host/qemu-neo1973/darwin-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/signal.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/signal.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,463 @@
+/*
+ *  Emulation of Linux signals
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+
+#ifdef __ia64__
+#undef uc_mcontext
+#undef uc_sigmask
+#undef uc_stack
+#undef uc_link
+#endif
+
+#include <signal.h>
+
+#include "qemu.h"
+
+#define DEBUG_SIGNAL
+
+#define MAX_SIGQUEUE_SIZE 1024
+
+struct sigqueue {
+    struct sigqueue *next;
+    target_siginfo_t info;
+};
+
+struct emulated_sigaction {
+    struct target_sigaction sa;
+    int pending; /* true if signal is pending */
+    struct sigqueue *first;
+    struct sigqueue info; /* in order to always have memory for the
+                             first signal, we put it here */
+};
+
+struct sigaltstack target_sigaltstack_used = {
+    0, 0, SA_DISABLE
+};
+
+static struct emulated_sigaction sigact_table[NSIG];
+static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+static struct sigqueue *first_free; /* first free siginfo queue entry */
+static int signal_pending; /* non zero if a signal may be pending */
+
+static void host_signal_handler(int host_signum, siginfo_t *info,
+                                void *puc);
+
+
+static inline int host_to_target_signal(int sig)
+{
+    return sig;
+}
+
+static inline int target_to_host_signal(int sig)
+{
+    return sig;
+}
+
+/* siginfo conversion */
+
+
+
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
+{
+
+}
+
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
+{
+
+}
+
+void signal_init(void)
+{
+    struct sigaction act;
+    int i;
+
+    /* set all host signal handlers. ALL signals are blocked during
+       the handlers to serialize them. */
+    sigfillset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    act.sa_sigaction = host_signal_handler;
+    for(i = 1; i < NSIG; i++) {
+        sigaction(i, &act, NULL);
+    }
+
+    memset(sigact_table, 0, sizeof(sigact_table));
+
+    first_free = &sigqueue_table[0];
+    for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
+        sigqueue_table[i].next = &sigqueue_table[i + 1];
+    sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
+}
+
+/* signal queue handling */
+
+static inline struct sigqueue *alloc_sigqueue(void)
+{
+    struct sigqueue *q = first_free;
+    if (!q)
+        return NULL;
+    first_free = q->next;
+    return q;
+}
+
+static inline void free_sigqueue(struct sigqueue *q)
+{
+    q->next = first_free;
+    first_free = q;
+}
+
+/* abort execution with signal */
+void __attribute((noreturn)) force_sig(int sig)
+{
+    int host_sig;
+    host_sig = target_to_host_signal(sig);
+    fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
+            sig, strsignal(host_sig));
+    _exit(-host_sig);
+}
+
+/* queue a signal so that it will be send to the virtual CPU as soon
+   as possible */
+int queue_signal(int sig, target_siginfo_t *info)
+{
+    struct emulated_sigaction *k;
+    struct sigqueue *q, **pq;
+    target_ulong handler;
+
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "queue_signal: sig=%d\n",
+            sig);
+#endif
+    k = &sigact_table[sig - 1];
+    handler = (target_ulong)k->sa.sa_handler;
+    if (handler == SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != SIGCHLD &&
+            sig != SIGURG &&
+            sig != SIGWINCH) {
+            force_sig(sig);
+        } else {
+            return 0; /* indicate ignored */
+        }
+    } else if (handler == host_to_target_signal(SIG_IGN)) {
+        /* ignore signal */
+        return 0;
+    } else if (handler == host_to_target_signal(SIG_ERR)) {
+        force_sig(sig);
+    } else {
+        pq = &k->first;
+        if (!k->pending) {
+            /* first signal */
+            q = &k->info;
+        } else {
+            q = alloc_sigqueue();
+            if (!q)
+                return -EAGAIN;
+            while (*pq != NULL)
+                pq = &(*pq)->next;
+        }
+        *pq = q;
+        q->info = *info;
+        q->next = NULL;
+        k->pending = 1;
+        /* signal that a new signal is pending */
+        signal_pending = 1;
+        return 1; /* indicates that the signal was queued */
+    }
+}
+
+static void host_signal_handler(int host_signum, siginfo_t *info,
+                                void *puc)
+{
+    int sig;
+    target_siginfo_t tinfo;
+
+    /* the CPU emulator uses some host signals to detect exceptions,
+       we we forward to it some signals */
+    if (host_signum == SIGSEGV || host_signum == SIGBUS
+#if defined(TARGET_I386) && defined(USE_CODE_COPY)
+        || host_signum == SIGFPE
+#endif
+        ) {
+        if (cpu_signal_handler(host_signum, (void*)info, puc))
+            return;
+    }
+
+    /* get target signal number */
+    sig = host_to_target_signal(host_signum);
+    if (sig < 1 || sig > NSIG)
+        return;
+
+#if defined(DEBUG_SIGNAL)
+	fprintf(stderr, "qemu: got signal %d\n", sig);
+#endif
+    if (queue_signal(sig, &tinfo) == 1) {
+        /* interrupt the virtual CPU as soon as possible */
+        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
+    }
+}
+
+int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
+{
+    /* XXX: test errors */
+    if(oss)
+    {
+        oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
+        oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
+        oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
+    }
+    if(ss)
+    {
+        target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
+        target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
+        target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
+    }
+    return 0;
+}
+
+int do_sigaction(int sig, const struct sigaction *act,
+                 struct sigaction *oact)
+{
+    struct emulated_sigaction *k;
+    struct sigaction act1;
+    int host_sig;
+
+    if (sig < 1 || sig > NSIG)
+        return -EINVAL;
+
+    k = &sigact_table[sig - 1];
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
+            sig, (int)act, (int)oact);
+#endif
+    if (oact) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
+            sig, (int)act, (int)oact);
+#endif
+
+        oact->sa_handler = tswapl(k->sa.sa_handler);
+        oact->sa_flags = tswapl(k->sa.sa_flags);
+        oact->sa_mask = tswapl(k->sa.sa_mask);
+    }
+    if (act) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
+            act->sa_handler, act->sa_flags, act->sa_mask);
+#endif
+
+        k->sa.sa_handler = tswapl(act->sa_handler);
+        k->sa.sa_flags = tswapl(act->sa_flags);
+        k->sa.sa_mask = tswapl(act->sa_mask);
+        /* we update the host signal state */
+        host_sig = target_to_host_signal(sig);
+        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "sigaction handler going to call sigaction\n",
+            act->sa_handler, act->sa_flags, act->sa_mask);
+#endif
+
+            sigfillset(&act1.sa_mask);
+            act1.sa_flags = SA_SIGINFO;
+            if (k->sa.sa_flags & SA_RESTART)
+                act1.sa_flags |= SA_RESTART;
+            /* NOTE: it is important to update the host kernel signal
+               ignore state to avoid getting unexpected interrupted
+               syscalls */
+            if (k->sa.sa_handler == SIG_IGN) {
+                act1.sa_sigaction = (void *)SIG_IGN;
+            } else if (k->sa.sa_handler == SIG_DFL) {
+                act1.sa_sigaction = (void *)SIG_DFL;
+            } else {
+                act1.sa_sigaction = host_signal_handler;
+            }
+            sigaction(host_sig, &act1, NULL);
+        }
+    }
+    return 0;
+}
+
+
+#ifdef TARGET_I386
+
+static inline void *
+get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
+{
+    /* XXX Fix that */
+    if(target_sigaltstack_used.ss_flags & SA_DISABLE)
+    {
+        int esp;
+        /* Default to using normal stack */
+        esp = env->regs[R_ESP];
+
+        return (void *)((esp - frame_size) & -8ul);
+    }
+    else
+    {
+        return target_sigaltstack_used.ss_sp;
+    }
+}
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			void *set, CPUState *env)
+{
+	void *frame;
+	int i, err = 0;
+
+    fprintf(stderr, "setup_frame %d\n", sig);
+	frame = get_sigframe(ka, env, sizeof(*frame));
+
+	/* Set up registers for signal handler */
+	env->regs[R_ESP] = (unsigned long) frame;
+	env->eip = (unsigned long) ka->sa.sa_handler;
+
+	env->eflags &= ~TF_MASK;
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV /* , current */);
+}
+
+long do_sigreturn(CPUState *env, int num)
+{
+    int i = 0;
+    struct target_sigcontext *scp = get_int_arg(&i, env);
+    /* XXX Get current signal number */
+    /* XXX Adjust accordin to sc_onstack, sc_mask */
+    if(tswapl(scp->sc_onstack) & 0x1)
+        target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
+    else
+        target_sigaltstack_used.ss_flags &=  SA_DISABLE;
+    int set = tswapl(scp->sc_eax);
+    sigprocmask(SIG_SETMASK, &set, NULL);
+
+    fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
+    fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
+    fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
+
+    env->regs[R_EAX] = tswapl(scp->sc_eax);
+    env->regs[R_EBX] = tswapl(scp->sc_ebx);
+    env->regs[R_ECX] = tswapl(scp->sc_ecx);
+    env->regs[R_EDX] = tswapl(scp->sc_edx);
+    env->regs[R_EDI] = tswapl(scp->sc_edi);
+    env->regs[R_ESI] = tswapl(scp->sc_esi);
+    env->regs[R_EBP] = tswapl(scp->sc_ebp);
+    env->regs[R_ESP] = tswapl(scp->sc_esp);
+    env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
+    env->eflags = tswapl(scp->sc_eflags);
+    env->eip = tswapl(scp->sc_eip);
+    env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
+    env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
+    env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
+    env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
+    env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
+
+    /* Again, because our caller's caller will reset EAX */
+    return env->regs[R_EAX];
+}
+
+#else
+
+static void setup_frame(int sig, struct emulated_sigaction *ka,
+			void *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env, int num)
+{
+    int i = 0;
+    struct target_sigcontext *scp = get_int_arg(&i, env);
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -ENOSYS;
+}
+
+#endif
+
+void process_pending_signals(void *cpu_env)
+{
+    struct emulated_sigaction *k;
+    struct sigqueue *q;
+    target_ulong handler;
+    int sig;
+
+    if (!signal_pending)
+        return;
+
+    k = sigact_table;
+
+    for(sig = 1; sig <= NSIG; sig++) {
+        if (k->pending)
+            goto handle_signal;
+        k++;
+    }
+
+    /* if no signal is pending, just return */
+    signal_pending = 0;
+    return;
+handle_signal:
+    #ifdef DEBUG_SIGNAL
+    fprintf(stderr, "qemu: process signal %d\n", sig);
+    #endif
+    /* dequeue signal */
+    q = k->first;
+    k->first = q->next;
+    if (!k->first)
+        k->pending = 0;
+
+    sig = gdb_handlesig (cpu_env, sig);
+    if (!sig) {
+        fprintf (stderr, "Lost signal\n");
+        abort();
+    }
+
+    handler = k->sa.sa_handler;
+    if (handler == SIG_DFL) {
+        /* default handler : ignore some signal. The other are fatal */
+        if (sig != SIGCHLD &&
+            sig != SIGURG &&
+            sig != SIGWINCH) {
+            force_sig(sig);
+        }
+    } else if (handler == SIG_IGN) {
+        /* ignore sig */
+    } else if (handler == SIG_ERR) {
+        force_sig(sig);
+    } else {
+
+        setup_frame(sig, k, 0, cpu_env);
+	if (k->sa.sa_flags & SA_RESETHAND)
+            k->sa.sa_handler = SIG_DFL;
+    }
+    if (q != &k->info)
+        free_sigqueue(q);
+}
+
+

Added: trunk/src/host/qemu-neo1973/darwin-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/syscall.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/syscall.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1567 @@
+/*
+ *  Darwin syscalls
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/host_info.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <mach/message.h>
+
+#include <pthread.h>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <sys/uio.h>
+#include <sys/termios.h>
+#include <sys/ptrace.h>
+#include <net/if.h>
+
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include <sys/attr.h>
+
+#include <mach/ndr.h>
+#include <mach/mig_errors.h>
+
+#include <sys/xattr.h>
+
+#include "qemu.h"
+
+//#define DEBUG_SYSCALL
+
+#ifdef DEBUG_SYSCALL
+# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
+# define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
+# define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
+
+# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
+# define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
+    DEBUG_ENABLE_ALL();
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
+                           if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
+                         } while(0)
+#else
+# define DEBUG_FORCE_ENABLE_LOCAL()
+# define DEBUG_BEGIN_ENABLE
+# define DEBUG_END_ENABLE
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#endif
+
+enum {
+    bswap_out = 0,
+    bswap_in = 1
+};
+
+extern const char *interp_prefix;
+
+static inline long get_errno(long ret)
+{
+    if (ret == -1)
+        return -errno;
+    else
+        return ret;
+}
+
+static inline int is_error(long ret)
+{
+    return (unsigned long)ret >= (unsigned long)(-4096);
+}
+
+/* ------------------------------------------------------------
+   Mach syscall handling
+*/
+
+void static inline print_description_msg_header(mach_msg_header_t *hdr)
+{
+    char *name = NULL;
+    int i;
+    struct { int number; char *name; } msg_name[] =
+    {
+        /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
+        { 200,      "host_info" },
+        { 202,      "host_page_size" },
+        { 206,      "host_get_clock_service" },
+        { 206,      "host_get_clock_service" },
+        { 206,      "host_get_clock_service" },
+        { 306,      "host_get_clock_service" },
+        { 3204,     "mach_port_allocate" },
+        { 3206,     "mach_port_deallocate" },
+        { 3404,     "mach_ports_lookup" },
+        { 3409,     "mach_task_get_special_port" },
+        { 3414,     "mach_task_get_exception_ports" },
+        { 3418,     "mach_semaphore_create" },
+        { 3504,     "mach_semaphore_create" },
+        { 3509,     "mach_semaphore_create" },
+        { 3518,     "semaphore_create" },
+        { 3616,     "thread_policy" },
+        { 3801,     "vm_allocate" },
+        { 3802,     "vm_deallocate" },
+        { 3802,     "vm_deallocate" },
+        { 3803,     "vm_protect" },
+        { 3812,     "vm_map" },
+        { 4241776,  "lu_message_send_id" },  /* lookupd */
+        { 4241876,  "lu_message_reply_id" }, /* lookupd */
+    };
+
+    for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+        if(msg_name[i].number == hdr->msgh_id)
+        {
+            name = msg_name[i].name;
+            break;
+        }
+    }
+    if(!name)
+        DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
+    else
+        DPRINTF("%s\n", name);
+#if 0
+    DPRINTF("Bits: %8x\n", hdr->msgh_bits);
+    DPRINTF("Size: %8x\n", hdr->msgh_size);
+    DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
+    DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
+    DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
+
+    DPRINTF("Id  : %8x\n", hdr->msgh_id);
+
+    NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
+    DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
+    DPRINTF("%d %d %d %d %d %d %d %d\n",
+           ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
+           ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
+#endif
+}
+
+static inline void print_mach_msg_return(mach_msg_return_t ret)
+{
+    int i, found = 0;
+#define MACH_MSG_RET(msg) { msg, #msg }
+    struct { int code; char *name; } msg_name[] =
+    {
+        /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
+        /* send message */
+        MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
+        MACH_MSG_RET(MACH_SEND_NO_BUFFER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DATA),
+        MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DEST),
+        MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
+        MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
+        MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
+        MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
+        MACH_MSG_RET(MACH_SEND_INTERRUPTED),
+        MACH_MSG_RET(MACH_SEND_TIMED_OUT),
+
+        MACH_MSG_RET(MACH_RCV_BODY_ERROR),
+        MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
+
+        MACH_MSG_RET(MACH_RCV_IN_SET),
+        MACH_MSG_RET(MACH_RCV_INTERRUPTED),
+
+        MACH_MSG_RET(MACH_RCV_INVALID_DATA),
+        MACH_MSG_RET(MACH_RCV_INVALID_NAME),
+        MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
+
+        MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
+        MACH_MSG_RET(MACH_RCV_PORT_DIED),
+
+        MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
+        MACH_MSG_RET(MACH_RCV_TIMED_OUT),
+        MACH_MSG_RET(MACH_RCV_TOO_LARGE)
+    };
+#undef MACH_MSG_RET
+
+    if( ret == MACH_MSG_SUCCESS)
+        DPRINTF("MACH_MSG_SUCCESS\n");
+    else
+    {
+        for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+            if(msg_name[i].code == ret) {
+                DPRINTF("%s\n", msg_name[i].name);
+                found = 1;
+                break;
+            }
+        }
+        if(!found)
+            qerror("unknow mach message ret code %d\n", ret);
+    }
+}
+
+static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
+{
+    hdr->msgh_bits = tswap32(hdr->msgh_bits);
+    hdr->msgh_size = tswap32(hdr->msgh_size);
+    hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
+    hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
+    hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
+    hdr->msgh_id = tswap32(hdr->msgh_id);
+}
+
+struct complex_msg {
+            mach_msg_header_t hdr;
+            mach_msg_body_t body;
+};
+
+static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
+{
+    mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
+    int i,j;
+
+    if(bswap == bswap_in)
+        tswap32s(&complex_msg->body.msgh_descriptor_count);
+
+    DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
+
+    for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
+        switch(descr->type)
+        {
+            case MACH_MSG_PORT_DESCRIPTOR:
+                tswap32s(&descr->name);
+                descr++;
+                break;
+            case MACH_MSG_OOL_DESCRIPTOR:
+            {
+                mach_msg_ool_descriptor_t *ool = (void *)descr;
+                tswap32s((uint32_t *)&ool->address);
+                tswap32s(&ool->size);
+
+                descr = (mach_msg_port_descriptor_t *)(ool+1);
+                break;
+            }
+            case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+            {
+                mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
+                mach_port_name_t * port_names;
+
+                if(bswap == bswap_in)
+                {
+                    tswap32s((uint32_t *)&ool_ports->address);
+                    tswap32s(&ool_ports->count);
+                }
+
+                port_names = ool_ports->address;
+
+                for(j = 0; j < ool_ports->count; j++)
+                    tswap32s(&port_names[j]);
+
+                if(bswap == bswap_out)
+                {
+                    tswap32s((uint32_t *)&ool_ports->address);
+                    tswap32s(&ool_ports->count);
+                }
+
+                descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
+                break;
+            }
+            default: qerror("unknow mach msg descriptor type %x\n", descr->type);
+        }
+    }
+    if(bswap == bswap_out)
+        tswap32s(&complex_msg->body.msgh_descriptor_count);
+}
+
+static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
+{
+    if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
+
+    swap_mach_msg_header(hdr);
+
+    if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
+}
+
+static inline uint32_t target_mach_msg_trap(
+        mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
+        uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
+{
+    extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
+          mach_msg_size_t, mach_msg_size_t, mach_port_t,
+          mach_msg_timeout_t, mach_port_t);
+    mach_msg_audit_trailer_t *trailer;
+    mach_msg_id_t msg_id;
+    uint32_t ret = 0;
+    int i;
+
+    swap_mach_msg(hdr, bswap_in);
+
+    msg_id = hdr->msgh_id;
+
+    print_description_msg_header(hdr);
+
+    ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
+
+    print_mach_msg_return(ret);
+
+    if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
+    {
+        /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
+                probably always bswap it  */
+        /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
+                    natural_t units but according to xnu/osfmk/mach/message.h: "The size of
+                    the message must be specified in bytes" */
+        trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
+        /* XXX: Should probably do that based on the option asked by the sender, but dealing
+        with kernel answer seems more sound */
+        switch(trailer->msgh_trailer_size)
+        {
+            case sizeof(mach_msg_audit_trailer_t):
+                for(i = 0; i < 8; i++)
+                    tswap32s(&trailer->msgh_audit.val[i]);
+                /* Fall in mach_msg_security_trailer_t case */
+            case sizeof(mach_msg_security_trailer_t):
+                tswap32s(&trailer->msgh_sender.val[0]);
+                tswap32s(&trailer->msgh_sender.val[1]);
+                /* Fall in mach_msg_seqno_trailer_t case */
+            case sizeof(mach_msg_seqno_trailer_t):
+                tswap32s(&trailer->msgh_seqno);
+                /* Fall in mach_msg_trailer_t case */
+            case sizeof(mach_msg_trailer_t):
+                tswap32s(&trailer->msgh_trailer_type);
+                tswap32s(&trailer->msgh_trailer_size);
+                break;
+            case 0:
+                /* Safer not to byteswap, but probably wrong */
+                break;
+            default:
+                qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
+                break;
+        }
+    }
+
+    /* Special message handling */
+    switch (msg_id) {
+        case 200: /* host_info */
+        {
+            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
+            struct {
+                uint32_t unknow1;
+                uint32_t max_cpus;
+                uint32_t avail_cpus;
+                uint32_t memory_size;
+                uint32_t cpu_type;
+                uint32_t cpu_subtype;
+            } *data = (void *)(err+1);
+
+            DPRINTF("maxcpu = 0x%x\n",   data->max_cpus);
+            DPRINTF("numcpu = 0x%x\n",   data->avail_cpus);
+            DPRINTF("memsize = 0x%x\n",  data->memory_size);
+
+#if defined(TARGET_I386)
+            data->cpu_type = CPU_TYPE_I386;
+            DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
+            data->cpu_subtype = CPU_SUBTYPE_PENT;
+            DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
+#elif defined(TARGET_PPC)
+            data->cpu_type = CPU_TYPE_POWERPC;
+            DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
+            data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
+            DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
+#else
+# error target not supported
+#endif
+            break;
+        }
+        case 202: /* host_page_size */
+        {
+            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
+            uint32_t *pagesize = (uint32_t *)(err+1);
+
+            DPRINTF("pagesize = %d\n", *pagesize);
+            break;
+        }
+        default: break;
+    }
+
+    swap_mach_msg(hdr, bswap_out);
+
+    return ret;
+}
+
+long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    extern uint32_t mach_reply_port();
+
+    long ret = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    DPRINTF("mach syscall %d : " , num);
+
+    switch(num) {
+    /* see xnu/osfmk/mach/syscall_sw.h */
+    case -26:
+        DPRINTF("mach_reply_port()\n");
+        ret = mach_reply_port();
+        break;
+    case -27:
+        DPRINTF("mach_thread_self()\n");
+        ret = mach_thread_self();
+        break;
+    case -28:
+        DPRINTF("mach_task_self()\n");
+        ret = mach_task_self();
+        break;
+    case -29:
+        DPRINTF("mach_host_self()\n");
+        ret = mach_host_self();
+        break;
+    case -31:
+        DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -33:
+        DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
+        ret = semaphore_signal_trap(arg1);
+        break;
+    case -34:
+        DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
+        ret = semaphore_signal_all_trap(arg1);
+        break;
+    case -35:
+        DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
+        ret = semaphore_signal_thread_trap(arg1,arg2);
+        break;
+#endif
+    case -36:
+        DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
+        extern int semaphore_wait_trap(int); // XXX: is there any header for that?
+        ret = semaphore_wait_trap(arg1);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -37:
+        DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
+        ret = semaphore_wait_signal_trap(arg1,arg2);
+        break;
+#endif
+    case -43:
+        DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3, arg4, arg5);
+        ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
+        tswap32s((uint32_t*)arg3);
+        break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+    case -61:
+        DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
+                arg1, arg2, arg3);
+        ret = syscall_thread_switch(arg1, arg2, arg3);  // just a hint to the scheduler; can drop?
+        break;
+#endif
+    case -89:
+        DPRINTF("mach_timebase_info(0x%x)\n", arg1);
+        struct mach_timebase_info info;
+        ret = mach_timebase_info(&info);
+        if(!is_error(ret))
+        {
+            struct mach_timebase_info *outInfo = (void*)arg1;
+            outInfo->numer = tswap32(info.numer);
+            outInfo->denom = tswap32(info.denom);
+        }
+        break;
+    case -90:
+        DPRINTF("mach_wait_until()\n");
+        extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
+        ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
+        break;
+    case -91:
+        DPRINTF("mk_timer_create()\n");
+        extern int mk_timer_create(); // XXX: is there any header for that?
+        ret = mk_timer_create();
+        break;
+    case -92:
+        DPRINTF("mk_timer_destroy()\n");
+        extern int mk_timer_destroy(int); // XXX: is there any header for that?
+        ret = mk_timer_destroy(arg1);
+        break;
+    case -93:
+        DPRINTF("mk_timer_create()\n");
+        extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
+        ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
+        break;
+    case -94:
+        DPRINTF("mk_timer_cancel()\n");
+        extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
+        ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
+        if((!is_error(ret)) && arg2)
+            tswap64s((uint64_t *)arg2);
+        break;
+    default:
+        gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(0);
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   thread type syscall handling
+*/
+long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
+                uint32_t arg8)
+{
+    extern uint32_t cthread_set_self(uint32_t);
+    extern uint32_t processor_facilities_used();
+    long ret = 0;
+
+    arg1 = tswap32(arg1);
+    arg2 = tswap32(arg2);
+    arg3 = tswap32(arg3);
+    arg4 = tswap32(arg4);
+    arg5 = tswap32(arg5);
+    arg6 = tswap32(arg6);
+    arg7 = tswap32(arg7);
+    arg8 = tswap32(arg8);
+
+    DPRINTF("thread syscall %d : " , num);
+
+    switch(num) {
+#ifdef TARGET_I386
+    case 0x3:
+#endif
+    case 0x7FF1: /* cthread_set_self */
+        DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
+        ret = cthread_set_self(arg1);
+#ifdef TARGET_I386
+        /* we need to update the LDT with the address of the thread */
+        write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
+                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+        /* New i386 convention, %gs should be set to our this LDT entry */
+        cpu_x86_load_seg(cpu_env, R_GS, 0x27);
+        /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
+        ret = 0x27;
+#endif
+        break;
+    case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
+        DPRINTF("pthread_self()\n");
+        ret = (uint32_t)pthread_self();
+        break;
+    case 0x7FF3:
+        DPRINTF("processor_facilities_used()\n");
+#ifdef __i386__
+        qerror("processor_facilities_used: not implemented!\n");
+#else
+        ret = (uint32_t)processor_facilities_used();
+#endif
+        break;
+    default:
+        gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
+        gdb_handlesig (cpu_env, SIGTRAP);
+        exit(0);
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   ioctl handling
+*/
+static inline void byteswap_termios(struct termios *t)
+{
+    tswap32s((uint32_t*)&t->c_iflag);
+    tswap32s((uint32_t*)&t->c_oflag);
+    tswap32s((uint32_t*)&t->c_cflag);
+    tswap32s((uint32_t*)&t->c_lflag);
+    /* 20 (char) bytes then */
+    tswap32s((uint32_t*)&t->c_ispeed);
+    tswap32s((uint32_t*)&t->c_ospeed);
+}
+
+static inline void byteswap_winsize(struct winsize *w)
+{
+    tswap16s(&w->ws_row);
+    tswap16s(&w->ws_col);
+    tswap16s(&w->ws_xpixel);
+    tswap16s(&w->ws_ypixel);
+}
+
+#define STRUCT(name, list...) STRUCT_ ## name,
+#define STRUCT_SPECIAL(name) STRUCT_ ## name,
+enum {
+#include "ioctls_types.h"
+};
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
+#define STRUCT_SPECIAL(name)
+#include "ioctls_types.h"
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+typedef struct IOCTLEntry {
+    unsigned int target_cmd;
+    unsigned int host_cmd;
+    const char *name;
+    int access;
+    const argtype arg_type[5];
+} IOCTLEntry;
+
+#define IOC_R 0x0001
+#define IOC_W 0x0002
+#define IOC_RW (IOC_R | IOC_W)
+
+#define MAX_STRUCT_SIZE 4096
+
+IOCTLEntry ioctl_entries[] = {
+#define IOCTL(cmd, access, types...) \
+    { cmd, cmd, #cmd, access, { types } },
+#include "ioctls.h"
+    { 0, 0, },
+};
+
+/* ??? Implement proper locking for ioctls.  */
+static long do_ioctl(long fd, long cmd, long arg)
+{
+    const IOCTLEntry *ie;
+    const argtype *arg_type;
+    int ret;
+    uint8_t buf_temp[MAX_STRUCT_SIZE];
+    int target_size;
+    void *argptr;
+
+    ie = ioctl_entries;
+    for(;;) {
+        if (ie->target_cmd == 0) {
+            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
+            return -ENOSYS;
+        }
+        if (ie->target_cmd == cmd)
+            break;
+        ie++;
+    }
+    arg_type = ie->arg_type;
+#if defined(DEBUG)
+    gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
+#endif
+    switch(arg_type[0]) {
+    case TYPE_NULL:
+        /* no argument */
+        ret = get_errno(ioctl(fd, ie->host_cmd));
+        break;
+    case TYPE_PTRVOID:
+    case TYPE_INT:
+        /* int argment */
+        ret = get_errno(ioctl(fd, ie->host_cmd, arg));
+        break;
+    case TYPE_PTR:
+        arg_type++;
+        target_size = thunk_type_size(arg_type, 0);
+        switch(ie->access) {
+        case IOC_R:
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(arg, target_size, 0);
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        case IOC_W:
+            argptr = lock_user(arg, target_size, 1);
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            break;
+        default:
+        case IOC_RW:
+            argptr = lock_user(arg, target_size, 1);
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(arg, target_size, 0);
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        }
+        break;
+    default:
+        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
+        ret = -ENOSYS;
+        break;
+    }
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   Unix syscall handling
+*/
+
+static inline void byteswap_attrlist(struct attrlist *a)
+{
+    tswap16s(&a->bitmapcount);
+    tswap16s(&a->reserved);
+    tswap32s(&a->commonattr);
+    tswap32s(&a->volattr);
+    tswap32s(&a->dirattr);
+    tswap32s(&a->fileattr);
+    tswap32s(&a->forkattr);
+}
+
+struct attrbuf_header {
+    unsigned long length;
+};
+
+static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
+{
+    DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
+}
+
+static inline void byteswap_statfs(struct statfs *s)
+{
+    tswap16s((uint16_t*)&s->f_otype);
+    tswap16s((uint16_t*)&s->f_oflags);
+    tswap32s((uint32_t*)&s->f_bsize);
+    tswap32s((uint32_t*)&s->f_iosize);
+    tswap32s((uint32_t*)&s->f_blocks);
+    tswap32s((uint32_t*)&s->f_bfree);
+    tswap32s((uint32_t*)&s->f_bavail);
+    tswap32s((uint32_t*)&s->f_files);
+    tswap32s((uint32_t*)&s->f_ffree);
+    tswap32s((uint32_t*)&s->f_fsid.val[0]);
+    tswap32s((uint32_t*)&s->f_fsid.val[1]);
+    tswap16s((uint16_t*)&s->f_reserved1);
+    tswap16s((uint16_t*)&s->f_type);
+    tswap32s((uint32_t*)&s->f_flags);
+}
+
+static inline void byteswap_stat(struct stat *s)
+{
+    tswap32s((uint32_t*)&s->st_dev);
+    tswap32s(&s->st_ino);
+    tswap16s(&s->st_mode);
+    tswap16s(&s->st_nlink);
+    tswap32s(&s->st_uid);
+    tswap32s(&s->st_gid);
+    tswap32s((uint32_t*)&s->st_rdev);
+    tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
+    tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
+    tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
+    tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
+    tswap64s((uint64_t*)&s->st_size);
+    tswap64s((uint64_t*)&s->st_blocks);
+    tswap32s((uint32_t*)&s->st_blksize);
+    tswap32s(&s->st_flags);
+    tswap32s(&s->st_gen);
+}
+
+static inline void byteswap_dirents(struct dirent *d, int bytes)
+{
+    char *b;
+    for( b = (char*)d; (int)b < (int)d+bytes; )
+    {
+        unsigned short s = ((struct dirent *)b)->d_reclen;
+        tswap32s(&((struct dirent *)b)->d_ino);
+        tswap16s(&((struct dirent *)b)->d_reclen);
+        if(s<=0)
+            break;
+        b += s;
+    }
+}
+
+static inline void byteswap_iovec(struct iovec *v, int n)
+{
+    int i;
+    for(i = 0; i < n; i++)
+    {
+        tswap32s((uint32_t*)&v[i].iov_base);
+        tswap32s((uint32_t*)&v[i].iov_len);
+    }
+}
+
+static inline void byteswap_timeval(struct timeval *t)
+{
+    tswap32s((uint32_t*)&t->tv_sec);
+    tswap32s((uint32_t*)&t->tv_usec);
+}
+
+long do_unix_syscall_indirect(void *cpu_env, int num);
+long do_sync();
+long do_exit(uint32_t arg1);
+long do_getlogin(char *out, uint32_t size);
+long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
+long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
+long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
+long do_execve(char* arg1, char ** arg2, char ** arg3);
+long do_getgroups(uint32_t arg1, gid_t * arg2);
+long do_gettimeofday(struct timeval * arg1, void * arg2);
+long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
+long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
+long do_utimes(char * arg1, struct timeval * arg2);
+long do_futimes(uint32_t arg1, struct timeval * arg2);
+long do_statfs(char * arg1, struct statfs * arg2);
+long do_fstatfs(uint32_t arg1, struct statfs * arg2);
+long do_stat(char * arg1, struct stat * arg2);
+long do_fstat(uint32_t arg1, struct stat * arg2);
+long do_lstat(char * arg1, struct stat * arg2);
+long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
+long do_lseek(void *cpu_env, int num);
+long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */);
+long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
+long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
+long do_fcntl(int fd, int cmd, int arg);
+
+long no_syscall(void *cpu_env, int num);
+
+long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
+{
+    DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
+    long ret = pread(arg1, arg2, arg3, arg4);
+    return ret;
+}
+
+long do_read(int d, void *buf, size_t nbytes)
+{
+    DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
+    long ret = get_errno(read(d, buf, nbytes));
+    if(!is_error(ret))
+        DPRINTF("%x\n", *(uint32_t*)buf);
+    return ret;
+}
+
+long unimpl_unix_syscall(void *cpu_env, int num);
+
+typedef long (*syscall_function_t)(void *cpu_env, int num);
+
+
+/* define a table that will handle the syscall number->function association */
+#define VOID    void
+#define INT     (uint32_t)get_int_arg(&i, cpu_env)
+#define INT64   (uint64_t)get_int64_arg(&i, cpu_env)
+#define UINT    (unsigned int)INT
+#define PTR     (void*)INT
+
+#define SIZE    INT
+#define OFFSET  INT64
+
+#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) {  return (long)function(); }
+#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1;  return (long)function(arg1); }
+#define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0;  typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
+#define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
+#define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
+#define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5;  return (long)function(arg1, arg2, arg3, arg4, arg5); }
+#define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
+#define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
+#define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
+#define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
+#define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
+#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
+#define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, args)
+
+#include "syscalls.h"
+
+#undef ENTRY
+#undef WRAPPER_CALL_DIRECT
+#undef WRAPPER_CALL_NOERRNO
+#undef WRAPPER_CALL_INDIRECT
+#undef OFFSET
+#undef SIZE
+#undef INT
+#undef PTR
+#undef INT64
+
+#define _ENTRY(name, number, function, nargs, call_type) [number] = {\
+        name, \
+        number, \
+        (syscall_function_t)function, \
+        nargs, \
+        call_type  \
+        },
+
+#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)  _ENTRY(name, number, __qemu_##function, nargs, call_type)
+#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
+#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
+#define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
+
+#define CALL_DIRECT 1
+#define CALL_INDIRECT 2
+#define CALL_NOERRNO  (CALL_DIRECT | 4 /* = 5 */)
+
+struct unix_syscall {
+    char * name;
+    int number;
+    syscall_function_t function;
+    int nargs;
+    int call_type;
+} unix_syscall_table[SYS_MAXSYSCALL] = {
+#include "syscalls.h"
+};
+
+#undef ENTRY
+#undef _ENTRY
+#undef ENTRY_CALL_DIRECT
+#undef ENTRY_CALL_INDIRECT
+#undef ENTRY_CALL_NOERRNO
+
+/* Actual syscalls implementation */
+
+long do_unix_syscall_indirect(void *cpu_env, int num)
+{
+    long ret;
+    int new_num;
+    int i = 0;
+
+    new_num = get_int_arg(&i, cpu_env);
+#ifdef TARGET_I386
+    ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
+    /* XXX: not necessary */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
+#elif TARGET_PPC
+    {
+        int i;
+        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
+        for(i = 3; i < 11; i++)
+            *regs[i] = *regs[i+1];
+        /* XXX: not necessary */
+        *regs[0] = new_num;
+    }
+#endif
+    ret = do_unix_syscall(cpu_env, new_num);
+#ifdef TARGET_I386
+    ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
+    /* XXX: not necessary */
+    ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
+#elif TARGET_PPC
+    {
+        int i;
+        /* XXX: not really needed those regs are volatile accross calls */
+        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
+        for(i = 11; i > 3; i--)
+            *regs[i] = *regs[i-1];
+        regs[3] = new_num;
+        *regs[0] = num;
+    }
+#endif
+    return ret;
+}
+
+long do_exit(uint32_t arg1)
+{
+    exit(arg1);
+    /* not reached */
+    return -1;
+}
+
+long do_sync()
+{
+    sync();
+    return 0;
+}
+
+long do_getlogin(char *out, uint32_t size)
+{
+    char *login = getlogin();
+    if(!login)
+        return -1;
+    memcpy(out, login, size);
+    return 0;
+}
+long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
+{
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
+    return get_errno(open(arg1, arg2, arg3));
+}
+
+long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
+    ret = get_errno(getfsstat(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg1)
+        byteswap_statfs(arg1);
+    return ret;
+}
+
+long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
+{
+    long ret;
+    DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
+    gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
+    if(arg2)
+        tswap32s(arg2);
+    ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
+    if((!is_error(ret)) && arg3)
+        tswap32s(arg3);
+    if(arg2)
+        tswap32s(arg2);
+    return ret;
+}
+
+long do_execve(char* arg1, char ** arg2, char ** arg3)
+{
+    long ret;
+    char **argv = arg2;
+    char **envp = arg3;
+    int argc;
+    int envc;
+
+    /* XXX: don't let the %s stay in here */
+    DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
+
+    for(argc = 0; argv[argc]; argc++);
+    for(envc = 0; envp[envc]; envc++);
+
+    argv = (char**)malloc(sizeof(char*)*argc);
+    envp = (char**)malloc(sizeof(char*)*envc);
+
+    for(; argc >= 0; argc--)
+        argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
+
+    for(; envc >= 0; envc--)
+        envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
+
+    ret = get_errno(execve(arg1, argv, envp));
+    free(argv);
+    free(envp);
+    return ret;
+}
+
+long do_getgroups(uint32_t arg1, gid_t * arg2)
+{
+    long ret;
+    int i;
+    DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
+    ret = get_errno(getgroups(arg1, arg2));
+    if(ret > 0)
+        for(i = 0; i < arg1; i++)
+            tswap32s(&arg2[i]);
+    return ret;
+}
+
+long do_gettimeofday(struct timeval * arg1, void * arg2)
+{
+    long ret;
+    DPRINTF("gettimeofday(%p, %p)\n",
+            arg1, arg2);
+    ret = get_errno(gettimeofday(arg1, arg2));
+    if(!is_error(ret))
+    {
+        /* timezone no longer used according to the manpage, so don't bother with it */
+        byteswap_timeval(arg1);
+    }
+    return ret;
+}
+
+long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
+    if(arg2)
+        byteswap_iovec(arg2, arg3);
+    ret = get_errno(readv(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg2)
+        byteswap_iovec(arg2, arg3);
+    return ret;
+}
+
+long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
+{
+    long ret;
+    DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
+    if(arg2)
+        byteswap_iovec(arg2, arg3);
+    ret = get_errno(writev(arg1, arg2, arg3));
+    if((!is_error(ret)) && arg2)
+        byteswap_iovec(arg2, arg3);
+    return ret;
+}
+
+long do_utimes(char * arg1, struct timeval * arg2)
+{
+    DPRINTF("utimes(%p, %p)\n", arg1, arg2);
+    if(arg2)
+    {
+        byteswap_timeval(arg2);
+        byteswap_timeval(arg2+1);
+    }
+    return get_errno(utimes(arg1, arg2));
+}
+
+long do_futimes(uint32_t arg1, struct timeval * arg2)
+{
+    DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
+    if(arg2)
+    {
+        byteswap_timeval(arg2);
+        byteswap_timeval(arg2+1);
+    }
+    return get_errno(futimes(arg1, arg2));
+}
+
+long do_statfs(char * arg1, struct statfs * arg2)
+{
+    long ret;
+    DPRINTF("statfs(%p, %p)\n", arg1, arg2);
+    ret = get_errno(statfs(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_statfs(arg2);
+    return ret;
+}
+
+long do_fstatfs(uint32_t arg1, struct statfs* arg2)
+{
+    long ret;
+    DPRINTF("fstatfs(0x%x, %p)\n",
+            arg1, arg2);
+    ret = get_errno(fstatfs(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_statfs(arg2);
+
+    return ret;
+}
+
+long do_stat(char * arg1, struct stat * arg2)
+{
+    long ret;
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("stat(%s, %p)\n", arg1, arg2);
+    ret = get_errno(stat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_fstat(uint32_t arg1, struct stat * arg2)
+{
+    long ret;
+    DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
+    ret = get_errno(fstat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_lstat(char * arg1, struct stat * arg2)
+{
+    long ret;
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
+    ret = get_errno(lstat(arg1, arg2));
+    if(!is_error(ret))
+        byteswap_stat(arg2);
+    return ret;
+}
+
+long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
+{
+    long ret;
+    DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
+    if(arg4)
+        tswap32s((uint32_t *)arg4);
+    ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
+    if(arg4)
+        tswap32s((uint32_t *)arg4);
+    if(!is_error(ret))
+        byteswap_dirents(arg2, ret);
+    return ret;
+}
+
+long do_lseek(void *cpu_env, int num)
+{
+    long ret;
+    int i = 0;
+    uint32_t arg1 = get_int_arg(&i, cpu_env);
+    uint64_t offset = get_int64_arg(&i, cpu_env);
+    uint32_t arg3 = get_int_arg(&i, cpu_env);
+    uint64_t r = lseek(arg1, offset, arg3);
+#ifdef TARGET_I386
+    /* lowest word in eax, highest in edx */
+    ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
+    ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
+#elif defined TARGET_PPC
+    ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
+    ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
+#else
+    qerror("64 bit ret value on your arch?");
+#endif
+    return get_errno(ret);
+}
+
+void no_swap(void * oldp, int size)
+{
+}
+
+void sysctl_tswap32s(void * oldp, int size)
+{
+    tswap32s(oldp);
+}
+
+void bswap_oid(uint32_t * oldp, int size)
+{
+    int count = size / sizeof(int);
+    int i = 0;
+    do { tswap32s(oldp + i); } while (++i < count);
+}
+
+void sysctl_usrstack(uint32_t * oldp, int size)
+{
+    DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
+    tswap32s(oldp);
+}
+
+void sysctl_ncpu(uint32_t * ncpu, int size)
+{
+    *ncpu = 0x1;
+    DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
+    tswap32s(ncpu);
+}
+
+void sysctl_exec(char * exec, int size)
+{
+    DPRINTF("sysctl_exec: %s\n", exec);
+}
+
+void sysctl_translate(char * exec, int size)
+{
+    DPRINTF("sysctl_translate: %s\n", exec);
+}
+
+struct sysctl_dir {
+    int num;
+    const char * name;
+    void (*swap_func)(void *, int);
+    struct sysctl_dir *childs;
+};
+
+#define ENTRYD(num, name, childs) { num, name, NULL, childs }
+#define ENTRYE(num, name, func)   { num, name, (void (*)(void *, int))func, NULL  }
+struct sysctl_dir sysctls_unspec[] = {
+    ENTRYE(3,  "oip", bswap_oid),
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls_kern[] = {
+    ENTRYE(KERN_TRANSLATE,          "translate",    sysctl_translate), /* 44 */
+    ENTRYE(KERN_EXEC,               "exec",         sysctl_exec), /* 45 */
+    ENTRYE(KERN_USRSTACK32,          "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
+    ENTRYE(KERN_SHREG_PRIVATIZABLE,  "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls_hw[] = {
+    ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
+    ENTRYE(104, "104", no_swap),
+    ENTRYE(105, "105", no_swap),
+    { 0, NULL, NULL, NULL }
+};
+
+struct sysctl_dir sysctls[] = {
+    ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
+    ENTRYD(CTL_KERN, "kern", sysctls_kern),
+    ENTRYD(CTL_HW,   "hw",   sysctls_hw ),
+    { 0, NULL, NULL, NULL }
+};
+
+#undef ENTRYE
+#undef ENTRYD
+
+static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
+{
+    if(!sysctl_elmt)
+        return NULL;
+    for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
+        if(sysctl_elmt->num == mib)
+            return sysctl_elmt;
+    }
+    return NULL;
+}
+
+static inline long bswap_syctl(int * mib, int count, void *buf, int size)
+{
+    int i;
+    struct sysctl_dir * sysctl = sysctls;
+    struct sysctl_dir * ret = NULL;
+
+    for(i = 0; i < count; i++) {
+
+        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
+            gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
+            return -ENOTDIR;
+        }
+        if(!(sysctl = sysctl->childs))
+            break;
+    }
+    
+    if(ret->childs)
+        qerror("we shouldn't have a directory element\n");
+
+    ret->swap_func(buf, size);
+    return 0;
+}
+
+static inline void print_syctl(int * mib, int count)
+{
+    int i;
+    struct sysctl_dir * sysctl = sysctls;
+    struct sysctl_dir * ret = NULL;
+
+    for(i = 0; i < count; i++) {
+        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
+            gemu_log("print_syctl: can't find mib %d\n", mib[i]);
+            return;
+        }
+        DPRINTF("%s.", sysctl->name);
+        if(!(sysctl = sysctl->childs))
+            break;
+    }
+    DPRINTF("\n");
+}
+
+long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */)
+{
+    long ret = 0;
+    int i;
+    DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
+            name, namelen, oldp, oldlenp, newp, newlen);
+    if(name) {
+        i = 0;
+        do { tswap32s( name + i); } while (++i < namelen);
+        print_syctl(name, namelen);
+        //bswap_syctl(name, namelen, newp, newlen);
+        tswap32s((uint32_t*)oldlenp);
+    }
+        
+    if(name) /* Sometimes sysctl is called with no arg1, ignore */
+        ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
+        return -ENOTDIR;
+    }
+#endif
+
+    if(name) {
+        //bswap_syctl(name, namelen, newp, newlen);
+        tswap32s((uint32_t*)oldlenp);
+
+        i = 0;
+        do { tswap32s( name + i); } while (++i < namelen);
+    }
+    return ret;
+}
+
+long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
+{
+    struct attrlist * attrlist = (void *)arg2;
+    long ret;
+
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    gemu_log("SYS_getdirentriesattr unimplemented\n");
+    return -ENOTSUP;
+#endif
+    /* XXX: don't let the %s stay in there */
+    DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
+            (char *)arg1, arg2, arg3, arg4, arg5);
+
+    if(arg2) /* XXX: We should handle that in a copy especially
+        if the structure is not writable */
+        byteswap_attrlist(attrlist);
+
+    ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
+
+    if(!is_error(ret))
+    {
+        byteswap_attrbuf((void *)arg3, attrlist);
+        byteswap_attrlist(attrlist);
+    }
+    return ret;
+}
+
+long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
+{
+    DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
+            arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
+    qerror("SYS_getdirentriesattr unimplemented\n");
+#endif
+
+    return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
+                                       (unsigned long *)arg5, (unsigned long *)arg6,
+                                       (unsigned long *)arg7, arg8));
+}
+
+static inline void bswap_flock(struct flock *f)
+{
+    tswap64s(&f->l_start);
+    tswap64s(&f->l_len);
+    tswap32s(&f->l_pid);
+    tswap16s(&f->l_type);
+    tswap16s(&f->l_whence);
+}
+
+static inline void bswap_fstore(struct fstore *f)
+{
+    tswap32s(&f->fst_flags);
+    tswap32s(&f->fst_posmode);
+    tswap64s(&f->fst_offset);
+    tswap64s(&f->fst_length);
+    tswap64s(&f->fst_bytesalloc);
+}
+
+static inline void bswap_radvisory(struct radvisory *f)
+{
+    tswap64s(&f->ra_offset);
+    tswap32s(&f->ra_count);
+}
+
+static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
+{
+    tswap64s(&f->fbt_offset);
+    tswap32s((uint32_t*)&f->fbt_length);
+    tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
+}
+
+static inline void bswap_log2phys(struct log2phys *f)
+{
+    tswap32s(&f->l2p_flags);
+    tswap64s(&f->l2p_contigbytes);
+    tswap64s(&f->l2p_devoffset);
+}
+
+static inline void bswap_fcntl_arg(int cmd, void * arg)
+{
+    switch(cmd)
+    {
+        case F_DUPFD:
+        case F_GETFD:
+        case F_SETFD:
+        case F_GETFL:
+        case F_SETFL:
+        case F_GETOWN:
+        case F_SETOWN:
+        case F_SETSIZE:
+        case F_RDAHEAD:
+        case F_FULLFSYNC:
+            break;
+        case F_GETLK:
+        case F_SETLK:
+        case F_SETLKW:
+            bswap_flock(arg);
+            break;
+        case F_PREALLOCATE:
+            bswap_fstore(arg);
+            break;
+        case F_RDADVISE:
+            bswap_radvisory(arg);
+            break;
+        case F_READBOOTSTRAP:
+        case F_WRITEBOOTSTRAP:
+            bswap_fbootstraptransfer(arg);
+            break;
+        case F_LOG2PHYS:
+            bswap_log2phys(arg);
+            break;
+        default:
+            gemu_log("unknow cmd in fcntl\n");
+    }
+}
+
+long do_fcntl(int fd, int cmd, int arg)
+{
+    long ret;
+    bswap_fcntl_arg(cmd, (void *)arg);
+    ret = get_errno(fcntl(fd, cmd, arg));
+    if(!is_error(ret))
+        bswap_fcntl_arg(cmd, (void *)arg);
+    return ret;
+}
+
+long no_syscall(void *cpu_env, int num)
+{
+    /* XXX: We should probably fordward it to the host kernel */
+    qerror("no unix syscall %d\n", num);
+    /* not reached */
+    return -1;
+}
+
+long unimpl_unix_syscall(void *cpu_env, int num)
+{
+    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
+        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
+
+    gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
+    gdb_handlesig (cpu_env, SIGTRAP);
+    exit(-1);
+}
+
+long do_unix_syscall(void *cpu_env, int num)
+{
+    long ret = 0;
+
+    DPRINTF("unix syscall %d: " , num);
+
+    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
+        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
+
+    DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
+    ret = unix_syscall_table[num].function(cpu_env, num);
+
+    if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
+        ret = get_errno(ret);
+
+    DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
+    return ret;
+}
+
+/* ------------------------------------------------------------
+   syscall_init
+*/
+void syscall_init(void)
+{
+    /* Nothing yet */
+}

Added: trunk/src/host/qemu-neo1973/darwin-user/syscalls.h
===================================================================
--- trunk/src/host/qemu-neo1973/darwin-user/syscalls.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/darwin-user/syscalls.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,384 @@
+/* generated from xnu/bsd/kern/syscalls.master */
+
+ ENTRY("syscall",                  SYS_syscall,                        do_unix_syscall_indirect,          0, CALL_INDIRECT, VOID) /* 0  indirect syscall */
+ ENTRY("exit",                     SYS_exit,                           do_exit,                           1, CALL_DIRECT, INT)   /* 1  */
+ ENTRY("fork",                     SYS_fork,                           fork,                              0, CALL_NOERRNO, VOID)  /* 2  */
+ ENTRY("read",                     SYS_read,                           do_read,                           3, CALL_DIRECT, INT, PTR, SIZE)   /* 3  */
+ ENTRY("write",                    SYS_write,                          write,                             3, CALL_DIRECT, INT, PTR, SIZE)   /* 4  */
+ ENTRY("open",                     SYS_open,                           do_open,                           3, CALL_DIRECT, PTR, INT, INT)   /* 5  */
+ ENTRY("close",                    SYS_close,                          close,                             1, CALL_DIRECT, INT)   /* 6  */
+ ENTRY("wait4",                    SYS_wait4,                          wait4,                             4, CALL_DIRECT, INT, PTR, INT, PTR)   /* 7  */
+ ENTRY("",                         8,                                  no_syscall,                        0, CALL_INDIRECT, VOID) /* 8  old creat */
+ ENTRY("link",                     SYS_link,                           link,                              2, CALL_DIRECT, PTR, PTR)   /* 9  */
+ ENTRY("unlink",                   SYS_unlink,                         unlink,                            1, CALL_DIRECT, PTR)   /* 10  */
+ ENTRY("",                         11,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 11  old execv */
+ ENTRY("chdir",                    SYS_chdir,                          chdir,                             1, CALL_DIRECT, PTR)   /* 12  */
+ ENTRY("fchdir",                   SYS_fchdir,                         fchdir,                            1, CALL_DIRECT, INT)   /* 13  */
+ ENTRY("mknod",                    SYS_mknod,                          mknod,                             3, CALL_DIRECT, PTR, INT, INT)   /* 14  */
+ ENTRY("chmod",                    SYS_chmod,                          chmod,                             2, CALL_DIRECT, PTR, INT)   /* 15  */
+ ENTRY("chown",                    SYS_chown,                          chown,                             3, CALL_DIRECT, PTR, INT, INT)   /* 16  */
+ ENTRY("obreak",                   SYS_obreak,                         no_syscall,                        1, CALL_INDIRECT, VOID)   /* 17  old break */
+ ENTRY("ogetfsstat",               18,                                 unimpl_unix_syscall,               3, CALL_INDIRECT, PTR, INT, INT)   /* 18  */
+ ENTRY("",                         19,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 19  old lseek */
+ ENTRY("getpid",                   SYS_getpid,                         getpid,                            0, CALL_NOERRNO, VOID)   /* 20  */
+ ENTRY("",                         21,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 21  old mount */
+ ENTRY("",                         22,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 22  old umount */
+ ENTRY("setuid",                   SYS_setuid,                         setuid,                            1, CALL_DIRECT, INT)   /* 23  */
+ ENTRY("getuid",                   SYS_getuid,                         getuid,                            0, CALL_NOERRNO, VOID)   /* 24  */
+ ENTRY("geteuid",                  SYS_geteuid,                        geteuid,                           0, CALL_NOERRNO, VOID)   /* 25  */
+ ENTRY("ptrace",                   SYS_ptrace,                         ptrace,                            4, CALL_DIRECT, INT, INT, PTR, INT)   /* 26  */
+ ENTRY("recvmsg",                  SYS_recvmsg,                        recvmsg,                           3, CALL_DIRECT, INT, PTR, INT)   /* 27  */
+ ENTRY("sendmsg",                  SYS_sendmsg,                        sendmsg,                           3, CALL_DIRECT, INT, PTR, INT)   /* 28  */
+ ENTRY("recvfrom",                 SYS_recvfrom,                       recvfrom,                          6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR)   /* 29  */
+ ENTRY("accept",                   SYS_accept,                         accept,                            3, CALL_DIRECT, INT, PTR, PTR)   /* 30  */
+ ENTRY("getpeername",              SYS_getpeername,                    getpeername,                       3, CALL_DIRECT, INT, PTR, PTR)   /* 31  */
+ ENTRY("getsockname",              SYS_getsockname,                    getsockname,                       3, CALL_DIRECT, INT, PTR, PTR)   /* 32  */
+ ENTRY("access",                   SYS_access,                         access,                            2, CALL_DIRECT, PTR, INT)   /* 33  */
+ ENTRY("chflags",                  SYS_chflags,                        chflags,                           2, CALL_DIRECT, PTR, INT)   /* 34  */
+ ENTRY("fchflags",                 SYS_fchflags,                       fchflags,                          2, CALL_DIRECT, INT, INT)   /* 35  */
+ ENTRY("sync",                     SYS_sync,                           do_sync,                           0, CALL_INDIRECT, VOID)   /* 36  */
+ ENTRY("kill",                     SYS_kill,                           kill,                              2, CALL_DIRECT, INT, INT)   /* 37  */
+ ENTRY("",                         38,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 38  old stat */
+ ENTRY("getppid",                  SYS_getppid,                        getppid,                           0, CALL_DIRECT, VOID)   /* 39  */
+ ENTRY("",                         40,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 40  old lstat */
+ ENTRY("dup",                      SYS_dup,                            dup,                               1, CALL_DIRECT, INT)   /* 41  */
+ ENTRY("pipe",                     SYS_pipe,                           pipe,               0, CALL_INDIRECT, PTR)   /* 42  */
+ ENTRY("getegid",                  SYS_getegid,                        getegid,                           0, CALL_NOERRNO, VOID)  /* 43  */
+ ENTRY("profil",                   SYS_profil,                         profil,                            4, CALL_DIRECT, PTR, SIZE, INT, INT)   /* 44  */
+ ENTRY("ktrace",                   SYS_ktrace,                         no_syscall,                        4, CALL_INDIRECT, VOID) /* 45  */
+ ENTRY("sigaction",                SYS_sigaction,                      do_sigaction,                      3, CALL_DIRECT, INT, PTR, PTR)   /* 46  */
+ ENTRY("getgid",                   SYS_getgid,                         getgid,                            0, CALL_NOERRNO, VOID)  /* 47  */
+ ENTRY("sigprocmask",              SYS_sigprocmask,                    do_sigprocmask,                    3, CALL_DIRECT, INT, PTR, PTR)   /* 48  */
+ ENTRY("getlogin",                 SYS_getlogin,                       do_getlogin,                       2, CALL_DIRECT, PTR, UINT)   /* 49 XXX */
+ ENTRY("setlogin",                 SYS_setlogin,                       setlogin,                          1, CALL_DIRECT, PTR)   /* 50  */
+ ENTRY("acct",                     SYS_acct,                           acct,                              1, CALL_DIRECT, PTR)   /* 51  */
+ ENTRY("sigpending",               SYS_sigpending,                     sigpending,                        1, CALL_DIRECT, PTR)   /* 52  */
+ ENTRY("sigaltstack",              SYS_sigaltstack,                    do_sigaltstack,                    2, CALL_DIRECT, PTR, PTR)   /* 53  */
+ ENTRY("ioctl",                    SYS_ioctl,                          do_ioctl,                          3, CALL_DIRECT, INT, INT, INT)   /* 54  */
+ ENTRY("reboot",                   SYS_reboot,                         unimpl_unix_syscall,               2, CALL_INDIRECT, INT, PTR)   /* 55  */
+ ENTRY("revoke",                   SYS_revoke,                         revoke,                            1, CALL_DIRECT, PTR)   /* 56  */
+ ENTRY("symlink",                  SYS_symlink,                        symlink,                           2, CALL_DIRECT, PTR, PTR)   /* 57  */
+ ENTRY("readlink",                 SYS_readlink,                       readlink,                          3, CALL_DIRECT, PTR, PTR, INT)   /* 58  */
+ ENTRY("execve",                   SYS_execve,                         do_execve,                         3, CALL_DIRECT, PTR, PTR, PTR)   /* 59  */
+ ENTRY("umask",                    SYS_umask,                          umask,                             1, CALL_DIRECT, INT)   /* 60  */
+ ENTRY("chroot",                   SYS_chroot,                         chroot,                            1, CALL_DIRECT, PTR)   /* 61  */
+ ENTRY("",                         62,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 62  old fstat */
+ ENTRY("",                         63,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 63  used internally , reserved */
+ ENTRY("",                         64,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 64  old getpagesize */
+ ENTRY("msync",                    SYS_msync,                          target_msync,                      3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT)   /* 65  */
+ ENTRY("vfork",                    SYS_vfork,                          vfork,                             0, CALL_DIRECT, VOID)   /* 66  */
+ ENTRY("",                         67,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 67  old vread */
+ ENTRY("",                         68,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 68  old vwrite */
+ ENTRY("sbrk",                     SYS_sbrk,                           sbrk,                              1, CALL_DIRECT, INT)   /* 69  */
+ ENTRY("sstk",                     SYS_sstk,                           no_syscall,                        1, CALL_INDIRECT, VOID) /* 70  */
+ ENTRY("",                         71,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 71  old mmap */
+ ENTRY("ovadvise",                 SYS_ovadvise,                       no_syscall,                        0, CALL_INDIRECT, VOID) /* 72  old vadvise */
+ ENTRY("munmap",                   SYS_munmap,                         target_munmap,                     2, CALL_DIRECT, UINT /* PTR */, SIZE)   /* 73  */
+ ENTRY("mprotect",                 SYS_mprotect,                       mprotect,                          3, CALL_DIRECT, PTR, SIZE, INT)   /* 74  */
+ ENTRY("madvise",                  SYS_madvise,                        madvise,                           3, CALL_DIRECT, PTR, SIZE, INT)   /* 75  */
+ ENTRY("",                         76,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 76  old vhangup */
+ ENTRY("",                         77,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 77  old vlimit */
+ ENTRY("mincore",                  SYS_mincore,                        mincore,                           3, CALL_DIRECT, PTR, SIZE, PTR)   /* 78  */
+ ENTRY("getgroups",                SYS_getgroups,                      do_getgroups,                      2, CALL_DIRECT, UINT, PTR)   /* 79  */
+ ENTRY("setgroups",                SYS_setgroups,                      setgroups,                         2, CALL_DIRECT, UINT, PTR)   /* 80  */
+ ENTRY("getpgrp",                  SYS_getpgrp,                        getpgrp,                           0, CALL_DIRECT, VOID)   /* 81  */
+ ENTRY("setpgid",                  SYS_setpgid,                        setpgid,                           2, CALL_DIRECT, INT, INT)   /* 82  */
+ ENTRY("setitimer",                SYS_setitimer,                      setitimer,                         3, CALL_DIRECT, INT, PTR, PTR)   /* 83  */
+ ENTRY("",                         84,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 84  old wait */
+ ENTRY("swapon",                   SYS_swapon,                         unimpl_unix_syscall,               0, CALL_INDIRECT, VOID)   /* 85  */
+ ENTRY("getitimer",                SYS_getitimer,                      getitimer,                         2, CALL_DIRECT, INT, PTR)   /* 86  */
+ ENTRY("",                         87,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 87  old gethostname */
+ ENTRY("",                         88,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 88  old sethostname */
+ ENTRY("getdtablesize",            SYS_getdtablesize,                  getdtablesize,                     0, CALL_DIRECT, VOID)   /* 89  */
+ ENTRY("dup2",                     SYS_dup2,                           dup2,                              2, CALL_DIRECT, INT, INT)   /* 90  */
+ ENTRY("",                         91,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 91  old getdopt */
+ ENTRY("fcntl",                    SYS_fcntl,                          do_fcntl,                          3, CALL_DIRECT, INT, INT, INT)   /* 92  */
+ ENTRY("select",                   SYS_select,                         select,                            5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR)   /* 93  */
+ ENTRY("",                         94,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 94  old setdopt */
+ ENTRY("fsync",                    SYS_fsync,                          fsync,                             1, CALL_DIRECT, INT)   /* 95  */
+ ENTRY("setpriority",              SYS_setpriority,                    setpriority,                       3, CALL_DIRECT, INT, INT, INT)   /* 96  */
+ ENTRY("socket",                   SYS_socket,                         socket,                            3, CALL_DIRECT, INT, INT, INT)   /* 97  */
+ ENTRY("connect",                  SYS_connect,                        connect,                           3, CALL_DIRECT, INT, PTR, INT)   /* 98  */
+ ENTRY("",                         99,                                 no_syscall,                        0, CALL_INDIRECT, VOID) /* 99  old accept */
+ ENTRY("getpriority",              SYS_getpriority,                    getpriority,                       2, CALL_DIRECT, INT, INT)   /* 100  */
+ ENTRY("",                         101,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 101  old send */
+ ENTRY("",                         102,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 102  old recv */
+ ENTRY("",                         103,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 103  old sigreturn */
+ ENTRY("bind",                     SYS_bind,                           bind,                              3, CALL_DIRECT, INT, PTR, INT)   /* 104  */
+ ENTRY("setsockopt",               SYS_setsockopt,                     setsockopt,                        5, CALL_DIRECT, INT, INT, INT, PTR, INT)   /* 105  */
+ ENTRY("listen",                   SYS_listen,                         listen,                            2, CALL_DIRECT, INT, INT)   /* 106  */
+ ENTRY("",                         107,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 107  old vtimes */
+ ENTRY("",                         108,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 108  old sigvec */
+ ENTRY("",                         109,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 109  old sigblock */
+ ENTRY("",                         110,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 110  old sigsetmask */
+ ENTRY("sigsuspend",               SYS_sigsuspend,                     unimpl_unix_syscall,               1, CALL_INDIRECT, INT)   /* 111  */
+ ENTRY("",                         112,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 112  old sigstack */
+ ENTRY("",                         113,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 113  old recvmsg */
+ ENTRY("",                         114,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 114  old sendmsg */
+ ENTRY("",                         115,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 115  old vtrace */
+ ENTRY("gettimeofday",             SYS_gettimeofday,                   do_gettimeofday,                   2, CALL_DIRECT, PTR, PTR) /* 116  */
+ ENTRY("getrusage",                SYS_getrusage,                      getrusage,                         2, CALL_DIRECT, INT, PTR)   /* 117  */
+ ENTRY("getsockopt",               SYS_getsockopt,                     getsockopt,                        5, CALL_DIRECT, INT, INT, INT, PTR, PTR)   /* 118  */
+ ENTRY("",                         119,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 119  old resuba */
+ ENTRY("readv",                    SYS_readv,                          do_readv,                          3, CALL_DIRECT, INT, PTR, UINT)   /* 120  */
+ ENTRY("writev",                   SYS_writev,                         do_writev,                         3, CALL_DIRECT, INT, PTR, UINT)   /* 121  */
+ ENTRY("settimeofday",             SYS_settimeofday,                   settimeofday,                      2, CALL_DIRECT, PTR, PTR)   /* 122  */
+ ENTRY("fchown",                   SYS_fchown,                         fchown,                            3, CALL_DIRECT, INT, INT, INT)   /* 123  */
+ ENTRY("fchmod",                   SYS_fchmod,                         fchmod,                            2, CALL_DIRECT, INT, INT)   /* 124  */
+ ENTRY("",                         125,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 125  old recvfrom */
+ ENTRY("",                         126,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 126  old setreuid */
+ ENTRY("",                         127,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 127  old setregid */
+ ENTRY("rename",                   SYS_rename,                         rename,                            2, CALL_DIRECT, PTR, PTR)   /* 128  */
+ ENTRY("",                         129,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 129  old truncate */
+ ENTRY("",                         130,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 130  old ftruncate */
+ ENTRY("flock",                    SYS_flock,                          flock,                             2, CALL_DIRECT, INT, INT)   /* 131  */
+ ENTRY("mkfifo",                   SYS_mkfifo,                         mkfifo,                            2, CALL_DIRECT, PTR, INT)   /* 132  */
+ ENTRY("sendto",                   SYS_sendto,                         sendto,                            6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT)   /* 133  */
+ ENTRY("shutdown",                 SYS_shutdown,                       shutdown,                          2, CALL_DIRECT, INT, INT)   /* 134  */
+ ENTRY("socketpair",               SYS_socketpair,                     socketpair,                        4, CALL_DIRECT, INT, INT, INT, PTR)   /* 135  */
+ ENTRY("mkdir",                    SYS_mkdir,                          mkdir,                             2, CALL_DIRECT, PTR, INT)   /* 136  */
+ ENTRY("rmdir",                    SYS_rmdir,                          rmdir,                             1, CALL_DIRECT, PTR)   /* 137  */
+ ENTRY("utimes",                   SYS_utimes,                         do_utimes,                         2, CALL_DIRECT, PTR, PTR)   /* 138  */
+ ENTRY("futimes",                  SYS_futimes,                        do_futimes,                        2, CALL_DIRECT, INT, PTR)   /* 139  */
+ ENTRY("adjtime",                  SYS_adjtime,                        adjtime,                           2, CALL_DIRECT, PTR, PTR)   /* 140  */
+ ENTRY("",                         141,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 141  old getpeername */
+ ENTRY("",                         142,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 142  old gethostid */
+ ENTRY("",                         143,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 143  old sethostid */
+ ENTRY("",                         144,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 144  old getrlimit */
+ ENTRY("",                         145,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 145  old setrlimit */
+ ENTRY("",                         146,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 146  old killpg */
+ ENTRY("setsid",                   SYS_setsid,                         setsid,                            0, CALL_DIRECT, VOID)   /* 147  */
+ ENTRY("",                         148,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 148  old setquota */
+ ENTRY("",                         149,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 149  old qquota */
+ ENTRY("",                         150,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 150  old getsockname */
+ ENTRY("getpgid",                  SYS_getpgid,                        getpgid,                           1, CALL_DIRECT, INT)   /* 151  */
+ ENTRY("setprivexec",              SYS_setprivexec,                    no_syscall,                        1, CALL_INDIRECT, VOID) /* 152  */
+ ENTRY("pread",                    SYS_pread,                          do_pread,                          4, CALL_DIRECT, INT, PTR, SIZE, OFFSET)   /* 153  */
+ ENTRY("pwrite",                   SYS_pwrite,                         pwrite,                            4, CALL_DIRECT, INT, PTR, SIZE, OFFSET)   /* 154  */
+#ifdef SYS_nfssvc
+ ENTRY("nfssvc",                   SYS_nfssvc,                         nfssvc,                            2, CALL_DIRECT, INT, PTR)   /* 155  */
+#else
+ ENTRY("nfssvc",                   155,                                no_syscall,                        2, CALL_INDIRECT, VOID)   /* 155  */
+#endif
+ ENTRY("",                         155,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 155  */
+ ENTRY("",                         156,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 156  old getdirentries */
+ ENTRY("statfs",                   SYS_statfs,                         do_statfs,                         2, CALL_DIRECT, PTR, PTR)   /* 157  */
+ ENTRY("fstatfs",                  SYS_fstatfs,                        do_fstatfs,                        2, CALL_DIRECT, INT, PTR)   /* 158  */
+ ENTRY("unmount",                  SYS_unmount,                        unmount,                           2, CALL_DIRECT, PTR, INT)   /* 159  */
+ ENTRY("",                         160,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 160  old async_daemon */
+ ENTRY("",                         161,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 161  */
+ ENTRY("",                         162,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 162  old getdomainname */
+ ENTRY("",                         163,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 163  old setdomainname */
+ ENTRY("",                         164,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 164  */
+ ENTRY("quotactl",                 SYS_quotactl,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 165  */
+ ENTRY("",                         166,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 166  old exportfs */
+ ENTRY("mount",                    SYS_mount,                          mount,                             4, CALL_DIRECT, PTR, PTR, INT, PTR)   /* 167  */
+ ENTRY("",                         168,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 168  old ustat */
+ ENTRY("",                         169,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 169  */
+ ENTRY("table",                    SYS_table,                          no_syscall,                        0, CALL_INDIRECT, VOID) /* 170  old table */
+ ENTRY("",                         171,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 171  old wait3 */
+ ENTRY("",                         172,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 172  old rpause */
+ ENTRY("waitid",                   SYS_waitid,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID) /* 173  */
+ ENTRY("",                         174,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 174  old getdents */
+ ENTRY("",                         175,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 175  old gc_control */
+ ENTRY("add_profil",               SYS_add_profil,                     add_profil,                        4, CALL_DIRECT, PTR, SIZE, UINT, UINT)   /* 176  */
+ ENTRY("",                         177,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 177  */
+ ENTRY("",                         178,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 178  */
+ ENTRY("",                         179,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 179  */
+ ENTRY("kdebug_trace",             SYS_kdebug_trace,                   no_syscall,                        6, CALL_INDIRECT, VOID) /* 180  */
+ ENTRY("setgid",                   SYS_setgid,                         setgid,                            1, CALL_DIRECT, INT)   /* 181  */
+ ENTRY("setegid",                  SYS_setegid,                        setegid,                           1, CALL_DIRECT, INT)   /* 182  */
+ ENTRY("seteuid",                  SYS_seteuid,                        seteuid,                           1, CALL_DIRECT, INT)   /* 183  */
+ ENTRY("sigreturn",                SYS_sigreturn,                      do_sigreturn,                      2, CALL_INDIRECT, PTR, INT)   /* 184  */
+ ENTRY("chud",                     SYS_chud,                           unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 185  */
+ ENTRY("",                         186,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 186  */
+ ENTRY("",                         187,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 187  */
+ ENTRY("stat",                     SYS_stat,                           do_stat,                           2, CALL_DIRECT, PTR, PTR)   /* 188  */
+ ENTRY("fstat",                    SYS_fstat,                          do_fstat,                          2, CALL_DIRECT, INT, PTR)   /* 189  */
+ ENTRY("lstat",                    SYS_lstat,                          do_lstat,                          2, CALL_DIRECT, PTR, PTR)   /* 190  */
+ ENTRY("pathconf",                 SYS_pathconf,                       pathconf,                          2, CALL_DIRECT, PTR, INT)   /* 191  */
+ ENTRY("fpathconf",                SYS_fpathconf,                      fpathconf,                         2, CALL_DIRECT, INT, INT)   /* 192  */
+ ENTRY("getfsstat",                SYS_getfsstat,                      do_getfsstat,                      3, CALL_DIRECT, PTR, INT, INT)   /* 193  */
+ ENTRY("",                         193,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 193  */
+ ENTRY("getrlimit",                SYS_getrlimit,                      getrlimit,                         2, CALL_DIRECT, UINT, PTR)   /* 194  */
+ ENTRY("setrlimit",                SYS_setrlimit,                      setrlimit,                         2, CALL_DIRECT, UINT, PTR)   /* 195  */
+ ENTRY("getdirentries",            SYS_getdirentries,                  do_getdirentries,                  4, CALL_DIRECT, INT, PTR, UINT, PTR)   /* 196  */
+ ENTRY("mmap",                     SYS_mmap,                           target_mmap,                       6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET)   /* 197  */
+ ENTRY("",                         198,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 198  __syscall */
+ ENTRY("lseek",                    SYS_lseek,                          do_lseek,                          3, CALL_INDIRECT, INT, OFFSET, INT)   /* 199  */
+ ENTRY("truncate",                 SYS_truncate,                       truncate,                          2, CALL_DIRECT, PTR, OFFSET)   /* 200  */
+ ENTRY("ftruncate",                SYS_ftruncate,                      ftruncate,                         2, CALL_DIRECT, INT, OFFSET)   /* 201  */
+ ENTRY("__sysctl",                 SYS___sysctl,                       do___sysctl,                       6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE)   /* 202  */
+ ENTRY("mlock",                    SYS_mlock,                          mlock,                             2, CALL_DIRECT, PTR, SIZE)   /* 203  */
+ ENTRY("munlock",                  SYS_munlock,                        munlock,                           2, CALL_DIRECT, PTR, SIZE)   /* 204  */
+ ENTRY("undelete",                 SYS_undelete,                       undelete,                          1, CALL_DIRECT, PTR)   /* 205  */
+ ENTRY("ATsocket",                 SYS_ATsocket,                       no_syscall,                        1, CALL_INDIRECT, VOID) /* 206  */
+ ENTRY("ATgetmsg",                 SYS_ATgetmsg,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 207  */
+ ENTRY("ATputmsg",                 SYS_ATputmsg,                       no_syscall,                        4, CALL_INDIRECT, VOID) /* 208  */
+ ENTRY("ATPsndreq",                SYS_ATPsndreq,                      no_syscall,                        4, CALL_INDIRECT, VOID) /* 209  */
+ ENTRY("ATPsndrsp",                SYS_ATPsndrsp,                      no_syscall,                        4, CALL_INDIRECT, VOID) /* 210  */
+ ENTRY("ATPgetreq",                SYS_ATPgetreq,                      no_syscall,                        3, CALL_INDIRECT, VOID) /* 211  */
+ ENTRY("ATPgetrsp",                SYS_ATPgetrsp,                      no_syscall,                        2, CALL_INDIRECT, VOID) /* 212  */
+ ENTRY("",                         213,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 213  Reserved for AppleTalk */
+ ENTRY("kqueue_from_portset_np",   SYS_kqueue_from_portset_np,         no_syscall,                        1, CALL_INDIRECT, VOID) /* 214  */
+ ENTRY("kqueue_portset_np",        SYS_kqueue_portset_np,              no_syscall,                        1, CALL_INDIRECT, VOID) /* 215  */
+ ENTRY("mkcomplex",                SYS_mkcomplex,                      no_syscall,                        3, CALL_INDIRECT, VOID)   /* 216  soon to be obsolete */
+ ENTRY("statv",                    SYS_statv,                          no_syscall,                        2, CALL_INDIRECT, VOID)   /* 217  soon to be obsolete */
+ ENTRY("lstatv",                   SYS_lstatv,                         no_syscall,                        2, CALL_INDIRECT, VOID)   /* 218  soon to be obsolete */
+ ENTRY("fstatv",                   SYS_fstatv,                         no_syscall,                        2, CALL_INDIRECT, VOID)   /* 219  soon to be obsolete */
+ ENTRY("getattrlist",              SYS_getattrlist,                    do_getattrlist,                    5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT)   /* 220  */
+ ENTRY("setattrlist",              SYS_setattrlist,                    unimpl_unix_syscall,               5, CALL_INDIRECT, VOID) /* 221  */
+ ENTRY("getdirentriesattr",        SYS_getdirentriesattr,              do_getdirentriesattr,              8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT)   /* 222  */
+ ENTRY("exchangedata",             SYS_exchangedata,                   exchangedata,                      3, CALL_DIRECT, PTR, PTR, UINT)   /* 223  */
+ ENTRY("checkuseraccess",          SYS_checkuseraccess,                checkuseraccess,                   6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT)   /* 224  */
+ ENTRY("",                         224,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 224  HFS checkuseraccess check access to a file */
+ ENTRY("searchfs",                 SYS_searchfs,                       searchfs,                          6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR)   /* 225  */
+ ENTRY("delete",                   SYS_delete,                         no_syscall,                        1, CALL_INDIRECT, VOID)   /* 226  private delete ( Carbon semantics ) */
+ ENTRY("copyfile",                 SYS_copyfile,                       no_syscall,                        4, CALL_INDIRECT, VOID)   /* 227  */
+ ENTRY("",                         228,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 228  */
+ ENTRY("",                         229,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 229  */
+ ENTRY("poll",                     SYS_poll,                           no_syscall,                        3, CALL_INDIRECT, VOID) /* 230  */
+ ENTRY("watchevent",               SYS_watchevent,                     no_syscall,                        2, CALL_INDIRECT, VOID)   /* 231  */
+ ENTRY("waitevent",                SYS_waitevent,                      no_syscall,                        2, CALL_INDIRECT, VOID)   /* 232  */
+ ENTRY("modwatch",                 SYS_modwatch,                       no_syscall,                        2, CALL_INDIRECT, VOID)   /* 233  */
+ ENTRY("getxattr",                 SYS_getxattr,                       no_syscall,                        6, CALL_INDIRECT, VOID)   /* 234  */
+ ENTRY("fgetxattr",                SYS_fgetxattr,                      no_syscall,                        6, CALL_INDIRECT, VOID)   /* 235  */
+ ENTRY("setxattr",                 SYS_setxattr,                       no_syscall,                        6, CALL_INDIRECT, VOID)   /* 236  */
+ ENTRY("fsetxattr",                SYS_fsetxattr,                      no_syscall,                        6, CALL_INDIRECT, VOID)   /* 237  */
+ ENTRY("removexattr",              SYS_removexattr,                    no_syscall,                        3, CALL_INDIRECT, VOID)   /* 238  */
+ ENTRY("fremovexattr",             SYS_fremovexattr,                   no_syscall,                        3, CALL_INDIRECT, VOID)   /* 239  */
+ ENTRY("listxattr",                SYS_listxattr,                      listxattr,                         4, CALL_INDIRECT, VOID)   /* 240  */
+ ENTRY("flistxattr",               SYS_flistxattr,                     no_syscall,                        4, CALL_INDIRECT, VOID)   /* 241  */
+ ENTRY("fsctl",                    SYS_fsctl,                          fsctl,                             4, CALL_DIRECT, PTR, UINT, PTR, UINT)   /* 242  */
+ ENTRY("initgroups",               SYS_initgroups,                     unimpl_unix_syscall,               3, CALL_INDIRECT, UINT, PTR, INT)   /* 243  */
+ ENTRY("",                         244,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 244  */
+ ENTRY("",                         245,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 245  */
+ ENTRY("",                         246,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 246  */
+#ifdef SYS_nfsclnt
+ ENTRY("nfsclnt",                  SYS_nfsclnt,                        nfsclnt,                           2, CALL_DIRECT, INT, PTR)   /* 247  */
+#else
+ ENTRY("nfsclnt",                  247,                                no_syscall,                        2, CALL_INDIRECT, VOID)   /* 247  */
+#endif
+ ENTRY("",                         247,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 247  */
+ ENTRY("",                         248,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 248  */
+ ENTRY("",                         249,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 249  */
+ ENTRY("minherit",                 SYS_minherit,                       minherit,                          3, CALL_DIRECT, PTR, INT, INT)   /* 250  */
+ ENTRY("semsys",                   SYS_semsys,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 251  */
+ ENTRY("msgsys",                   SYS_msgsys,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 252  */
+ ENTRY("shmsys",                   SYS_shmsys,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 253  */
+ ENTRY("semctl",                   SYS_semctl,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 254  */
+ ENTRY("semget",                   SYS_semget,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 255  */
+ ENTRY("semop",                    SYS_semop,                          unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 256  */
+ ENTRY("",                         257,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 257  */
+ ENTRY("msgctl",                   SYS_msgctl,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 258  */
+ ENTRY("msgget",                   SYS_msgget,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 259  */
+ ENTRY("msgsnd",                   SYS_msgsnd,                         unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 260  */
+ ENTRY("msgrcv",                   SYS_msgrcv,                         unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 261  */
+ ENTRY("shmat",                    SYS_shmat,                          unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 262  */
+ ENTRY("shmctl",                   SYS_shmctl,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 263  */
+ ENTRY("shmdt",                    SYS_shmdt,                          unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 264  */
+ ENTRY("shmget",                   SYS_shmget,                         unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 265  */
+ ENTRY("shm_open",                 SYS_shm_open,                       shm_open,                          3, CALL_DIRECT, PTR, INT, INT)   /* 266  */
+ ENTRY("shm_unlink",               SYS_shm_unlink,                     shm_unlink,                        1, CALL_DIRECT, PTR)   /* 267  */
+ ENTRY("sem_open",                 SYS_sem_open,                       unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 268  */
+ ENTRY("sem_close",                SYS_sem_close,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 269  */
+ ENTRY("sem_unlink",               SYS_sem_unlink,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 270  */
+ ENTRY("sem_wait",                 SYS_sem_wait,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 271  */
+ ENTRY("sem_trywait",              SYS_sem_trywait,                    unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 272  */
+ ENTRY("sem_post",                 SYS_sem_post,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 273  */
+ ENTRY("sem_getvalue",             SYS_sem_getvalue,                   unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 274  */
+ ENTRY("sem_init",                 SYS_sem_init,                       unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 275  */
+ ENTRY("sem_destroy",              SYS_sem_destroy,                    unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 276  */
+ ENTRY("open_extended",            SYS_open_extended,                  unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 277  */
+ ENTRY("umask_extended",           SYS_umask_extended,                 unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 278  */
+ ENTRY("stat_extended",            SYS_stat_extended,                  unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 279  */
+ ENTRY("lstat_extended",           SYS_lstat_extended,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 280  */
+ ENTRY("fstat_extended",           SYS_fstat_extended,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 281  */
+ ENTRY("chmod_extended",           SYS_chmod_extended,                 unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 282  */
+ ENTRY("fchmod_extended",          SYS_fchmod_extended,                unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 283  */
+ ENTRY("access_extended",          SYS_access_extended,                unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 284  */
+ ENTRY("settid",                   SYS_settid,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 285  */
+ ENTRY("gettid",                   SYS_gettid,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 286  */
+ ENTRY("setsgroups",               SYS_setsgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 287  */
+ ENTRY("getsgroups",               SYS_getsgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 288  */
+ ENTRY("setwgroups",               SYS_setwgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 289  */
+ ENTRY("getwgroups",               SYS_getwgroups,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 290  */
+ ENTRY("mkfifo_extended",          SYS_mkfifo_extended,                unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 291  */
+ ENTRY("mkdir_extended",           SYS_mkdir_extended,                 unimpl_unix_syscall,               5, CALL_INDIRECT, VOID)   /* 292  */
+ ENTRY("identitysvc",              SYS_identitysvc,                    unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 293  */
+ ENTRY("",                         294,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 294  */
+ ENTRY("",                         295,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 295  */
+ ENTRY("load_shared_file",         SYS_load_shared_file,               unimpl_unix_syscall,               7, CALL_INDIRECT, VOID)   /* 296  */
+ ENTRY("reset_shared_file",        SYS_reset_shared_file,              unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 297  */
+ ENTRY("new_system_shared_regions",  SYS_new_system_shared_regions,    unimpl_unix_syscall,               0, CALL_INDIRECT, VOID)   /* 298  */
+ ENTRY("shared_region_map_file_np",  SYS_shared_region_map_file_np,    unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 299  */
+ ENTRY("shared_region_make_private_np",  SYS_shared_region_make_private_np,  unimpl_unix_syscall,         2, CALL_INDIRECT, VOID)   /* 300  */
+ ENTRY("",                         301,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 301  */
+ ENTRY("",                         302,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 302  */
+ ENTRY("",                         303,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 303  */
+ ENTRY("",                         304,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 304  */
+ ENTRY("",                         305,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 305  */
+ ENTRY("",                         306,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 306  */
+ ENTRY("",                         307,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 307  */
+ ENTRY("",                         308,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 308  */
+ ENTRY("",                         309,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 309  */
+ ENTRY("getsid",                   SYS_getsid,                         getsid,                            1, CALL_DIRECT, INT)   /* 310  */
+ ENTRY("settid_with_pid",          SYS_settid_with_pid,                unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 311  */
+ ENTRY("",                         312,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 312  */
+ ENTRY("aio_fsync",                SYS_aio_fsync,                      unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 313  */
+ ENTRY("aio_return",               SYS_aio_return,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 314  */
+ ENTRY("aio_suspend",              SYS_aio_suspend,                    unimpl_unix_syscall,               3, CALL_INDIRECT, VOID)   /* 315  */
+ ENTRY("aio_cancel",               SYS_aio_cancel,                     unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 316  */
+ ENTRY("aio_error",                SYS_aio_error,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 317  */
+ ENTRY("aio_read",                 SYS_aio_read,                       unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 318  */
+ ENTRY("aio_write",                SYS_aio_write,                      unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 319  */
+ ENTRY("lio_listio",               SYS_lio_listio,                     unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 320  */
+ ENTRY("",                         321,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 321  */
+ ENTRY("",                         322,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 322  */
+ ENTRY("",                         323,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 323  */
+ ENTRY("mlockall",                 SYS_mlockall,                       mlockall,                          1, CALL_DIRECT, INT)   /* 324  */
+ ENTRY("munlockall",               SYS_munlockall,                     unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 325  */
+ ENTRY("",                         326,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 326  */
+ ENTRY("issetugid",                SYS_issetugid,                      issetugid,                         0, CALL_DIRECT, VOID)   /* 327  */
+ ENTRY("__pthread_kill",           SYS___pthread_kill,                 unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 328  */
+ ENTRY("pthread_sigmask",          SYS_pthread_sigmask,                pthread_sigmask,                   3, CALL_DIRECT, INT, PTR, PTR)   /* 329  */
+ ENTRY("sigwait",                  SYS_sigwait,                        sigwait,                           2, CALL_DIRECT, PTR, PTR)   /* 330  */
+ ENTRY("__disable_threadsignal",   SYS___disable_threadsignal,         unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 331  */
+ ENTRY("__pthread_markcancel",     SYS___pthread_markcancel,           unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 332  */
+ ENTRY("__pthread_canceled",       SYS___pthread_canceled,             unimpl_unix_syscall,               1, CALL_INDIRECT, VOID)   /* 333  */
+ ENTRY("__semwait_signal",         SYS___semwait_signal,               unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 334  */
+ ENTRY("utrace",                   SYS_utrace,                         unimpl_unix_syscall,               2, CALL_INDIRECT, VOID)   /* 335  */
+ ENTRY("proc_info",                SYS_proc_info,                      unimpl_unix_syscall,               6, CALL_INDIRECT, VOID)   /* 336  */
+ ENTRY("",                         337,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 337  */
+ ENTRY("",                         338,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 338  */
+ ENTRY("",                         339,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 339  */
+ ENTRY("",                         340,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 340  */
+ ENTRY("",                         341,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 341  */
+ ENTRY("",                         342,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 342  */
+ ENTRY("",                         343,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 343  */
+ ENTRY("",                         344,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 344  */
+ ENTRY("",                         345,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 345  */
+ ENTRY("",                         346,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 346  */
+ ENTRY("",                         347,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 347  */
+ ENTRY("",                         348,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 348  */
+ ENTRY("",                         349,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 349  */
+ ENTRY("audit",                    SYS_audit,                          audit,                             2, CALL_DIRECT, PTR, INT)   /* 350  */
+ ENTRY("auditon",                  SYS_auditon,                        auditon,                           3, CALL_DIRECT, INT, PTR, INT)   /* 351  */
+ ENTRY("",                         352,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 352  */
+ ENTRY("getauid",                  SYS_getauid,                        getauid,                           1, CALL_DIRECT, PTR)   /* 353  */
+ ENTRY("setauid",                  SYS_setauid,                        setauid,                           1, CALL_DIRECT, PTR)   /* 354  */
+ ENTRY("getaudit",                 SYS_getaudit,                       getaudit,                          1, CALL_DIRECT, PTR)   /* 355  */
+ ENTRY("setaudit",                 SYS_setaudit,                       setaudit,                          1, CALL_DIRECT, PTR)   /* 356  */
+ ENTRY("getaudit_addr",            SYS_getaudit_addr,                  getaudit_addr,                     2, CALL_DIRECT, PTR, INT)   /* 357  */
+ ENTRY("setaudit_addr",            SYS_setaudit_addr,                  setaudit_addr,                     2, CALL_DIRECT, PTR, INT)   /* 358  */
+ ENTRY("auditctl",                 SYS_auditctl,                       auditctl,                          1, CALL_DIRECT, PTR)   /* 359  */
+ ENTRY("",                         360,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 360  */
+ ENTRY("",                         361,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 361  */
+ ENTRY("kqueue",                   SYS_kqueue,                         kqueue,                            0, CALL_DIRECT, VOID)   /* 362  */
+ ENTRY("kevent",                   SYS_kevent,                         kevent,                            6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR)   /* 363  */
+ ENTRY("lchown",                   SYS_lchown,                         lchown,                            3, CALL_DIRECT, PTR, INT , INT)   /* 364  */
+ ENTRY("stack_snapshot",           SYS_stack_snapshot,                 unimpl_unix_syscall,               4, CALL_INDIRECT, VOID)   /* 365  */
+ ENTRY("",                         366,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 366  */
+ ENTRY("",                         367,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 367  */
+ ENTRY("",                         368,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 368  */
+ ENTRY("",                         369,                                no_syscall,                        0, CALL_INDIRECT, VOID) /* 369  */

Modified: trunk/src/host/qemu-neo1973/dis-asm.h
===================================================================
--- trunk/src/host/qemu-neo1973/dis-asm.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dis-asm.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -181,6 +181,7 @@
 #define bfd_mach_sh4al_dsp  0x4d
 #define bfd_mach_sh5        0x50
   bfd_arch_alpha,      /* Dec Alpha */
+#define bfd_mach_alpha 1
   bfd_arch_arm,        /* Advanced Risc Machines ARM */
 #define bfd_mach_arm_2         1
 #define bfd_mach_arm_2a                2
@@ -377,6 +378,7 @@
 extern int print_insn_v850		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_tic30		PARAMS ((bfd_vma, disassemble_info*));
 extern int print_insn_ppc		PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha             PARAMS ((bfd_vma, disassemble_info*));
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */

Modified: trunk/src/host/qemu-neo1973/disas.c
===================================================================
--- trunk/src/host/qemu-neo1973/disas.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/disas.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -197,6 +197,9 @@
 #elif defined(TARGET_SH4)
     disasm_info.mach = bfd_mach_sh4;
     print_insn = print_insn_sh;
+#elif defined(TARGET_ALPHA)
+    disasm_info.mach = bfd_mach_alpha;
+    print_insn = print_insn_alpha;
 #else
     fprintf(out, "0x" TARGET_FMT_lx
 	    ": Asm output not supported on this arch\n", code);
@@ -255,6 +258,9 @@
     print_insn = print_insn_alpha;
 #elif defined(__sparc__)
     print_insn = print_insn_sparc;
+#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
+    disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
 #elif defined(__arm__) 
     print_insn = print_insn_arm;
 #elif defined(__MIPSEB__)
@@ -378,6 +384,9 @@
     print_insn = print_insn_arm;
 #elif defined(TARGET_SPARC)
     print_insn = print_insn_sparc;
+#ifdef TARGET_SPARC64
+    disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
 #elif defined(TARGET_PPC)
 #ifdef TARGET_PPC64
     disasm_info.mach = bfd_mach_ppc64;

Modified: trunk/src/host/qemu-neo1973/dyngen-exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen-exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen-exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -62,6 +62,9 @@
 #endif
 #endif
 
+/* XXX: This may be wrong for 64-bit ILP32 hosts.  */
+typedef void * host_reg_t;
+
 #define INT8_MIN		(-128)
 #define INT16_MIN		(-32767-1)
 #define INT32_MIN		(-2147483647-1)
@@ -75,27 +78,30 @@
 #define UINT32_MAX		(4294967295U)
 #define UINT64_MAX		((uint64_t)(18446744073709551615))
 
+#ifdef _BSD
+typedef struct __sFILE FILE;
+#else
 typedef struct FILE FILE;
+#endif
 extern int fprintf(FILE *, const char *, ...);
+extern int fputs(const char *, FILE *);
 extern int printf(const char *, ...);
 #undef NULL
 #define NULL 0
 
-#ifdef __i386__
+#if defined(__i386__)
 #define AREG0 "ebp"
 #define AREG1 "ebx"
 #define AREG2 "esi"
 #define AREG3 "edi"
-#endif
-#ifdef __x86_64__
-#define AREG0 "rbp"
-#define AREG1 "rbx"
+#elif defined(__x86_64__)
+#define AREG0 "r14"
+#define AREG1 "r15"
 #define AREG2 "r12"
 #define AREG3 "r13"
-//#define AREG4 "r14"
-//#define AREG5 "r15"
-#endif
-#ifdef __powerpc__
+//#define AREG4 "rbp"
+//#define AREG5 "rbx"
+#elif defined(__powerpc__)
 #define AREG0 "r27"
 #define AREG1 "r24"
 #define AREG2 "r25"
@@ -113,20 +119,22 @@
 #endif
 #define USE_INT_TO_FLOAT_HELPERS
 #define BUGGY_GCC_DIV64
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
-#endif
-#ifdef __mips__
-#define AREG0 "s3"
+#elif defined(__mips__)
+#define AREG0 "fp"
 #define AREG1 "s0"
 #define AREG2 "s1"
 #define AREG3 "s2"
-#endif
-#ifdef __sparc__
+#define AREG4 "s3"
+#define AREG5 "s4"
+#define AREG6 "s5"
+#define AREG7 "s6"
+#define AREG8 "s7"
+#elif defined(__sparc__)
 #ifdef HOST_SOLARIS
 #define AREG0 "g2"
 #define AREG1 "g3"
@@ -155,14 +163,12 @@
 #endif
 #endif
 #define USE_FP_CONVERT
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define AREG0 "r10"
 #define AREG1 "r7"
 #define AREG2 "r8"
 #define AREG3 "r9"
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 /* Note $15 is the frame pointer, so anything in op-i386.c that would
    require a frame pointer, like alloca, would probably loose.  */
 #define AREG0 "$15"
@@ -172,19 +178,19 @@
 #define AREG4 "$12"
 #define AREG5 "$13"
 #define AREG6 "$14"
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define AREG0 "%a5"
 #define AREG1 "%a4"
 #define AREG2 "%d7"
 #define AREG3 "%d6"
 #define AREG4 "%d5"
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
+#else
+#error unsupported CPU
 #endif
 
 /* force GCC to generate only one epilog at the end of the function */
@@ -237,40 +243,37 @@
 #define ASM_NAME(x) #x
 #endif
 
-#ifdef __i386__
+#if defined(__i386__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __powerpc__
+#elif defined(__powerpc__)
 #define EXIT_TB() asm volatile ("blr")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define EXIT_TB() asm volatile ("br %r14")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 #define EXIT_TB() asm volatile ("ret")
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
 #define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \
 					  ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __sparc__
+#elif defined(__sparc__)
 #define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop")
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define EXIT_TB() asm volatile ("b exec_loop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define EXIT_TB() asm volatile ("rts")
+#elif defined(__mips__)
+#define EXIT_TB() asm volatile ("jr $ra")
+#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#else
+#error unsupported CPU
 #endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */

Modified: trunk/src/host/qemu-neo1973/dyngen.c
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -117,6 +117,21 @@
 #define elf_check_arch(x) ((x) == EM_68K)
 #define ELF_USES_RELOCA
 
+#elif defined(HOST_MIPS)
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOC
+
+#elif defined(HOST_MIPS64)
+
+/* Assume n32 ABI here, which is ELF32. */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOCA
+
 #else
 #error unsupported CPU - please update the code
 #endif
@@ -148,11 +163,11 @@
 
 #ifdef CONFIG_FORMAT_COFF
 
-#include "a.out.h"
-
 typedef int32_t host_long;
 typedef uint32_t host_ulong;
 
+#include "a.out.h"
+
 #define FILENAMELEN 256
 
 typedef struct coff_sym {
@@ -1641,6 +1656,26 @@
             error("rts expected at the end of %s", name);
         copy_size = p - p_start;
     }
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+    {
+#define INSN_RETURN     0x03e00008
+#define INSN_NOP        0x00000000
+
+        uint8_t *p = p_end;
+
+        if (p < (p_start + 0x8)) {
+            error("empty code for %s", name);
+        } else {
+            uint32_t end_insn1, end_insn2;
+
+            p -= 0x8;
+            end_insn1 = get32((uint32_t *)(p + 0x0));
+            end_insn2 = get32((uint32_t *)(p + 0x4));
+            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
+                error("jr ra not found at end of %s", name);
+        }
+        copy_size = p - p_start;
+    }
 #else
 #error unsupported CPU
 #endif
@@ -1715,8 +1750,9 @@
 		    }
 #endif
 #if defined(__APPLE__)
-/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
-                    fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
+                    /* Set __attribute((unused)) on darwin because we
+                       want to avoid warning when we don't use the symbol.  */
+                    fprintf(outfile, "    extern char %s __attribute__((unused));\n", sym_name);
 #elif defined(HOST_IA64)
 			if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
 				/*
@@ -1740,7 +1776,7 @@
         {
             EXE_SYM *sym;
             const char *sym_name, *p;
-            unsigned long val;
+            host_ulong val;
             int n;
 
             for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
@@ -1772,7 +1808,7 @@
 #ifdef CONFIG_FORMAT_MACH
                     offset -= section_hdr[sym->n_sect-1].addr;
 #endif
-                    val = *(unsigned long *)(ptr + offset);
+                    val = *(host_ulong *)(ptr + offset);
 #ifdef ELF_USES_RELOCA
                     {
                         int reloc_shndx, nb_relocs1, j;
@@ -1801,7 +1837,7 @@
             }
         }
 
-        /* load parameres in variables */
+        /* load parameters in variables */
         for(i = 0; i < nb_args; i++) {
             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
         }
@@ -2349,6 +2385,33 @@
                                     reloc_offset, reloc_offset, name, addend,
 				    reloc_offset);
                             break;
+                        case R_SPARC_HH22:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | (((%s + %d) >> 42) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+                             break;
+
+			case R_SPARC_LM22:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | (((%s + %d) >> 10) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+			    break;
+
+			case R_SPARC_HM10:
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + %d) = "
+				    "((*(uint32_t *)(gen_code_ptr + %d)) "
+				    " & ~0x00000000) "
+				    " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
+                                    reloc_offset, reloc_offset, name, addend);
+			    break;
+
                         default:
 			    error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
                         }
@@ -2456,6 +2519,81 @@
                 }
                 }
             }
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+            {
+                for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+		    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
+                        char name[256];
+                        int type;
+                        int addend;
+                        int reloc_offset;
+
+			sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
+                        /* the compiler leave some unnecessary references to the code */
+                        if (sym_name[0] == '\0')
+                            continue;
+                        get_reloc_expr(name, sizeof(name), sym_name);
+			type = ELF32_R_TYPE(rel->r_info);
+                        addend = get32((uint32_t *)(text + rel->r_offset));
+                        reloc_offset = rel->r_offset - start_offset;
+			switch (type) {
+			case R_MIPS_26:
+                            fprintf(outfile, "    /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "(0x%x & ~0x3fffff) "
+				    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+				    "   & 0x3fffff);\n",
+                                    reloc_offset, addend, addend, name, reloc_offset);
+			    break;
+			case R_MIPS_HI16:
+                            fprintf(outfile, "    /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			case R_MIPS_LO16:
+                            fprintf(outfile, "    /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (%s & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			case R_MIPS_PC16:
+                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "(0x%x & ~0xffff) "
+				    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+				    "   & 0xffff);\n",
+                                    reloc_offset, addend, addend, name, reloc_offset);
+			    break;
+			case R_MIPS_GOT16:
+			case R_MIPS_CALL16:
+                            fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
+				    rel->r_offset, sym_name);
+                            fprintf(outfile,
+				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+				    "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+				    " & ~0xffff) "
+				    " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+                                    reloc_offset, reloc_offset, name);
+			    break;
+			default:
+			    error("unsupported MIPS relocation (%d)", type);
+			}
+		    }
+                }
+            }
 #else
 #error unsupported CPU
 #endif

Modified: trunk/src/host/qemu-neo1973/dyngen.h
===================================================================
--- trunk/src/host/qemu-neo1973/dyngen.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/dyngen.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -28,37 +28,21 @@
 #endif
 int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 
-#ifdef __i386__
+#if defined(__i386__) || defined(__x86_64__) || defined(__s390__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
 }
-#endif
-
-#ifdef __x86_64__
+#elif defined(__ia64__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-}
-#endif
-
-#ifdef __s390__
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
-#endif
-
-#ifdef __ia64__
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
     while (start < stop) {
 	asm volatile ("fc %0" :: "r"(start));
 	start += 32;
     }
     asm volatile (";;sync.i;;srlz.i;;");
 }
-#endif
+#elif defined(__powerpc__)
 
-#ifdef __powerpc__
-
 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
 
 static void inline flush_icache_range(unsigned long start, unsigned long stop)
@@ -78,17 +62,12 @@
     asm volatile ("sync" : : : "memory");
     asm volatile ("isync" : : : "memory");
 }
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     asm ("imb");
 }
-#endif
-
-#ifdef __sparc__
-
+#elif defined(__sparc__)
 static void inline flush_icache_range(unsigned long start, unsigned long stop)
 {
 	unsigned long p;
@@ -99,10 +78,7 @@
 	for (; p < stop; p += 8)
 		__asm__ __volatile__("flush\t%0" : : "r" (p));
 }
-
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     register unsigned long _beg __asm ("a1") = start;
@@ -110,14 +86,22 @@
     register unsigned long _flg __asm ("a3") = 0;
     __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
 }
-#endif
+#elif defined(__mc68000)
 
-#ifdef __mc68000
-#include <asm/cachectl.h>
+# include <asm/cachectl.h>
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
 }
+#elif defined(__mips__)
+
+#include <sys/cachectl.h>
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+    _flush_cache ((void *)start, stop - start, BCACHE);
+}
+#else
+#error unsupported CPU
 #endif
 
 #ifdef __alpha__
@@ -248,7 +232,6 @@
 
 #ifdef __ia64
 
-
 /* Patch instruction with "val" where "mask" has 1 bits. */
 static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
 {

Modified: trunk/src/host/qemu-neo1973/ecc.h
===================================================================
--- trunk/src/host/qemu-neo1973/ecc.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/ecc.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -5,7 +5,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 struct ecc_state_s {

Modified: trunk/src/host/qemu-neo1973/elf.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/elf.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -328,6 +328,9 @@
 #define R_SPARC_11		31
 #define R_SPARC_64		32
 #define R_SPARC_OLO10           33
+#define R_SPARC_HH22            34
+#define R_SPARC_HM10            35
+#define R_SPARC_LM22            36
 #define R_SPARC_WDISP16		40
 #define R_SPARC_WDISP19		41
 #define R_SPARC_7		43

Modified: trunk/src/host/qemu-neo1973/elf_ops.h
===================================================================
--- trunk/src/host/qemu-neo1973/elf_ops.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/elf_ops.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -139,11 +139,13 @@
 }
 
 int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
-                       int must_swab, uint64_t *pentry)
+                       int must_swab, uint64_t *pentry,
+                       uint64_t *lowaddr, uint64_t *highaddr)
 {
     struct elfhdr ehdr;
     struct elf_phdr *phdr = NULL, *ph;
     int size, i, total_size;
+    elf_word low = 0, high = 0;
     elf_word mem_size, addr;
     uint8_t *data = NULL;
 
@@ -193,12 +195,20 @@
             cpu_physical_memory_write_rom(addr, data, mem_size);
 
             total_size += mem_size;
+            if (!low || addr < low)
+                low = addr;
+            if (!high || (addr + mem_size) > high)
+                high = addr + mem_size;
 
             qemu_free(data);
             data = NULL;
         }
     }
     qemu_free(phdr);
+    if (lowaddr)
+        *lowaddr = (uint64_t)low;
+    if (highaddr)
+        *highaddr = (uint64_t)high;
     return total_size;
  fail:
     qemu_free(data);

Modified: trunk/src/host/qemu-neo1973/exec-all.h
===================================================================
--- trunk/src/host/qemu-neo1973/exec-all.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/exec-all.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -357,7 +357,7 @@
 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 
-#ifdef __powerpc__
+#if defined(__powerpc__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -373,9 +373,7 @@
                           : "cr0", "memory");
     return ret;
 }
-#endif
-
-#ifdef __i386__
+#elif defined(__i386__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -386,9 +384,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -399,9 +395,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __s390__
+#elif defined(__s390__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -413,9 +407,7 @@
 			  : "cc", "memory" );
     return ret;
 }
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -432,9 +424,7 @@
 			  : "m" (*p));
     return ret;
 }
-#endif
-
-#ifdef __sparc__
+#elif defined(__sparc__)
 static inline int testandset (int *p)
 {
 	int ret;
@@ -446,9 +436,7 @@
 
 	return (ret ? 1 : 0);
 }
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
 static inline int testandset (int *spinlock)
 {
     register unsigned int ret;
@@ -458,9 +446,7 @@
     
     return ret;
 }
-#endif
-
-#ifdef __mc68000
+#elif defined(__mc68000)
 static inline int testandset (int *p)
 {
     char ret;
@@ -470,15 +456,36 @@
                          : "cc","memory");
     return ret;
 }
-#endif
+#elif defined(__ia64)
 
-#ifdef __ia64
 #include <ia64intrin.h>
 
 static inline int testandset (int *p)
 {
     return __sync_lock_test_and_set (p, 1);
 }
+#elif defined(__mips__)
+static inline int testandset (int *p)
+{
+    int ret;
+
+    __asm__ __volatile__ (
+	"	.set push		\n"
+	"	.set noat		\n"
+	"	.set mips2		\n"
+	"1:	li	$1, 1		\n"
+	"	ll	%0, %1		\n"
+	"	sc	$1, %1		\n"
+	"	bnez	$1, 1b		\n"
+	"	.set pop		"
+	: "=r" (ret), "+R" (*p)
+	:
+	: "memory");
+
+    return ret;
+}
+#else
+#error unimplemented CPU support
 #endif
 
 typedef int spinlock_t;
@@ -572,6 +579,8 @@
     is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
 #elif defined (TARGET_SH4)
     is_user = ((env->sr & SR_MD) == 0);
+#elif defined (TARGET_ALPHA)
+    is_user = ((env->ps >> 3) & 3);
 #else
 #error unimplemented CPU
 #endif
@@ -581,13 +590,12 @@
     }
     pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-        cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
+        cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
     }
     return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
 }
 #endif
 
-
 #ifdef USE_KQEMU
 #define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
 

Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/exec.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,6 +47,8 @@
 //#define DEBUG_TB_CHECK 
 //#define DEBUG_TLB_CHECK 
 
+//#define DEBUG_IOPORT
+
 #if !defined(CONFIG_USER_ONLY)
 /* TB consistency checks only implemented for usermode emulation.  */
 #undef DEBUG_TB_CHECK
@@ -62,6 +64,9 @@
 
 #if defined(TARGET_SPARC64)
 #define TARGET_PHYS_ADDR_SPACE_BITS 41
+#elif defined(TARGET_ALPHA)
+#define TARGET_PHYS_ADDR_SPACE_BITS 42
+#define TARGET_VIRT_ADDR_SPACE_BITS 42
 #elif defined(TARGET_PPC64)
 #define TARGET_PHYS_ADDR_SPACE_BITS 42
 #else
@@ -82,6 +87,7 @@
 int phys_ram_fd;
 uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
+static ram_addr_t phys_ram_alloc_offset = 0;
 
 CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
@@ -106,7 +112,15 @@
 } PhysPageDesc;
 
 #define L2_BITS 10
+#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
+/* XXX: this is a temporary hack for alpha target.
+ *      In the future, this is to be replaced by a multi-level table
+ *      to actually be able to handle the complete 64 bits address space.
+ */
+#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
+#else
 #define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#endif
 
 #define L1_SIZE (1 << L1_BITS)
 #define L2_SIZE (1 << L2_BITS)
@@ -127,6 +141,9 @@
 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 static int io_mem_nb;
+#if defined(CONFIG_SOFTMMU)
+static int io_mem_watch;
+#endif
 
 /* log support */
 char *logfilename = "/tmp/qemu.log";
@@ -273,6 +290,7 @@
         cpu_index++;
     }
     env->cpu_index = cpu_index;
+    env->nb_watchpoints = 0;
     *penv = env;
 }
 
@@ -331,7 +349,7 @@
 
 #ifdef DEBUG_TB_CHECK
 
-static void tb_invalidate_check(unsigned long address)
+static void tb_invalidate_check(target_ulong address)
 {
     TranslationBlock *tb;
     int i;
@@ -1012,7 +1030,8 @@
 #if defined(TARGET_HAS_ICE)
 static void breakpoint_invalidate(CPUState *env, target_ulong pc)
 {
-    target_ulong addr, pd;
+    target_phys_addr_t addr;
+    target_ulong pd;
     ram_addr_t ram_addr;
     PhysPageDesc *p;
 
@@ -1028,6 +1047,44 @@
 }
 #endif
 
+/* Add a watchpoint.  */
+int  cpu_watchpoint_insert(CPUState *env, target_ulong addr)
+{
+    int i;
+
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        if (addr == env->watchpoint[i].vaddr)
+            return 0;
+    }
+    if (env->nb_watchpoints >= MAX_WATCHPOINTS)
+        return -1;
+
+    i = env->nb_watchpoints++;
+    env->watchpoint[i].vaddr = addr;
+    tlb_flush_page(env, addr);
+    /* FIXME: This flush is needed because of the hack to make memory ops
+       terminate the TB.  It can be removed once the proper IO trap and
+       re-execute bits are in.  */
+    tb_flush(env);
+    return i;
+}
+
+/* Remove a watchpoint.  */
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
+{
+    int i;
+
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        if (addr == env->watchpoint[i].vaddr) {
+            env->nb_watchpoints--;
+            env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
+            tlb_flush_page(env, addr);
+            return 0;
+        }
+    }
+    return -1;
+}
+
 /* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
    breakpoint is reached */
 int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
@@ -1221,6 +1278,18 @@
     abort();
 }
 
+CPUState *cpu_copy(CPUState *env)
+{
+    CPUState *new_env = cpu_init();
+    /* preserve chaining and index */
+    CPUState *next_cpu = new_env->next_cpu;
+    int cpu_index = new_env->cpu_index;
+    memcpy(new_env, env, sizeof(CPUState));
+    new_env->next_cpu = next_cpu;
+    new_env->cpu_index = cpu_index;
+    return new_env;
+}
+
 #if !defined(CONFIG_USER_ONLY)
 
 /* NOTE: if flush_global is true, also flush global entries (not
@@ -1243,6 +1312,16 @@
         env->tlb_table[1][i].addr_read = -1;
         env->tlb_table[1][i].addr_write = -1;
         env->tlb_table[1][i].addr_code = -1;
+#if (NB_MMU_MODES >= 3)
+        env->tlb_table[2][i].addr_read = -1;
+        env->tlb_table[2][i].addr_write = -1;
+        env->tlb_table[2][i].addr_code = -1;
+#if (NB_MMU_MODES == 4)
+        env->tlb_table[3][i].addr_read = -1;
+        env->tlb_table[3][i].addr_write = -1;
+        env->tlb_table[3][i].addr_code = -1;
+#endif
+#endif
     }
 
     memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
@@ -1288,6 +1367,12 @@
     i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_flush_entry(&env->tlb_table[0][i], addr);
     tlb_flush_entry(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+    tlb_flush_entry(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+    tlb_flush_entry(&env->tlb_table[3][i], addr);
+#endif
+#endif
 
     /* Discard jump cache entries for any tb which might potentially
        overlap the flushed page.  */
@@ -1377,6 +1462,14 @@
             tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
         for(i = 0; i < CPU_TLB_SIZE; i++)
             tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
+#if (NB_MMU_MODES >= 3)
+        for(i = 0; i < CPU_TLB_SIZE; i++)
+            tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
+#if (NB_MMU_MODES == 4)
+        for(i = 0; i < CPU_TLB_SIZE; i++)
+            tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
+#endif
+#endif
     }
 
 #if !defined(CONFIG_SOFTMMU)
@@ -1429,6 +1522,14 @@
         tlb_update_dirty(&env->tlb_table[0][i]);
     for(i = 0; i < CPU_TLB_SIZE; i++)
         tlb_update_dirty(&env->tlb_table[1][i]);
+#if (NB_MMU_MODES >= 3)
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_table[2][i]);
+#if (NB_MMU_MODES == 4)
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_table[3][i]);
+#endif
+#endif
 }
 
 static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, 
@@ -1454,6 +1555,12 @@
     i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
     tlb_set_dirty1(&env->tlb_table[0][i], addr);
     tlb_set_dirty1(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+    tlb_set_dirty1(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+    tlb_set_dirty1(&env->tlb_table[3][i], addr);
+#endif
+#endif
 }
 
 /* add a new TLB entry. At most one entry for a given virtual address
@@ -1471,6 +1578,7 @@
     target_phys_addr_t addend;
     int ret;
     CPUTLBEntry *te;
+    int i;
 
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
     if (!p) {
@@ -1497,6 +1605,22 @@
             address = vaddr;
             addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
         }
+
+        /* Make accesses to pages with watchpoints go via the
+           watchpoint trap routines.  */
+        for (i = 0; i < env->nb_watchpoints; i++) {
+            if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) {
+                if (address & ~TARGET_PAGE_MASK) {
+                    env->watchpoint[i].is_ram = 0;
+                    address = vaddr | io_mem_watch;
+                } else {
+                    env->watchpoint[i].is_ram = 1;
+                    /* TODO: Figure out how to make read watchpoints coexist
+                       with code.  */
+                    pd = (pd & TARGET_PAGE_MASK) | io_mem_watch | IO_MEM_ROMD;
+                }
+            }
+        }
         
         index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
         addend -= vaddr;
@@ -1812,11 +1936,33 @@
     return p->phys_offset;
 }
 
+/* XXX: better than nothing */
+ram_addr_t qemu_ram_alloc(unsigned int size)
+{
+    ram_addr_t addr;
+    if ((phys_ram_alloc_offset + size) >= phys_ram_size) {
+        fprintf(stderr, "Not enough memory (requested_size = %u, max memory = %d)\n", 
+                size, phys_ram_size);
+        abort();
+    }
+    addr = phys_ram_alloc_offset;
+    phys_ram_alloc_offset = TARGET_PAGE_ALIGN(phys_ram_alloc_offset + size);
+    return addr;
+}
+
+void qemu_ram_free(ram_addr_t addr)
+{
+}
+
 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
 {
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read  0x%08x\n", (int)addr);
 #endif
+#ifdef TARGET_SPARC
+    // Not enabled yet because of bugs in gdbstub etc.
+    //raise_exception(TT_DATA_ACCESS);
+#endif
     return 0;
 }
 
@@ -1825,6 +1971,10 @@
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
 #endif
+#ifdef TARGET_SPARC
+    // Not enabled yet because of bugs in gdbstub etc.
+    //raise_exception(TT_DATA_ACCESS);
+#endif
 }
 
 static CPUReadMemoryFunc *unassigned_mem_read[3] = {
@@ -1929,6 +2079,85 @@
     notdirty_mem_writel,
 };
 
+#if defined(CONFIG_SOFTMMU)
+/* Watchpoint access routines.  Watchpoints are inserted using TLB tricks,
+   so these check for a hit then pass through to the normal out-of-line
+   phys routines.  */
+static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+    return ldub_phys(addr);
+}
+
+static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+    return lduw_phys(addr);
+}
+
+static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    return ldl_phys(addr);
+}
+
+/* Generate a debug exception if a watchpoint has been hit.
+   Returns the real physical address of the access.  addr will be a host
+   address in the is_ram case.  */
+static target_ulong check_watchpoint(target_phys_addr_t addr)
+{
+    CPUState *env = cpu_single_env;
+    target_ulong watch;
+    target_ulong retaddr;
+    int i;
+
+    retaddr = addr;
+    for (i = 0; i < env->nb_watchpoints; i++) {
+        watch = env->watchpoint[i].vaddr;
+        if (((env->mem_write_vaddr ^ watch) & TARGET_PAGE_MASK) == 0) {
+            if (env->watchpoint[i].is_ram)
+                retaddr = addr - (unsigned long)phys_ram_base;
+            if (((addr ^ watch) & ~TARGET_PAGE_MASK) == 0) {
+                cpu_single_env->watchpoint_hit = i + 1;
+                cpu_interrupt(cpu_single_env, CPU_INTERRUPT_DEBUG);
+                break;
+            }
+        }
+    }
+    return retaddr;
+}
+
+static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stb_phys(addr, val);
+}
+
+static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stw_phys(addr, val);
+}
+
+static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+    addr = check_watchpoint(addr);
+    stl_phys(addr, val);
+}
+
+static CPUReadMemoryFunc *watch_mem_read[3] = {
+    watch_mem_readb,
+    watch_mem_readw,
+    watch_mem_readl,
+};
+
+static CPUWriteMemoryFunc *watch_mem_write[3] = {
+    watch_mem_writeb,
+    watch_mem_writew,
+    watch_mem_writel,
+};
+#endif
+
 static void io_mem_init(void)
 {
     cpu_register_io_memory(IO_MEM_ROM >> IO_MEM_SHIFT, error_mem_read, unassigned_mem_write, NULL);
@@ -1936,6 +2165,10 @@
     cpu_register_io_memory(IO_MEM_NOTDIRTY >> IO_MEM_SHIFT, error_mem_read, notdirty_mem_write, NULL);
     io_mem_nb = 5;
 
+#if defined(CONFIG_SOFTMMU)
+    io_mem_watch = cpu_register_io_memory(-1, watch_mem_read,
+                                          watch_mem_write, NULL);
+#endif
     /* alloc dirty bits array */
     phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
     memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
@@ -2258,6 +2491,36 @@
     }
 }
 
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val)
+{
+    int io_index;
+    uint8_t *ptr;
+    unsigned long pd;
+    PhysPageDesc *p;
+
+    p = phys_page_find(addr >> TARGET_PAGE_BITS);
+    if (!p) {
+        pd = IO_MEM_UNASSIGNED;
+    } else {
+        pd = p->phys_offset;
+    }
+        
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+        io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+#ifdef TARGET_WORDS_BIGENDIAN
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val >> 32);
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val);
+#else
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+        io_mem_write[io_index][2](io_mem_opaque[io_index], addr + 4, val >> 32);
+#endif
+    } else {
+        ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
+            (addr & ~TARGET_PAGE_MASK);
+        stq_p(ptr, val);
+    }
+}
+
 /* warning: addr must be aligned */
 void stl_phys(target_phys_addr_t addr, uint32_t val)
 {
@@ -2320,7 +2583,8 @@
                         uint8_t *buf, int len, int is_write)
 {
     int l;
-    target_ulong page, phys_addr;
+    target_phys_addr_t phys_addr;
+    target_ulong page;
 
     while (len > 0) {
         page = addr & TARGET_PAGE_MASK;

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat-native.c
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat-native.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat-native.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -30,7 +30,26 @@
 #define sqrtf(f)		((float)sqrt(f))
 #define remainderf(fa, fb)	((float)remainder(fa, fb))
 #define rintf(f)		((float)rint(f))
+#if !defined(__sparc__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
+extern long double rintl(long double);
+extern long double scalbnl(long double, int);
+
+long long
+llrintl(long double x) {
+	return ((long long) rintl(x));
+}
+
+long
+lrintl(long double x) {
+	return ((long) rintl(x));
+}
+
+long double
+ldexpl(long double x, int n) {
+	return (scalbnl(x, n));
+}
 #endif
+#endif
 
 #if defined(__powerpc__)
 
@@ -59,11 +78,21 @@
     return (float32)v;
 }
 
+float32 uint32_to_float32(unsigned int v STATUS_PARAM)
+{
+    return (float32)v;
+}
+
 float64 int32_to_float64(int v STATUS_PARAM)
 {
     return (float64)v;
 }
 
+float64 uint32_to_float64(unsigned int v STATUS_PARAM)
+{
+    return (float64)v;
+}
+
 #ifdef FLOATX80
 floatx80 int32_to_floatx80(int v STATUS_PARAM)
 {
@@ -74,10 +103,18 @@
 {
     return (float32)v;
 }
+float32 uint64_to_float32( uint64_t v STATUS_PARAM)
+{
+    return (float32)v;
+}
 float64 int64_to_float64( int64_t v STATUS_PARAM)
 {
     return (float64)v;
 }
+float64 uint64_to_float64( uint64_t v STATUS_PARAM)
+{
+    return (float64)v;
+}
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
 {
@@ -132,6 +169,37 @@
 }
 #endif
 
+unsigned int float32_to_uint32( float32 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = llrintf(a);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = (int64_t)a;
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision operations.
 *----------------------------------------------------------------------------*/
@@ -218,9 +286,62 @@
 }
 #endif
 
+unsigned int float64_to_uint32( float64 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = llrint(a);
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM)
+{
+    int64_t v;
+    unsigned int res;
+
+    v = (int64_t)a;
+    if (v < 0) {
+        res = 0;
+    } else if (v > 0xffffffff) {
+        res = 0xffffffff;
+    } else {
+        res = v;
+    }
+    return res;
+}
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = llrint(a + (float64)INT64_MIN);
+
+    return v - INT64_MIN;
+}
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = (int64_t)(a + (float64)INT64_MIN);
+
+    return v - INT64_MIN;
+}
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision operations.
 *----------------------------------------------------------------------------*/
+#if defined(__sun__) && defined(HOST_SOLARIS) && HOST_SOLARIS < 10
+static inline float64 trunc(float64 x)
+{
+    return x < 0 ? -floor(-x) : floor(x);
+}
+#endif
 float64 float64_trunc_to_int( float64 a STATUS_PARAM )
 {
     return trunc(a);

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat-native.h
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat-native.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat-native.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -15,7 +15,7 @@
  *   Solaris 10 with GCC4 does not need these macros as they
  *   are defined in <iso/math_c99.h> with a compiler directive
  */
-#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ( ( HOST_SOLARIS >= 10 ) && ( __GNUC__ <= 4) ))
+#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ((HOST_SOLARIS >= 10) && (__GNUC__ <= 4)))
 /*
  * C99 7.12.3 classification macros
  * and
@@ -33,6 +33,29 @@
 #define isunordered(x,y)        unordered(x, y)
 #endif
 
+#if defined(__sun__) && !defined(NEED_LIBSUNMATH)
+
+#ifndef isnan
+# define isnan(x) \
+    (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
+     : sizeof (x) == sizeof (double) ? isnan_d (x) \
+     : isnan_f (x))
+static inline int isnan_f  (float       x) { return x != x; }
+static inline int isnan_d  (double      x) { return x != x; }
+static inline int isnan_ld (long double x) { return x != x; }
+#endif
+
+#ifndef isinf
+# define isinf(x) \
+    (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
+     : sizeof (x) == sizeof (double) ? isinf_d (x) \
+     : isinf_f (x))
+static inline int isinf_f  (float       x) { return isnan (x - x); }
+static inline int isinf_d  (double      x) { return isnan (x - x); }
+static inline int isinf_ld (long double x) { return isnan (x - x); }
+#endif
+#endif
+
 typedef float float32;
 typedef double float64;
 #ifdef FLOATX80
@@ -99,7 +122,9 @@
 | Software IEC/IEEE integer-to-floating-point conversion routines.
 *----------------------------------------------------------------------------*/
 float32 int32_to_float32( int STATUS_PARAM);
+float32 uint32_to_float32( unsigned int STATUS_PARAM);
 float64 int32_to_float64( int STATUS_PARAM);
+float64 uint32_to_float64( unsigned int STATUS_PARAM);
 #ifdef FLOATX80
 floatx80 int32_to_floatx80( int STATUS_PARAM);
 #endif
@@ -107,7 +132,9 @@
 float128 int32_to_float128( int STATUS_PARAM);
 #endif
 float32 int64_to_float32( int64_t STATUS_PARAM);
+float32 uint64_to_float32( uint64_t STATUS_PARAM);
 float64 int64_to_float64( int64_t STATUS_PARAM);
+float64 uint64_to_float64( uint64_t v STATUS_PARAM);
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
 #endif
@@ -120,6 +147,8 @@
 *----------------------------------------------------------------------------*/
 int float32_to_int32( float32  STATUS_PARAM);
 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
+unsigned int float32_to_uint32( float32 a STATUS_PARAM);
+unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM);
 int64_t float32_to_int64( float32  STATUS_PARAM);
 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
 float64 float32_to_float64( float32  STATUS_PARAM);
@@ -200,8 +229,12 @@
 *----------------------------------------------------------------------------*/
 int float64_to_int32( float64 STATUS_PARAM );
 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
+unsigned int float64_to_uint32( float64 STATUS_PARAM );
+unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
 int64_t float64_to_int64( float64 STATUS_PARAM );
 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
+uint64_t float64_to_uint64( float64 STATUS_PARAM );
+uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM );
 float32 float64_to_float32( float64 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 STATUS_PARAM );

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat.c
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1164,6 +1164,27 @@
 
 }
 
+float32 uint64_to_float32( uint64 a STATUS_PARAM )
+{
+    int8 shiftCount;
+
+    if ( a == 0 ) return 0;
+    shiftCount = countLeadingZeros64( a ) - 40;
+    if ( 0 <= shiftCount ) {
+        return packFloat32( 1 > 0, 0x95 - shiftCount, a<<shiftCount );
+    }
+    else {
+        shiftCount += 7;
+        if ( shiftCount < 0 ) {
+            shift64RightJamming( a, - shiftCount, &a );
+        }
+        else {
+            a <<= shiftCount;
+        }
+        return roundAndPackFloat32( 1 > 0, 0x9C - shiftCount, a STATUS_VAR );
+    }
+}
+
 /*----------------------------------------------------------------------------
 | Returns the result of converting the 64-bit two's complement integer `a'
 | to the double-precision floating-point format.  The conversion is performed
@@ -1183,6 +1204,13 @@
 
 }
 
+float64 uint64_to_float64( uint64 a STATUS_PARAM )
+{
+    if ( a == 0 ) return 0;
+    return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
+
+}
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
@@ -5282,6 +5310,26 @@
     return res;
 }
 
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = int64_to_float64(INT64_MIN STATUS_VAR);
+    v = float64_to_int64((a + v) STATUS_VAR);
+
+    return v - INT64_MIN;
+}
+
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
+{
+    int64_t v;
+
+    v = int64_to_float64(INT64_MIN STATUS_VAR);
+    v = float64_to_int64_round_to_zero((a + v) STATUS_VAR);
+
+    return v - INT64_MIN;
+}
+
 #define COMPARE(s, nan_exp)                                                  \
 INLINE int float ## s ## _compare_internal( float ## s a, float ## s b,      \
                                       int is_quiet STATUS_PARAM )            \

Modified: trunk/src/host/qemu-neo1973/fpu/softfloat.h
===================================================================
--- trunk/src/host/qemu-neo1973/fpu/softfloat.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/fpu/softfloat.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,6 +32,10 @@
 #ifndef SOFTFLOAT_H
 #define SOFTFLOAT_H
 
+#if defined(HOST_SOLARIS) && defined(NEEDS_LIBSUNMATH)
+#include <sunmath.h>
+#endif
+
 #include <inttypes.h>
 #include "config.h"
 
@@ -193,7 +197,9 @@
 float128 int32_to_float128( int STATUS_PARAM );
 #endif
 float32 int64_to_float32( int64_t STATUS_PARAM );
+float32 uint64_to_float32( uint64_t STATUS_PARAM );
 float64 int64_to_float64( int64_t STATUS_PARAM );
+float64 uint64_to_float64( uint64_t STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 int64_to_floatx80( int64_t STATUS_PARAM );
 #endif
@@ -258,6 +264,8 @@
 unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
 int64_t float64_to_int64( float64 STATUS_PARAM );
 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
+uint64_t float64_to_uint64 (float64 a STATUS_PARAM);
+uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
 float32 float64_to_float32( float64 STATUS_PARAM );
 #ifdef FLOATX80
 floatx80 float64_to_floatx80( float64 STATUS_PARAM );

Modified: trunk/src/host/qemu-neo1973/gdbstub.c
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/gdbstub.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -52,26 +52,30 @@
     RS_GETLINE,
     RS_CHKSUM1,
     RS_CHKSUM2,
+    RS_SYSCALL,
 };
-/* XXX: This is not thread safe.  Do we care?  */
-static int gdbserver_fd = -1;
-
 typedef struct GDBState {
     CPUState *env; /* current CPU */
     enum RSState state; /* parsing state */
-    int fd;
     char line_buf[4096];
     int line_buf_index;
     int line_csum;
+    char last_packet[4100];
+    int last_packet_len;
 #ifdef CONFIG_USER_ONLY
+    int fd;
     int running_state;
+#else
+    CharDriverState *chr;
 #endif
 } GDBState;
 
 #ifdef CONFIG_USER_ONLY
+/* XXX: This is not thread safe.  Do we care?  */
+static int gdbserver_fd = -1;
+
 /* XXX: remove this hack.  */
 static GDBState gdbserver_state;
-#endif
 
 static int get_char(GDBState *s)
 {
@@ -91,9 +95,32 @@
     }
     return ch;
 }
+#endif
 
+/* GDB stub state for use by semihosting syscalls.  */
+static GDBState *gdb_syscall_state;
+static gdb_syscall_complete_cb gdb_current_syscall_cb;
+
+enum {
+    GDB_SYS_UNKNOWN,
+    GDB_SYS_ENABLED,
+    GDB_SYS_DISABLED,
+} gdb_syscall_mode;
+
+/* If gdb is connected when the first semihosting syscall occurs then use
+   remote gdb syscalls.  Otherwise use native file IO.  */
+int use_gdb_syscalls(void)
+{
+    if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
+        gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED
+                                              : GDB_SYS_DISABLED);
+    }
+    return gdb_syscall_mode == GDB_SYS_ENABLED;
+}
+
 static void put_buffer(GDBState *s, const uint8_t *buf, int len)
 {
+#ifdef CONFIG_USER_ONLY
     int ret;
 
     while (len > 0) {
@@ -106,6 +133,9 @@
             len -= ret;
         }
     }
+#else
+    qemu_chr_write(s->chr, buf, len);
+#endif
 }
 
 static inline int fromhex(int v)
@@ -154,33 +184,39 @@
 /* return -1 if error, 0 if OK */
 static int put_packet(GDBState *s, char *buf)
 {
-    char buf1[3];
-    int len, csum, ch, i;
+    int len, csum, i;
+    char *p;
 
 #ifdef DEBUG_GDB
     printf("reply='%s'\n", buf);
 #endif
 
     for(;;) {
-        buf1[0] = '$';
-        put_buffer(s, buf1, 1);
+        p = s->last_packet;
+        *(p++) = '$';
         len = strlen(buf);
-        put_buffer(s, buf, len);
+        memcpy(p, buf, len);
+        p += len;
         csum = 0;
         for(i = 0; i < len; i++) {
             csum += buf[i];
         }
-        buf1[0] = '#';
-        buf1[1] = tohex((csum >> 4) & 0xf);
-        buf1[2] = tohex((csum) & 0xf);
+        *(p++) = '#';
+        *(p++) = tohex((csum >> 4) & 0xf);
+        *(p++) = tohex((csum) & 0xf);
 
-        put_buffer(s, buf1, 3);
+        s->last_packet_len = p - s->last_packet;
+        put_buffer(s, s->last_packet, s->last_packet_len);
 
-        ch = get_char(s);
-        if (ch < 0)
+#ifdef CONFIG_USER_ONLY
+        i = get_char(s);
+        if (i < 0)
             return -1;
-        if (ch == '+')
+        if (i == '+')
             break;
+#else
+        break;
+#endif
     }
     return 0;
 }
@@ -271,7 +307,7 @@
     registers[98] = tswapl(tmp);
     registers[99] = tswapl(env->lr);
     registers[100] = tswapl(env->ctr);
-    registers[101] = tswapl(do_load_xer(env));
+    registers[101] = tswapl(ppc_load_xer(env));
     registers[102] = 0;
 
     return 103 * 4;
@@ -299,7 +335,7 @@
         env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
     env->lr = tswapl(registers[99]);
     env->ctr = tswapl(registers[100]);
-    do_store_xer(env, tswapl(registers[101]));
+    ppc_store_xer(env, tswapl(registers[101]));
 }
 #elif defined (TARGET_SPARC)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -341,9 +377,9 @@
     for (i = 0; i < 64; i += 2) {
 	uint64_t tmp;
 
-        tmp = (uint64_t)tswap32(*((uint32_t *)&env->fpr[i])) << 32;
-        tmp |= tswap32(*((uint32_t *)&env->fpr[i + 1]));
-        registers[i/2 + 32] = tmp;
+        tmp = ((uint64_t)*(uint32_t *)&env->fpr[i]) << 32;
+        tmp |= *(uint32_t *)&env->fpr[i + 1];
+        registers[i / 2 + 32] = tswap64(tmp);
     }
     registers[64] = tswapl(env->pc);
     registers[65] = tswapl(env->npc);
@@ -383,8 +419,11 @@
     env->fsr = tswapl(registers[70]);
 #else
     for (i = 0; i < 64; i += 2) {
-	*((uint32_t *)&env->fpr[i]) = tswap32(registers[i/2 + 32] >> 32);
-	*((uint32_t *)&env->fpr[i + 1]) = tswap32(registers[i/2 + 32] & 0xffffffff);
+        uint64_t tmp;
+
+        tmp = tswap64(registers[i / 2 + 32]);
+	*((uint32_t *)&env->fpr[i]) = tmp >> 32;
+	*((uint32_t *)&env->fpr[i + 1]) = tmp & 0xffffffff;
     }
     env->pc = tswapl(registers[64]);
     env->npc = tswapl(registers[65]);
@@ -532,20 +571,21 @@
     *(uint32_t *)ptr = tswapl(env->PC);
     ptr += 4;
 
-#ifdef MIPS_USES_FPU
-    for (i = 0; i < 32; i++)
+    if (env->CP0_Config1 & (1 << CP0C1_FP))
       {
-        *(uint32_t *)ptr = tswapl(FPR_W (env, i));
+        for (i = 0; i < 32; i++)
+          {
+            *(uint32_t *)ptr = tswapl(env->fpr[i].fs[FP_ENDIAN_IDX]);
+            ptr += 4;
+          }
+
+        *(uint32_t *)ptr = tswapl(env->fcr31);
         ptr += 4;
+
+        *(uint32_t *)ptr = tswapl(env->fcr0);
+        ptr += 4;
       }
 
-    *(uint32_t *)ptr = tswapl(env->fcr31);
-    ptr += 4;
-
-    *(uint32_t *)ptr = tswapl(env->fcr0);
-    ptr += 4;
-#endif
-
     /* 32 FP registers, fsr, fir, fp.  Not yet implemented.  */
     /* what's 'fp' mean here?  */
 
@@ -593,27 +633,28 @@
     env->PC = tswapl(*(uint32_t *)ptr);
     ptr += 4;
 
-#ifdef MIPS_USES_FPU
-    for (i = 0; i < 32; i++)
+    if (env->CP0_Config1 & (1 << CP0C1_FP))
       {
-	FPR_W (env, i) = tswapl(*(uint32_t *)ptr);
+        for (i = 0; i < 32; i++)
+          {
+            env->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(uint32_t *)ptr);
+            ptr += 4;
+          }
+
+        env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
         ptr += 4;
-      }
 
-    env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF;
-    ptr += 4;
+        env->fcr0 = tswapl(*(uint32_t *)ptr);
+        ptr += 4;
 
-    env->fcr0 = tswapl(*(uint32_t *)ptr);
-    ptr += 4;
+        /* set rounding mode */
+        RESTORE_ROUNDING_MODE;
 
-    /* set rounding mode */
-    RESTORE_ROUNDING_MODE;
-
 #ifndef CONFIG_SOFTFLOAT
-    /* no floating point exception for native float */
-    SET_FP_ENABLE(env->fcr31, 0);
+        /* no floating point exception for native float */
+        SET_FP_ENABLE(env->fcr31, 0);
 #endif
-#endif
+      }
 }
 #elif defined (TARGET_SH4)
 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
@@ -741,6 +782,34 @@
         vm_start();
 #endif
 	return RS_IDLE;
+    case 'F':
+        {
+            target_ulong ret;
+            target_ulong err;
+
+            ret = strtoull(p, (char **)&p, 16);
+            if (*p == ',') {
+                p++;
+                err = strtoull(p, (char **)&p, 16);
+            } else {
+                err = 0;
+            }
+            if (*p == ',')
+                p++;
+            type = *p;
+            if (gdb_current_syscall_cb)
+                gdb_current_syscall_cb(s->env, ret, err);
+            if (type == 'C') {
+                put_packet(s, "T02");
+            } else {
+#ifdef CONFIG_USER_ONLY
+                s->running_state = 1;
+#else
+                vm_start();
+#endif
+            }
+        }
+        break;
     case 'g':
         reg_size = cpu_gdb_read_registers(env, mem_buf);
         memtohex(buf, mem_buf, reg_size);
@@ -790,6 +859,12 @@
             if (cpu_breakpoint_insert(env, addr) < 0)
                 goto breakpoint_error;
             put_packet(s, "OK");
+#ifndef CONFIG_USER_ONLY
+        } else if (type == 2) {
+            if (cpu_watchpoint_insert(env, addr) < 0)
+                goto breakpoint_error;
+            put_packet(s, "OK");
+#endif
         } else {
         breakpoint_error:
             put_packet(s, "E22");
@@ -806,11 +881,16 @@
         if (type == 0 || type == 1) {
             cpu_breakpoint_remove(env, addr);
             put_packet(s, "OK");
+#ifndef CONFIG_USER_ONLY
+        } else if (type == 2) {
+            cpu_watchpoint_remove(env, addr);
+            put_packet(s, "OK");
+#endif
         } else {
             goto breakpoint_error;
         }
         break;
-#ifdef CONFIG_USER_ONLY
+#ifdef CONFIG_LINUX_USER
     case 'q':
         if (strncmp(p, "Offsets", 7) == 0) {
             TaskState *ts = env->opaque;
@@ -841,10 +921,21 @@
     char buf[256];
     int ret;
 
+    if (s->state == RS_SYSCALL)
+        return;
+
     /* disable single step if it was enable */
     cpu_single_step(s->env, 0);
 
     if (reason == EXCP_DEBUG) {
+        if (s->env->watchpoint_hit) {
+            snprintf(buf, sizeof(buf), "T%02xwatch:" TARGET_FMT_lx ";",
+                     SIGTRAP,
+                     s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr);
+            put_packet(s, buf);
+            s->env->watchpoint_hit = 0;
+            return;
+        }
 	tb_flush(s->env);
         ret = SIGTRAP;
     } else if (reason == EXCP_INTERRUPT) {
@@ -857,6 +948,60 @@
 }
 #endif
 
+/* Send a gdb syscall request.
+   This accepts limited printf-style format specifiers, specifically:
+    %x - target_ulong argument printed in hex.
+    %s - string pointer (target_ulong) and length (int) pair.  */
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...)
+{
+    va_list va;
+    char buf[256];
+    char *p;
+    target_ulong addr;
+    GDBState *s;
+
+    s = gdb_syscall_state;
+    if (!s)
+        return;
+    gdb_current_syscall_cb = cb;
+    s->state = RS_SYSCALL;
+#ifndef CONFIG_USER_ONLY
+    vm_stop(EXCP_DEBUG);
+#endif
+    s->state = RS_IDLE;
+    va_start(va, fmt);
+    p = buf;
+    *(p++) = 'F';
+    while (*fmt) {
+        if (*fmt == '%') {
+            fmt++;
+            switch (*fmt++) {
+            case 'x':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx, addr);
+                break;
+            case 's':
+                addr = va_arg(va, target_ulong);
+                p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int));
+                break;
+            default:
+                fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",
+                        fmt - 1);
+                break;
+            }
+        } else {
+            *(p++) = *(fmt++);
+        }
+    }
+    va_end(va);
+    put_packet(s, buf);
+#ifdef CONFIG_USER_ONLY
+    gdb_handlesig(s->env, 0);
+#else
+    cpu_interrupt(s->env, CPU_INTERRUPT_EXIT);
+#endif
+}
+
 static void gdb_read_byte(GDBState *s, int ch)
 {
     CPUState *env = s->env;
@@ -864,6 +1009,26 @@
     char reply[1];
 
 #ifndef CONFIG_USER_ONLY
+    if (s->last_packet_len) {
+        /* Waiting for a response to the last packet.  If we see the start
+           of a new command then abandon the previous response.  */
+        if (ch == '-') {
+#ifdef DEBUG_GDB
+            printf("Got NACK, retransmitting\n");
+#endif
+            put_buffer(s, s->last_packet, s->last_packet_len);
+        }
+#ifdef DEBUG_GDB
+        else if (ch == '+')
+            printf("Got ACK\n");
+        else
+            printf("Got '%c' when expecting ACK/NACK\n", ch);
+#endif
+        if (ch == '+' || ch == '$')
+            s->last_packet_len = 0;
+        if (ch != '$')
+            return;
+    }
     if (vm_running) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
@@ -908,6 +1073,8 @@
                 s->state = gdb_handle_packet(s, env, s->line_buf);
             }
             break;
+        default:
+            abort();
         }
     }
 }
@@ -972,30 +1139,7 @@
   put_packet(s, buf);
 }
 
-#else
-static void gdb_read(void *opaque)
-{
-    GDBState *s = opaque;
-    int i, size;
-    uint8_t buf[4096];
 
-    size = recv(s->fd, buf, sizeof(buf), 0);
-    if (size < 0)
-        return;
-    if (size == 0) {
-        /* end of connection */
-        qemu_del_vm_stop_handler(gdb_vm_stopped, s);
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
-        qemu_free(s);
-        vm_start();
-    } else {
-        for(i = 0; i < size; i++)
-            gdb_read_byte(s, buf[i]);
-    }
-}
-
-#endif
-
 static void gdb_accept(void *opaque)
 {
     GDBState *s;
@@ -1018,32 +1162,14 @@
     val = 1;
     setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
     
-#ifdef CONFIG_USER_ONLY
     s = &gdbserver_state;
     memset (s, 0, sizeof (GDBState));
-#else
-    s = qemu_mallocz(sizeof(GDBState));
-    if (!s) {
-        close(fd);
-        return;
-    }
-#endif
     s->env = first_cpu; /* XXX: allow to change CPU */
     s->fd = fd;
 
-#ifdef CONFIG_USER_ONLY
+    gdb_syscall_state = s;
+
     fcntl(fd, F_SETFL, O_NONBLOCK);
-#else
-    socket_set_nonblock(fd);
-
-    /* stop the VM */
-    vm_stop(EXCP_INTERRUPT);
-
-    /* start handling I/O */
-    qemu_set_fd_handler(s->fd, gdb_read, NULL, s);
-    /* when the VM is stopped, the following callback is called */
-    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
-#endif
 }
 
 static int gdbserver_open(int port)
@@ -1074,9 +1200,6 @@
         perror("listen");
         return -1;
     }
-#ifndef CONFIG_USER_ONLY
-    socket_set_nonblock(fd);
-#endif
     return fd;
 }
 
@@ -1086,10 +1209,69 @@
     if (gdbserver_fd < 0)
         return -1;
     /* accept connections */
-#ifdef CONFIG_USER_ONLY
     gdb_accept (NULL);
+    return 0;
+}
 #else
-    qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL);
-#endif
+static int gdb_chr_can_recieve(void *opaque)
+{
+  return 1;
+}
+
+static void gdb_chr_recieve(void *opaque, const uint8_t *buf, int size)
+{
+    GDBState *s = opaque;
+    int i;
+
+    for (i = 0; i < size; i++) {
+        gdb_read_byte(s, buf[i]);
+    }
+}
+
+static void gdb_chr_event(void *opaque, int event)
+{
+    switch (event) {
+    case CHR_EVENT_RESET:
+        vm_stop(EXCP_INTERRUPT);
+        gdb_syscall_state = opaque;
+        break;
+    default:
+        break;
+    }
+}
+
+int gdbserver_start(const char *port)
+{
+    GDBState *s;
+    char gdbstub_port_name[128];
+    int port_num;
+    char *p;
+    CharDriverState *chr;
+
+    if (!port || !*port)
+      return -1;
+
+    port_num = strtol(port, &p, 10);
+    if (*p == 0) {
+        /* A numeric value is interpreted as a port number.  */
+        snprintf(gdbstub_port_name, sizeof(gdbstub_port_name),
+                 "tcp::%d,nowait,nodelay,server", port_num);
+        port = gdbstub_port_name;
+    }
+
+    chr = qemu_chr_open(port);
+    if (!chr)
+        return -1;
+
+    s = qemu_mallocz(sizeof(GDBState));
+    if (!s) {
+        return -1;
+    }
+    s->env = first_cpu; /* XXX: allow to change CPU */
+    s->chr = chr;
+    qemu_chr_add_handlers(chr, gdb_chr_can_recieve, gdb_chr_recieve,
+                          gdb_chr_event, s);
+    qemu_add_vm_stop_handler(gdb_vm_stopped, s);
     return 0;
 }
+#endif

Modified: trunk/src/host/qemu-neo1973/gdbstub.h
===================================================================
--- trunk/src/host/qemu-neo1973/gdbstub.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/gdbstub.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,12 +1,19 @@
 #ifndef GDBSTUB_H
 #define GDBSTUB_H
 
-#define DEFAULT_GDBSTUB_PORT 1234
+#define DEFAULT_GDBSTUB_PORT "1234"
 
+typedef void (*gdb_syscall_complete_cb)(CPUState *env,
+                                        target_ulong ret, target_ulong err);
+
+void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...);
+int use_gdb_syscalls(void);
 #ifdef CONFIG_USER_ONLY
 int gdb_handlesig (CPUState *, int);
 void gdb_exit(CPUState *, int);
+int gdbserver_start(int);
+#else
+int gdbserver_start(const char *port);
 #endif
-int gdbserver_start(int);
 
 #endif

Added: trunk/src/host/qemu-neo1973/hostregs_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/hostregs_helper.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hostregs_helper.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,98 @@
+/*
+ *  Save/restore host registrs.
+ *
+ *  Copyright (c) 2007 CodeSourcery
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* The GCC global register vairable extension is used to reserve some
+   host registers for use by dyngen.  However only the core parts of the
+   translation engine are compiled with these settings.  We must manually
+   save/restore these registers when called from regular code.
+   It is not sufficient to save/restore T0 et. al. as these may be declared
+   with a datatype smaller than the actual register.  */
+
+#if defined(DECLARE_HOST_REGS)
+
+#define DO_REG(REG)					\
+    register host_reg_t reg_AREG##REG asm(AREG##REG);	\
+    volatile host_reg_t saved_AREG##REG;
+
+#elif defined(SAVE_HOST_REGS)
+
+#define DO_REG(REG)					\
+    __asm__ __volatile__ ("" : "=r" (reg_AREG##REG));	\
+    saved_AREG##REG = reg_AREG##REG;
+
+#else
+
+#define DO_REG(REG)                                     \
+    reg_AREG##REG = saved_AREG##REG;		        \
+    __asm__ __volatile__ ("" : : "r" (reg_AREG##REG));
+
+#endif
+
+#ifdef AREG0
+DO_REG(0)
+#endif
+
+#ifdef AREG1
+DO_REG(1)
+#endif
+
+#ifdef AREG2
+DO_REG(2)
+#endif
+
+#ifdef AREG3
+DO_REG(3)
+#endif
+
+#ifdef AREG4
+DO_REG(4)
+#endif
+
+#ifdef AREG5
+DO_REG(5)
+#endif
+
+#ifdef AREG6
+DO_REG(6)
+#endif
+
+#ifdef AREG7
+DO_REG(7)
+#endif
+
+#ifdef AREG8
+DO_REG(8)
+#endif
+
+#ifdef AREG9
+DO_REG(9)
+#endif
+
+#ifdef AREG10
+DO_REG(10)
+#endif
+
+#ifdef AREG11
+DO_REG(11)
+#endif
+
+#undef SAVE_HOST_REGS
+#undef DECLARE_HOST_REGS
+#undef DO_REG

Modified: trunk/src/host/qemu-neo1973/hw/acpi.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/acpi.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/acpi.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -24,6 +24,7 @@
 #define PM_FREQ 3579545
 
 #define ACPI_DBG_IO_ADDR  0xb044
+#define SMB_IO_BASE       0xb100
 
 typedef struct PIIX4PMState {
     PCIDevice dev;
@@ -34,6 +35,15 @@
     uint8_t apms;
     QEMUTimer *tmr_timer;
     int64_t tmr_overflow_time;
+    i2c_bus *smbus;
+    uint8_t smb_stat;
+    uint8_t smb_ctl;
+    uint8_t smb_cmd;
+    uint8_t smb_addr;
+    uint8_t smb_data0;
+    uint8_t smb_data1;
+    uint8_t smb_data[32];
+    uint8_t smb_index;
 } PIIX4PMState;
 
 #define RTC_EN (1 << 10)
@@ -45,6 +55,14 @@
 
 #define SUS_EN (1 << 13)
 
+#define SMBHSTSTS 0x00
+#define SMBHSTCNT 0x02
+#define SMBHSTCMD 0x03
+#define SMBHSTADD 0x04
+#define SMBHSTDAT0 0x05
+#define SMBHSTDAT1 0x06
+#define SMBBLKDAT 0x07
+
 static uint32_t get_pmtmr(PIIX4PMState *s)
 {
     uint32_t d;
@@ -71,7 +89,7 @@
     pmsts = get_pmsts(s);
     sci_level = (((pmsts & s->pmen) & 
                   (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
-    pci_set_irq(&s->dev, 0, sci_level);
+    qemu_set_irq(s->dev.irq[0], sci_level);
     /* schedule a timer interruption if needed */
     if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
         expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
@@ -231,6 +249,141 @@
 #endif
 }
 
+static void smb_transaction(PIIX4PMState *s)
+{
+    uint8_t prot = (s->smb_ctl >> 2) & 0x07;
+    uint8_t read = s->smb_addr & 0x01;
+    uint8_t cmd = s->smb_cmd;
+    uint8_t addr = s->smb_addr >> 1;
+    i2c_bus *bus = s->smbus;
+
+#ifdef DEBUG
+    printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+#endif
+    switch(prot) {
+    case 0x0:
+        smbus_quick_command(bus, addr, read);
+        break;
+    case 0x1:
+        if (read) {
+            s->smb_data0 = smbus_receive_byte(bus, addr);
+        } else {
+            smbus_send_byte(bus, addr, cmd);
+        }
+        break;
+    case 0x2:
+        if (read) {
+            s->smb_data0 = smbus_read_byte(bus, addr, cmd);
+        } else {
+            smbus_write_byte(bus, addr, cmd, s->smb_data0);
+        }
+        break;
+    case 0x3:
+        if (read) {
+            uint16_t val;
+            smbus_read_word(bus, addr, cmd);
+            s->smb_data0 = val;
+            s->smb_data1 = val >> 8;
+        } else {
+            smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
+        }
+        break;
+    case 0x5:
+        if (read) {
+            s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
+        } else {
+            smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
+        }
+        break;
+    default:
+        goto error;
+    }
+    return;
+
+  error:
+    s->smb_stat |= 0x04;
+}
+
+static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PIIX4PMState *s = opaque;
+    addr &= 0x3f;
+#ifdef DEBUG
+    printf("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    switch(addr) {
+    case SMBHSTSTS:
+        s->smb_stat = 0;
+        s->smb_index = 0;
+        break;
+    case SMBHSTCNT:
+        s->smb_ctl = val;
+        if (val & 0x40)
+            smb_transaction(s);
+        break;
+    case SMBHSTCMD:
+        s->smb_cmd = val;
+        break;
+    case SMBHSTADD:
+        s->smb_addr = val;
+        break;
+    case SMBHSTDAT0:
+        s->smb_data0 = val;
+        break;
+    case SMBHSTDAT1:
+        s->smb_data1 = val;
+        break;
+    case SMBBLKDAT:
+        s->smb_data[s->smb_index++] = val;
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+    PIIX4PMState *s = opaque;
+    uint32_t val;
+
+    addr &= 0x3f;
+    switch(addr) {
+    case SMBHSTSTS:
+        val = s->smb_stat;
+        break;
+    case SMBHSTCNT:
+        s->smb_index = 0;
+        val = s->smb_ctl & 0x1f;
+        break;
+    case SMBHSTCMD:
+        val = s->smb_cmd;
+        break;
+    case SMBHSTADD:
+        val = s->smb_addr;
+        break;
+    case SMBHSTDAT0:
+        val = s->smb_data0;
+        break;
+    case SMBHSTDAT1:
+        val = s->smb_data1;
+        break;
+    case SMBBLKDAT:
+        val = s->smb_data[s->smb_index++];
+        if (s->smb_index > 31)
+            s->smb_index = 0;
+        break;
+    default:
+        val = 0;
+        break;
+    }
+#ifdef DEBUG
+    printf("SMB readb port=0x%04x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
 static void pm_io_space_update(PIIX4PMState *s)
 {
     uint32_t pm_io_base;
@@ -298,10 +451,11 @@
     return 0;
 }
 
-void piix4_pm_init(PCIBus *bus, int devfn)
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn)
 {
     PIIX4PMState *s;
     uint8_t *pci_conf;
+    uint32_t smb_io_base;
 
     s = (PIIX4PMState *)pci_register_device(bus,
                                          "PM", sizeof(PIIX4PMState),
@@ -332,7 +486,17 @@
     pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
 	(serial_hds[1] != NULL ? 0x90 : 0);
 
+    smb_io_base = SMB_IO_BASE;
+    pci_conf[0x90] = smb_io_base | 1;
+    pci_conf[0x91] = smb_io_base >> 8;
+    pci_conf[0xd2] = 0x09;
+    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
+    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
+
     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
 
     register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
+
+    s->smbus = i2c_init_bus();
+    return s->smbus;
 }

Modified: trunk/src/host/qemu-neo1973/hw/adlib.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/adlib.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/adlib.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -267,7 +267,7 @@
     AUD_remove_card (&s->card);
 }
 
-int Adlib_init (AudioState *audio)
+int Adlib_init (AudioState *audio, qemu_irq *pic)
 {
     AdlibState *s = &glob_adlib;
     audsettings_t as;

Modified: trunk/src/host/qemu-neo1973/hw/ads7846.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -4,14 +4,13 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include <vl.h>
 
 struct ads7846_state_s {
-    void (*interrupt)(void *opaque, int level);
-    void *opaque;
+    qemu_irq interrupt;
 
     int input[8];
     int pressure;
@@ -48,7 +47,7 @@
 static void ads7846_int_update(struct ads7846_state_s *s)
 {
     if (s->interrupt)
-        s->interrupt(s->opaque, s->pressure == 0);
+        qemu_set_irq(s->interrupt, s->pressure == 0);
 }
 
 uint32_t ads7846_read(void *opaque)
@@ -101,13 +100,15 @@
         s->input[4] = ADS_Z2POS(x, y);
         s->input[5] = ADS_XPOS(x, y);
     }
-    s->pressure = !!buttons_state;
 
-    ads7846_int_update(s);
+    if (s->pressure == !buttons_state) {
+        s->pressure = !!buttons_state;
+
+         ads7846_int_update(s);
+    }
 }
 
-struct ads7846_state_s *ads7846_init(
-                void (*penirq)(void *opaque, int level), void *opaque)
+struct ads7846_state_s *ads7846_init(qemu_irq penirq)
 {
     struct ads7846_state_s *s;
     s = (struct ads7846_state_s *)
@@ -115,7 +116,6 @@
     memset(s, 0, sizeof(struct ads7846_state_s));
 
     s->interrupt = penirq;
-    s->opaque = opaque;
 
     s->input[0] = ADS_TEMP0;	/* TEMP0 */
     s->input[2] = ADS_VBAT;	/* VBAT */

Added: trunk/src/host/qemu-neo1973/hw/alpha_palcode.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/alpha_palcode.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1099 @@
+/*
+ *  Alpha emulation - PALcode emulation for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "qemu.h"
+#include "cpu.h"
+#include "exec-all.h"
+
+#if !defined (CONFIG_USER_ONLY)
+/* Shared handlers */
+static void pal_reset (CPUState *env);
+/* Console handlers */
+static void pal_console_call (CPUState *env, uint32_t palcode);
+/* OpenVMS handlers */
+static void pal_openvms_call (CPUState *env, uint32_t palcode);
+/* UNIX / Linux handlers */
+static void pal_unix_call (CPUState *env, uint32_t palcode);
+
+pal_handler_t pal_handlers[] = {
+    /* Console handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_console_call,
+    },
+    /* OpenVMS handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_openvms_call,
+    },
+    /* UNIX / Linux handler */
+    {
+        .reset = &pal_reset,
+        .call_pal = &pal_unix_call,
+    },
+};
+
+#if 0
+/* One must explicitely check that the TB is valid and the FOE bit is reset */
+static void update_itb ()
+{
+    /* This writes into a temp register, not the actual one */
+    mtpr(TB_TAG);
+    mtpr(TB_CTL);
+    /* This commits the TB update */
+    mtpr(ITB_PTE); 
+}
+
+static void update_dtb ();
+{
+    mtpr(TB_CTL);
+    /* This write into a temp register, not the actual one */
+    mtpr(TB_TAG);
+    /* This commits the TB update */
+    mtpr(DTB_PTE);
+}
+#endif
+
+static void pal_reset (CPUState *env)
+{
+}
+
+static void do_swappal (CPUState *env, uint64_t palid)
+{
+    pal_handler_t *pal_handler;
+    int status;
+
+    status = 0;
+    switch (palid) {
+    case 0 ... 2:
+        pal_handler = &pal_handlers[palid];
+        env->pal_handler = pal_handler;
+        env->ipr[IPR_PAL_BASE] = -1ULL;
+        (*pal_handler->reset)(env);
+        break;
+    case 3 ... 255:
+        /* Unknown identifier */
+        env->ir[0] = 1;
+        return;
+    default:
+        /* We were given the entry point address */
+        env->pal_handler = NULL;
+        env->ipr[IPR_PAL_BASE] = palid;
+        env->pc = env->ipr[IPR_PAL_BASE];
+        cpu_loop_exit();
+    }
+}
+
+static void pal_console_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x0000009E:
+        /* RDUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    default:
+        break;
+    }
+}
+
+static void pal_openvms_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid, val, oldval;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000003:
+        /* LDQP */
+        break;
+    case 0x00000004:
+        /* STQP */
+        break;
+    case 0x00000005:
+        /* SWPCTX */
+        break;
+    case 0x00000006:
+        /* MFPR_ASN */
+        if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000007:
+        /* MTPR_ASTEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000008:
+        /* MTPR_ASTSR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x0000000B:
+        /* MFPR_FEN */
+        if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000000C:
+        /* MTPR_FEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000000D:
+        /* MTPR_IPIR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000000E:
+        /* MFPR_IPL */
+        if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000000F:
+        /* MTPR_IPL */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000010:
+        /* MFPR_MCES */
+        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000011:
+        /* MTPR_MCES */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000012:
+        /* MFPR_PCBB */
+        if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000013:
+        /* MFPR_PRBR */
+        if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000014:
+        /* MTPR_PRBR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000015:
+        /* MFPR_PTBR */
+        if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000016:
+        /* MFPR_SCBB */
+        if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000017:
+        /* MTPR_SCBB */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000018:
+        /* MTPR_SIRR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000019:
+        /* MFPR_SISR */
+        if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001A:
+        /* MFPR_TBCHK */
+        if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001B:
+        /* MTPR_TBIA */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001C:
+        /* MTPR_TBIAP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001D:
+        /* MTPR_TBIS */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000001E:
+        /* MFPR_ESP */
+        if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000001F:
+        /* MTPR_ESP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000020:
+        /* MFPR_SSP */
+        if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000021:
+        /* MTPR_SSP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000022:
+        /* MFPR_USP */
+        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000023:
+        /* MTPR_USP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000024:
+        /* MTPR_TBISD */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000025:
+        /* MTPR_TBISI */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000026:
+        /* MFPR_ASTEN */
+        if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000027:
+        /* MFPR_ASTSR */
+        if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000029:
+        /* MFPR_VPTB */
+        if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000002A:
+        /* MTPR_VPTB */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002B:
+        /* MTPR_PERFMON */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002E:
+        /* MTPR_DATFX */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000003E:
+        /* WTINT */
+        break;
+    case 0x0000003F:
+        /* MFPR_WHAMI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000082:
+        /* CHME */
+        break;
+    case 0x00000083:
+        /* CHMK */
+        break;
+    case 0x00000084:
+        /* CHMS */
+        break;
+    case 0x00000085:
+        /* CHMU */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000087:
+        /* INSQHIL */
+        break;
+    case 0x00000088:
+        /* INSQTIL */
+        break;
+    case 0x00000089:
+        /* INSQHIQ */
+        break;
+    case 0x0000008A:
+        /* INSQTIQ */
+        break;
+    case 0x0000008B:
+        /* INSQUEL */
+        break;
+    case 0x0000008C:
+        /* INSQUEQ */
+        break;
+    case 0x0000008D:
+        /* INSQUEL/D */
+        break;
+    case 0x0000008E:
+        /* INSQUEQ/D */
+        break;
+    case 0x0000008F:
+        /* PROBER */
+        break;
+    case 0x00000090:
+        /* PROBEW */
+        break;
+    case 0x00000091:
+        /* RD_PS */
+        break;
+    case 0x00000092:
+        /* REI */
+        break;
+    case 0x00000093:
+        /* REMQHIL */
+        break;
+    case 0x00000094:
+        /* REMQTIL */
+        break;
+    case 0x00000095:
+        /* REMQHIQ */
+        break;
+    case 0x00000096:
+        /* REMQTIQ */
+        break;
+    case 0x00000097:
+        /* REMQUEL */
+        break;
+    case 0x00000098:
+        /* REMQUEQ */
+        break;
+    case 0x00000099:
+        /* REMQUEL/D */
+        break;
+    case 0x0000009A:
+        /* REMQUEQ/D */
+        break;
+    case 0x0000009B:
+        /* SWASTEN */
+        break;
+    case 0x0000009C:
+        /* WR_PS_SW */
+        break;
+    case 0x0000009D:
+        /* RSCC */
+        break;
+    case 0x0000009E:
+        /* READ_UNQ */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRITE_UNQ */
+        /* REQUIRED */
+        break;
+    case 0x000000A0:
+        /* AMOVRR */
+        break;
+    case 0x000000A1:
+        /* AMOVRM */
+        break;
+    case 0x000000A2:
+        /* INSQHILR */
+        break;
+    case 0x000000A3:
+        /* INSQTILR */
+        break;
+    case 0x000000A4:
+        /* INSQHIQR */
+        break;
+    case 0x000000A5:
+        /* INSQTIQR */
+        break;
+    case 0x000000A6:
+        /* REMQHILR */
+        break;
+    case 0x000000A7:
+        /* REMQTILR */
+        break;
+    case 0x000000A8:
+        /* REMQHIQR */
+        break;
+    case 0x000000A9:
+        /* REMQTIQR */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    case 0x000000AE:
+        /* CLRFEN */
+        break;
+    default:
+        break;
+    }
+}
+
+static void pal_unix_call (CPUState *env, uint32_t palcode)
+{
+    uint64_t palid, val, oldval;
+
+    if (palcode < 0x00000080) {
+        /* Privileged palcodes */
+        if (!(env->ps >> 3)) {
+            /* TODO: generate privilege exception */
+        }
+    }
+    switch (palcode) {
+    case 0x00000000:
+        /* HALT */
+        /* REQUIRED */
+        break;
+    case 0x00000001:
+        /* CFLUSH */
+        break;
+    case 0x00000002:
+        /* DRAINA */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000009:
+        /* CSERVE */
+        /* REQUIRED */
+        break;
+    case 0x0000000A:
+        /* SWPPAL */
+        /* REQUIRED */
+        palid = env->ir[16];
+        do_swappal(env, palid);
+        break;
+    case 0x0000000D:
+        /* WRIPIR */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000010:
+        /* RDMCES */
+        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000011:
+        /* WRMCES */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002B:
+        /* WRFEN */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000002D:
+        /* WRVPTPTR */
+        break;
+    case 0x00000030:
+        /* SWPCTX */
+        break;
+    case 0x00000031:
+        /* WRVAL */
+        break;
+    case 0x00000032:
+        /* RDVAL */
+        break;
+    case 0x00000033:
+        /* TBI */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000034:
+        /* WRENT */
+        break;
+    case 0x00000035:
+        /* SWPIPL */
+        break;
+    case 0x00000036:
+        /* RDPS */
+        break;
+    case 0x00000037:
+        /* WRKGP */
+        break;
+    case 0x00000038:
+        /* WRUSP */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x00000039:
+        /* WRPERFMON */
+        val = env->ir[16];
+        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
+            env->ir[0] = val;
+        break;
+    case 0x0000003A:
+        /* RDUSP */
+        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000003C:
+        /* WHAMI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x0000003D:
+        /* RETSYS */
+        break;
+    case 0x0000003E:
+        /* WTINT */
+        break;
+    case 0x0000003F:
+        /* RTI */
+        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
+            env->ir[0] = val;
+        break;
+    case 0x00000080:
+        /* BPT */
+        /* REQUIRED */
+        break;
+    case 0x00000081:
+        /* BUGCHK */
+        /* REQUIRED */
+        break;
+    case 0x00000083:
+        /* CALLSYS */
+        break;
+    case 0x00000086:
+        /* IMB */
+        /* REQUIRED */
+        /* Implemented as no-op */
+        break;
+    case 0x00000092:
+        /* URTI */
+        break;
+    case 0x0000009E:
+        /* RDUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x0000009F:
+        /* WRUNIQUE */
+        /* REQUIRED */
+        break;
+    case 0x000000AA:
+        /* GENTRAP */
+        /* REQUIRED */
+        break;
+    case 0x000000AE:
+        /* CLRFEN */
+        break;
+    default:
+        break;
+    }
+}
+
+void call_pal (CPUState *env)
+{
+    pal_handler_t *pal_handler = env->pal_handler;
+
+    switch (env->exception_index) {
+    case EXCP_RESET:
+        (*pal_handler->reset)(env);
+        break;
+    case EXCP_MCHK:
+        (*pal_handler->machine_check)(env);
+        break;
+    case EXCP_ARITH:
+        (*pal_handler->arithmetic)(env);
+        break;
+    case EXCP_INTERRUPT:
+        (*pal_handler->interrupt)(env);
+        break;
+    case EXCP_DFAULT:
+        (*pal_handler->dfault)(env);
+        break;
+    case EXCP_DTB_MISS_PAL:
+        (*pal_handler->dtb_miss_pal)(env);
+        break;
+    case EXCP_DTB_MISS_NATIVE:
+        (*pal_handler->dtb_miss_native)(env);
+        break;
+    case EXCP_UNALIGN:
+        (*pal_handler->unalign)(env);
+        break;
+    case EXCP_ITB_MISS:
+        (*pal_handler->itb_miss)(env);
+        break;
+    case EXCP_ITB_ACV:
+        (*pal_handler->itb_acv)(env);
+        break;
+    case EXCP_OPCDEC:
+        (*pal_handler->opcdec)(env);
+        break;
+    case EXCP_FEN:
+        (*pal_handler->fen)(env);
+        break;
+    default:
+        if (env->exception_index >= EXCP_CALL_PAL &&
+            env->exception_index < EXCP_CALL_PALP) {
+            /* Unprivileged PAL call */
+            (*pal_handler->call_pal)
+                (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
+        } else if (env->exception_index >= EXCP_CALL_PALP &&
+                   env->exception_index < EXCP_CALL_PALE) {
+            /* Privileged PAL call */
+            (*pal_handler->call_pal)
+                (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
+        } else {
+            /* Should never happen */
+        }
+        break;
+    }
+    env->ipr[IPR_EXC_ADDR] &= ~1;
+}
+
+void pal_init (CPUState *env)
+{
+    do_swappal(env, 0);
+}
+
+#if 0
+static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
+{
+    uint64_t virbnd, ptbr;
+
+    if ((env->features & FEATURE_VIRBND)) {
+        cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
+        if (vaddr >= virbnd)
+            cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
+        else
+            cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
+    } else {
+        cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
+    }
+
+    return ptbr;
+}
+
+static int get_page_bits (CPUState *env)
+{
+    /* XXX */
+    return 13;
+}
+
+static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
+                    uint64_t ptebase, int page_bits, uint64_t level,
+                    int is_user, int rw)
+{
+    uint64_t pteaddr, pte, pfn;
+    uint8_t gh;
+    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar;
+
+    pteaddr = (ptebase << page_bits) + (8 * level);
+    pte = ldq_raw(pteaddr);
+    /* Decode all interresting PTE fields */
+    pfn = pte >> 32;
+    uwe = (pte >> 13) & 1;
+    kwe = (pte >> 12) & 1;
+    ure = (pte >> 9) & 1;
+    kre = (pte >> 8) & 1;
+    gh = (pte >> 5) & 3;
+    foE = (pte >> 3) & 1;
+    foW = (pte >> 2) & 1;
+    foR = (pte >> 1) & 1;
+    v = pte & 1;
+    ret = 0;
+    if (!v)
+        ret = 0x1;
+    /* Check access rights */
+    ar = 0;
+    if (is_user) {
+        if (ure)
+            ar |= PAGE_READ;
+        if (uwe)
+            ar |= PAGE_WRITE;
+        if (rw == 1 && !uwe)
+            ret |= 0x2;
+        if (rw != 1 && !ure)
+            ret |= 0x2;
+    } else {
+        if (kre)
+            ar |= PAGE_READ;
+        if (kwe)
+            ar |= PAGE_WRITE;
+        if (rw == 1 && !kwe)
+            ret |= 0x2;
+        if (rw != 1 && !kre)
+            ret |= 0x2;
+    }
+    if (rw == 0 && foR)
+        ret |= 0x4;
+    if (rw == 2 && foE)
+        ret |= 0x8;
+    if (rw == 1 && foW)
+        ret |= 0xC;
+    *pfnp = pfn;
+    if (zbitsp != NULL)
+        *zbitsp = page_bits + (3 * gh);
+    if (protp != NULL)
+        *protp = ar;
+
+    return ret;
+}
+
+static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
+                           uint64_t ptebase, int page_bits,
+                           uint64_t vaddr, int is_user, int rw)
+{
+    uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
+    int lvl_bits, ret;
+
+    page_mask = (1ULL << page_bits) - 1ULL;
+    lvl_bits = page_bits - 3;
+    lvl_mask = (1ULL << lvl_bits) - 1ULL;
+    level3 = (vaddr >> page_bits) & lvl_mask;
+    level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
+    level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
+    /* Level 1 PTE */
+    ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
+    switch (ret) {
+    case 3:
+        /* Access violation */
+        return 2;
+    case 2:
+        /* translation not valid */
+        return 1;
+    default:
+        /* OK */
+        break;
+    }
+    /* Level 2 PTE */
+    ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
+    switch (ret) {
+    case 3:
+        /* Access violation */
+        return 2;
+    case 2:
+        /* translation not valid */
+        return 1;
+    default:
+        /* OK */
+        break;
+    }
+    /* Level 3 PTE */
+    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
+    if (ret & 0x1) {
+        /* Translation not valid */
+        ret = 1;
+    } else if (ret & 2) {
+        /* Access violation */
+        ret = 2;
+    } else {
+        switch (ret & 0xC) {
+        case 0:
+            /* OK */
+            ret = 0;
+            break;
+        case 0x4:
+            /* Fault on read */
+            ret = 3;
+            break;
+        case 0x8:
+            /* Fault on execute */
+            ret = 4;
+            break;
+        case 0xC:
+            /* Fault on write */
+            ret = 5;
+            break;
+        }
+    }
+    *paddr = (pfn << page_bits) | (vaddr & page_mask);
+    
+    return 0;
+}
+
+static int virtual_to_physical (CPUState *env, uint64_t *physp,
+                                int *zbitsp, int *protp,
+                                uint64_t virtual, int is_user, int rw)
+{
+    uint64_t sva, ptebase;
+    int seg, page_bits, ret;
+
+    sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
+    if (sva != virtual)
+        seg = -1;
+    else
+        seg = sva >> (VA_BITS - 2);
+    virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
+    ptebase = get_ptebase(env, virtual);
+    page_bits = get_page_bits(env);
+    ret = 0;
+    switch (seg) {
+    case 0:
+        /* seg1: 3 levels of PTE */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    case 1:
+        /* seg1: 2 levels of PTE */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    case 2:
+        /* kernel segment */
+        if (is_user) {
+            ret = 2;
+        } else {
+            *physp = virtual;
+        }
+        break;
+    case 3:
+        /* seg1: TB mapped */
+        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
+                             virtual, is_user, rw);
+        break;
+    default:
+        ret = 1;
+        break;
+    }
+
+    return ret;
+}
+
+/* XXX: code provision */
+int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+                              int is_user, int is_softmmu)
+{
+    uint64_t physical, page_size, end;
+    int prot, zbits, ret;
+
+    if (env->user_mode_only) {
+        ret = 2;
+    } else { 
+        ret = virtual_to_physical(env, &physical, &zbits, &prot,
+                                  address, is_user, rw);
+    }
+    switch (ret) {
+    case 0:
+        /* No fault */
+        page_size = 1ULL << zbits;
+        address &= ~(page_size - 1);
+        for (end = physical + page_size; physical < end; physical += 0x1000) {
+            ret = tlb_set_page(env, address, physical, prot,
+                               is_user, is_softmmu);
+            address += 0x1000;
+        }
+        break;
+#if 0
+    case 1:
+        env->exception_index = EXCP_DFAULT;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 2:
+        env->exception_index = EXCP_ACCESS_VIOLATION;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 3:
+        env->exception_index = EXCP_FAULT_ON_READ;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    case 4:
+        env->exception_index = EXCP_FAULT_ON_EXECUTE;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+    case 5:
+        env->exception_index = EXCP_FAULT_ON_WRITE;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+#endif
+    default:
+        /* Should never happen */
+        env->exception_index = EXCP_MCHK;
+        env->ipr[IPR_EXC_ADDR] = address;
+        ret = 1;
+        break;
+    }
+
+    return ret;
+}
+#endif
+
+#else /* !defined (CONFIG_USER_ONLY) */
+void pal_init (CPUState *env)
+{
+}
+
+void call_pal (CPUState *env, int palcode)
+{
+    target_ulong ret;
+
+    printf("%s: palcode %02x\n", __func__, palcode);
+    if (logfile != NULL)
+        fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
+    switch (palcode) {
+    case 0x83:
+        /* CALLSYS */
+        printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+        if (logfile != NULL)
+            fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
+                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
+                         env->ir[IR_A5]);
+        env->ir[IR_A3] = ret;
+        if (ret > (target_ulong)(-515)) {
+            env->ir[IR_V0] = 1;
+        } else {
+            env->ir[IR_V0] = 0;
+        }
+        break;
+    case 0x9E:
+        /* RDUNIQUE */
+        env->ir[IR_V0] = env->unique;
+        printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+        break;
+    case 0x9F:
+        /* WRUNIQUE */
+        env->unique = env->ir[IR_A0];
+        printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
+        break;
+    default:
+        printf("%s: unhandled palcode %02x\n", __func__, palcode);
+        if (logfile != NULL)
+            fprintf(logfile, "%s: unhandled palcode %02x\n",
+                    __func__, palcode);
+        exit(1);
+    }
+}
+#endif

Modified: trunk/src/host/qemu-neo1973/hw/apb_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/apb_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -200,14 +200,14 @@
     return bus_offset + irq_num;
 }
 
-static void pci_apb_set_irq(void *pic, int irq_num, int level)
+static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
 {
     /* PCI IRQ map onto the first 32 INO.  */
-    pic_set_irq_new(pic, irq_num, level);
+    qemu_set_irq(pic[irq_num], level);
 }
 
 PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
-                     void *pic)
+                     qemu_irq *pic)
 {
     APBState *s;
     PCIDevice *d;

Modified: trunk/src/host/qemu-neo1973/hw/apic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/apic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/apic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -816,6 +816,7 @@
     env->apic_state = s;
     apic_init_ipi(s);
     s->id = last_apic_id++;
+    env->cpuid_apic_id = s->id;
     s->cpu_env = env;
     s->apicbase = 0xfee00000 | 
         (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE;
@@ -831,7 +832,7 @@
     }
     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
 
-    register_savevm("apic", 0, 1, apic_save, apic_load, s);
+    register_savevm("apic", 0, 2, apic_save, apic_load, s);
     qemu_register_reset(apic_reset, s);
     
     local_apics[s->id] = s;

Modified: trunk/src/host/qemu-neo1973/hw/arm_boot.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_boot.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_boot.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -24,8 +24,20 @@
   0  /* Kernel entry point.  Set by integratorcp_init.  */
 };
 
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+    if (env->kernel_filename)
+        arm_load_kernel(env, env->ram_size, env->kernel_filename, 
+                        env->kernel_cmdline, env->initrd_filename, 
+                        env->board_id, env->loader_start);
+}
+
 static void set_kernel_args(uint32_t ram_size, int initrd_size,
-                            const char *kernel_cmdline)
+                            const char *kernel_cmdline,
+                            target_phys_addr_t loader_start)
 {
     uint32_t *p;
 
@@ -40,12 +52,12 @@
     stl_raw(p++, 4);
     stl_raw(p++, 0x54410002);
     stl_raw(p++, ram_size);
-    stl_raw(p++, 0);
+    stl_raw(p++, loader_start);
     if (initrd_size) {
         /* ATAG_INITRD2 */
         stl_raw(p++, 4);
         stl_raw(p++, 0x54420005);
-        stl_raw(p++, INITRD_LOAD_ADDR);
+        stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
         stl_raw(p++, initrd_size);
     }
     if (kernel_cmdline && *kernel_cmdline) {
@@ -64,42 +76,70 @@
     stl_raw(p++, 0);
 }
 
-void arm_load_kernel(int ram_size, const char *kernel_filename,
+void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
                      const char *kernel_cmdline, const char *initrd_filename,
                      int board_id, target_phys_addr_t loader_start)
 {
     int kernel_size;
     int initrd_size;
     int n;
+    int is_linux = 0;
+    uint64_t elf_entry;
+    target_ulong entry;
 
     /* Load the kernel.  */
     if (!kernel_filename) {
         fprintf(stderr, "Kernel image must be specified\n");
         exit(1);
     }
-    kernel_size = load_image(kernel_filename,
-                             phys_ram_base + KERNEL_LOAD_ADDR + S3C_SRAM_SIZE);////
+
+    if (!env->kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        env->board_id = board_id;
+        env->loader_start = loader_start;
+        qemu_register_reset(main_cpu_reset, env);
+    }
+    /* Assume that raw images are linux kernels, and ELF images are not.  */
+    kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+    entry = elf_entry;
     if (kernel_size < 0) {
+        kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
+    }
+    if (kernel_size < 0) {
+        kernel_size = load_image(kernel_filename,
+                                 phys_ram_base + KERNEL_LOAD_ADDR);
+        entry = loader_start + KERNEL_LOAD_ADDR;
+        is_linux = 1;
+    }
+    if (kernel_size < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
         exit(1);
     }
-    if (initrd_filename) {
-        initrd_size = load_image(initrd_filename,
-                                 phys_ram_base + INITRD_LOAD_ADDR);
-        if (initrd_size < 0) {
-            fprintf(stderr, "qemu: could not load initrd '%s'\n",
-                    initrd_filename);
-            exit(1);
+    if (!is_linux) {
+        /* Jump to the entry point.  */
+        env->regs[15] = entry & 0xfffffffe;
+        env->thumb = entry & 1;
+    } else {
+        if (initrd_filename) {
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + INITRD_LOAD_ADDR);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initrd '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_size = 0;
         }
-    } else {
-        initrd_size = 0;
+        bootloader[1] |= board_id & 0xff;
+        bootloader[2] |= (board_id >> 8) & 0xff;
+        bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
+        bootloader[6] = entry;
+        for (n = 0; n < sizeof(bootloader) / 4; n++)
+            stl_raw(phys_ram_base + (n * 4), bootloader[n]);
+        set_kernel_args(ram_size, initrd_size, kernel_cmdline, loader_start);
     }
-    bootloader[1] |= board_id & 0xff;
-    bootloader[2] |= (board_id >> 8) & 0xff;
-    bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
-    bootloader[6] = loader_start + KERNEL_LOAD_ADDR;
-    for (n = 0; n < sizeof(bootloader) / 4; n++)
-        stl_raw(phys_ram_base + (n * 4), bootloader[n]);
-    set_kernel_args(ram_size, initrd_size, kernel_cmdline);
 }
-

Modified: trunk/src/host/qemu-neo1973/hw/arm_gic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_gic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_gic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -60,10 +60,8 @@
 
 typedef struct gic_state
 {
-    arm_pic_handler handler;
     uint32_t base;
-    void *parent;
-    int parent_irq;
+    qemu_irq parent_irq;
     int enabled;
     int cpu_enabled;
 
@@ -88,7 +86,7 @@
 
     s->current_pending = 1023;
     if (!s->enabled || !s->cpu_enabled) {
-        pic_set_irq_new(s->parent, s->parent_irq, 0);
+        qemu_irq_lower(s->parent_irq);
         return;
     }
     best_prio = 0x100;
@@ -102,12 +100,12 @@
         }
     }
     if (best_prio > s->priority_mask) {
-        pic_set_irq_new(s->parent, s->parent_irq, 0);
+        qemu_irq_lower(s->parent_irq);
     } else {
         s->current_pending = best_irq;
         if (best_prio < s->running_priority) {
             DPRINTF("Raised pending IRQ %d\n", best_irq);
-            pic_set_irq_new(s->parent, s->parent_irq, 1);
+            qemu_irq_raise(s->parent_irq);
         }
     }
 }
@@ -150,7 +148,7 @@
         DPRINTF("ACK no pending IRQ\n");
         return 1023;
     }
-    pic_set_irq_new(s->parent, s->parent_irq, 0);
+    qemu_irq_lower(s->parent_irq);
     s->last_active[new_irq] = s->running_irq;
     /* For level triggered interrupts we clear the pending bit while
        the interrupt is active.  */
@@ -520,16 +518,16 @@
     s->cpu_enabled = 0;
 }
 
-void *arm_gic_init(uint32_t base, void *parent, int parent_irq)
+qemu_irq *arm_gic_init(uint32_t base, qemu_irq parent_irq)
 {
     gic_state *s;
+    qemu_irq *qi;
     int iomemtype;
 
     s = (gic_state *)qemu_mallocz(sizeof(gic_state));
     if (!s)
         return NULL;
-    s->handler = gic_set_irq;
-    s->parent = parent;
+    qi = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ);
     s->parent_irq = parent_irq;
     if (base != 0xffffffff) {
         iomemtype = cpu_register_io_memory(0, gic_cpu_readfn,
@@ -543,5 +541,5 @@
         s->base = 0;
     }
     gic_reset(s);
-    return s;
+    return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/arm_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_pic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_pic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -11,11 +11,6 @@
 #include "arm_pic.h"
 
 /* Stub functions for hardware that doesn't exist.  */
-void pic_set_irq(int irq, int level)
-{
-    cpu_abort(cpu_single_env, "pic_set_irq");
-}
-
 void pic_info(void)
 {
 }
@@ -25,49 +20,29 @@
 }
 
 
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
-    arm_pic_handler *p = (arm_pic_handler *)opaque;
-    /* Call the real handler.  */
-    (*p)(opaque, irq, level);
-}
-
-/* Model the IRQ/FIQ CPU interrupt lines as a two input interrupt controller.
-   Input 0 is IRQ and input 1 is FIQ.  */
-typedef struct
-{
-    arm_pic_handler handler;
-    CPUState *cpu_env;
-} arm_pic_cpu_state;
-
+/* Input 0 is IRQ and input 1 is FIQ.  */
 static void arm_pic_cpu_handler(void *opaque, int irq, int level)
 {
-    arm_pic_cpu_state *s = (arm_pic_cpu_state *)opaque;
+    CPUState *env = (CPUState *)opaque;
     switch (irq) {
     case ARM_PIC_CPU_IRQ:
         if (level)
-            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
         else
-            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
         break;
     case ARM_PIC_CPU_FIQ:
         if (level)
-            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+            cpu_interrupt(env, CPU_INTERRUPT_FIQ);
         else
-            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
+            cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
         break;
     default:
-        cpu_abort(s->cpu_env, "arm_pic_cpu_handler: Bad interrput line %d\n",
-                  irq);
+        cpu_abort(env, "arm_pic_cpu_handler: Bad interrput line %d\n", irq);
     }
 }
 
-void *arm_pic_init_cpu(CPUState *env)
+qemu_irq *arm_pic_init_cpu(CPUState *env)
 {
-    arm_pic_cpu_state *s;
-    
-    s = (arm_pic_cpu_state *)malloc(sizeof(arm_pic_cpu_state));
-    s->handler = arm_pic_cpu_handler;
-    s->cpu_env = env;
-    return s;
+    return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2);
 }

Modified: trunk/src/host/qemu-neo1973/hw/arm_pic.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_pic.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_pic.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,14 +14,10 @@
 #ifndef ARM_INTERRUPT_H
 #define ARM_INTERRUPT_H 1
 
-/* The first element of an individual PIC state structures should
-   be a pointer to the handler routine.  */
-typedef void (*arm_pic_handler)(void *opaque, int irq, int level);
-
 /* The CPU is also modeled as an interrupt controller.  */
 #define ARM_PIC_CPU_IRQ 0
 #define ARM_PIC_CPU_FIQ 1
-void *arm_pic_init_cpu(CPUState *env);
+qemu_irq *arm_pic_init_cpu(CPUState *env);
 
 #endif /* !ARM_INTERRUPT_H */
 

Modified: trunk/src/host/qemu-neo1973/hw/arm_sysctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_sysctl.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_sysctl.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -149,7 +149,7 @@
         if (s->lockval == LOCK_VALUE) {
             s->resetlevel = val;
             if (val & 0x100)
-                cpu_abort(cpu_single_env, "Board reset\n");
+                qemu_system_reset_request ();
         }
         break;
     case 0x44: /* PCICTL */

Modified: trunk/src/host/qemu-neo1973/hw/arm_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/arm_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/arm_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,8 +32,7 @@
     int raw_freq;
     int freq;
     int int_level;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } arm_timer_state;
 
 /* Calculate the new expiry time of the given timer.  */
@@ -85,9 +84,9 @@
     }
     /* Update interrupts.  */
     if (s->int_level && (s->control & TIMER_CTRL_IE)) {
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_raise(s->irq);
     } else {
-        pic_set_irq_new(s->pic, s->irq, 0);
+        qemu_irq_lower(s->irq);
     }
 
     next = now;
@@ -215,12 +214,11 @@
     arm_timer_update((arm_timer_state *)opaque, now);
 }
 
-static void *arm_timer_init(uint32_t freq, void *pic, int irq)
+static void *arm_timer_init(uint32_t freq, qemu_irq irq)
 {
     arm_timer_state *s;
 
     s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
-    s->pic = pic;
     s->irq = irq;
     s->raw_freq = s->freq = 1000000;
     s->control = TIMER_CTRL_IE;
@@ -233,26 +231,23 @@
 
 /* ARM PrimeCell SP804 dual timer module.
    Docs for this device don't seem to be publicly available.  This
-   implementation is based on gueswork, the linux kernel sources and the
+   implementation is based on guesswork, the linux kernel sources and the
    Integrator/CP timer modules.  */
 
 typedef struct {
-    /* Include a pseudo-PIC device to merge the two interrupt sources.  */
-    arm_pic_handler handler;
     void *timer[2];
     int level[2];
     uint32_t base;
-    /* The output PIC device.  */
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } sp804_state;
 
+/* Merge the IRQs from the two component devices.  */
 static void sp804_set_irq(void *opaque, int irq, int level)
 {
     sp804_state *s = (sp804_state *)opaque;
 
     s->level[irq] = level;
-    pic_set_irq_new(s->pic, s->irq, s->level[0] || s->level[1]);
+    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
 }
 
 static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
@@ -293,20 +288,20 @@
    sp804_write
 };
 
-void sp804_init(uint32_t base, void *pic, int irq)
+void sp804_init(uint32_t base, qemu_irq irq)
 {
     int iomemtype;
     sp804_state *s;
+    qemu_irq *qi;
 
     s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
-    s->handler = sp804_set_irq;
+    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     /* ??? The timers are actually configurable between 32kHz and 1MHz, but
        we don't implement that.  */
-    s->timer[0] = arm_timer_init(1000000, s, 0);
-    s->timer[1] = arm_timer_init(1000000, s, 1);
+    s->timer[0] = arm_timer_init(1000000, qi[0]);
+    s->timer[1] = arm_timer_init(1000000, qi[1]);
     iomemtype = cpu_register_io_memory(0, sp804_readfn,
                                        sp804_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
@@ -362,7 +357,7 @@
    icp_pit_write
 };
 
-void icp_pit_init(uint32_t base, void *pic, int irq)
+void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
 {
     int iomemtype;
     icp_pit_state *s;
@@ -370,10 +365,10 @@
     s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
     s->base = base;
     /* Timer 0 runs at the system clock speed (40MHz).  */
-    s->timer[0] = arm_timer_init(40000000, pic, irq);
+    s->timer[0] = arm_timer_init(40000000, pic[irq]);
     /* The other two timers run at 1MHz.  */
-    s->timer[1] = arm_timer_init(1000000, pic, irq + 1);
-    s->timer[2] = arm_timer_init(1000000, pic, irq + 2);
+    s->timer[1] = arm_timer_init(1000000, pic[irq + 1]);
+    s->timer[2] = arm_timer_init(1000000, pic[irq + 2]);
 
     iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
                                        icp_pit_writefn, s);

Modified: trunk/src/host/qemu-neo1973/hw/cirrus_vga.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cirrus_vga.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cirrus_vga.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -3193,6 +3193,9 @@
     vga_common_init((VGAState *)s, 
                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     cirrus_init_common(s, device_id, 1);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
     s->pci_dev = (PCIDevice *)d;
 
     /* setup memory space */

Modified: trunk/src/host/qemu-neo1973/hw/cs4231.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cs4231.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,9 +47,6 @@
 #ifdef DEBUG_CS
 #define DPRINTF(fmt, args...)                           \
     do { printf("CS: " fmt , ##args); } while (0)
-#define pic_set_irq_new(intctl, irq, level)                             \
-    do { printf("CS: set_irq(%d): %d\n", (irq), (level));               \
-        pic_set_irq_new((intctl), (irq),(level));} while (0)
 #else
 #define DPRINTF(fmt, args...)
 #endif

Modified: trunk/src/host/qemu-neo1973/hw/cuda.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/cuda.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/cuda.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -124,9 +124,7 @@
     int data_in_index;
     int data_out_index;
 
-    SetIRQFunc *set_irq;
-    int irq;
-    void *irq_opaque;
+    qemu_irq irq;
     uint8_t autopoll;
     uint8_t data_in[128];
     uint8_t data_out[16];
@@ -145,9 +143,9 @@
 static void cuda_update_irq(CUDAState *s)
 {
     if (s->ifr & s->ier & (SR_INT | T1_INT)) {
-        s->set_irq(s->irq_opaque, s->irq, 1);
+        qemu_irq_raise(s->irq);
     } else {
-        s->set_irq(s->irq_opaque, s->irq, 0);
+        qemu_irq_lower(s->irq);
     }
 }
 
@@ -630,13 +628,11 @@
     &cuda_readl,
 };
 
-int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
+int cuda_init(qemu_irq irq)
 {
     CUDAState *s = &cuda_state;
     int cuda_mem_index;
 
-    s->set_irq = set_irq;
-    s->irq_opaque = irq_opaque;
     s->irq = irq;
 
     s->timers[0].index = 0;

Added: trunk/src/host/qemu-neo1973/hw/ds1225y.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ds1225y.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ds1225y.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,121 @@
+/*
+ * QEMU NVRAM emulation for DS1225Y chip
+ * 
+ * Copyright (c) 2007 Hervé Poussineau
+ * 
+ * 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 "vl.h"
+
+typedef enum
+{
+    none = 0,
+    readmode,
+    writemode,
+} nvram_open_mode;
+
+struct ds1225y_t
+{
+    target_ulong mem_base;
+    uint32_t capacity;
+    const char *filename;
+    QEMUFile *file;
+    nvram_open_mode open_mode;
+};
+
+static int ds1225y_set_to_mode(ds1225y_t *NVRAM, nvram_open_mode mode, const char *filemode)
+{
+    if (NVRAM->open_mode != mode)
+    {
+        if (NVRAM->file)
+            qemu_fclose(NVRAM->file);
+        NVRAM->file = qemu_fopen(NVRAM->filename, filemode);
+        NVRAM->open_mode = mode;
+    }
+    return (NVRAM->file != NULL);
+}
+
+static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+    ds1225y_t *NVRAM = opaque;
+    int64_t pos;
+
+    pos = addr - NVRAM->mem_base;
+    if (addr >= NVRAM->capacity)
+        addr -= NVRAM->capacity;
+
+    if (!ds1225y_set_to_mode(NVRAM, readmode, "rb"))
+        return 0;
+    qemu_fseek(NVRAM->file, pos, SEEK_SET);
+    return (uint32_t)qemu_get_byte(NVRAM->file);
+}
+
+static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    ds1225y_t *NVRAM = opaque;
+    int64_t pos;
+
+    pos = addr - NVRAM->mem_base;
+    if (ds1225y_set_to_mode(NVRAM, writemode, "wb"))
+    {
+        qemu_fseek(NVRAM->file, pos, SEEK_SET);
+        qemu_put_byte(NVRAM->file, (int)value);
+    }
+}
+
+static CPUReadMemoryFunc *nvram_read[] = {
+    &nvram_readb,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+    &nvram_writeb,
+    NULL,
+    NULL,
+};
+
+static CPUWriteMemoryFunc *nvram_none[] = {
+    NULL,
+    NULL,
+    NULL,
+};
+
+/* Initialisation routine */
+ds1225y_t *ds1225y_init(target_ulong mem_base, const char *filename)
+{
+    ds1225y_t *s;
+    int mem_index1, mem_index2;
+
+    s = qemu_mallocz(sizeof(ds1225y_t));
+    if (!s)
+        return NULL;
+    s->mem_base = mem_base;
+    s->capacity = 0x2000; /* Fixed for ds1225y chip: 8K */
+    s->filename = filename;
+
+    /* Read/write memory */
+    mem_index1 = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+    cpu_register_physical_memory(mem_base, s->capacity, mem_index1);
+    /* Read-only memory */
+    mem_index2 = cpu_register_io_memory(0, nvram_read, nvram_none, s);
+    cpu_register_physical_memory(mem_base + s->capacity, s->capacity, mem_index2);
+    return s;
+}

Added: trunk/src/host/qemu-neo1973/hw/eepro100.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eepro100.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eepro100.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1714 @@
+/*
+ * QEMU i8255x (PRO100) emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * Portions of the code are copies from grub / etherboot eepro100.c
+ * and linux e100.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Tested features (i82559):
+ *      PXE boot (i386) no valid link
+ *      Linux networking (i386) ok
+ *
+ * Untested:
+ *      non-i386 platforms
+ *      Windows networking
+ *
+ * References:
+ *
+ * Intel 8255x 10/100 Mbps Ethernet Controller Family
+ * Open Source Software Developer Manual
+ */
+
+#if defined(TARGET_I386)
+# warning "PXE boot still not working!"
+#endif
+
+#include <assert.h>
+#include <stddef.h>             /* offsetof */
+#include "vl.h"
+#include "eeprom93xx.h"
+
+/* Common declarations for all PCI devices. */
+
+#define PCI_VENDOR_ID           0x00    /* 16 bits */
+#define PCI_DEVICE_ID           0x02    /* 16 bits */
+#define PCI_COMMAND             0x04    /* 16 bits */
+#define PCI_STATUS              0x06    /* 16 bits */
+
+#define PCI_REVISION_ID         0x08    /* 8 bits  */
+#define PCI_CLASS_CODE          0x0b    /* 8 bits */
+#define PCI_SUBCLASS_CODE       0x0a    /* 8 bits */
+#define PCI_HEADER_TYPE         0x0e    /* 8 bits */
+
+#define PCI_BASE_ADDRESS_0      0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1      0x14    /* 32 bits */
+#define PCI_BASE_ADDRESS_2      0x18    /* 32 bits */
+#define PCI_BASE_ADDRESS_3      0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4      0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5      0x24    /* 32 bits */
+
+#define PCI_CONFIG_8(offset, value) \
+    (pci_conf[offset] = (value))
+#define PCI_CONFIG_16(offset, value) \
+    (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value))
+#define PCI_CONFIG_32(offset, value) \
+    (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value))
+
+#define KiB 1024
+
+/* debug EEPRO100 card */
+//~ #define DEBUG_EEPRO100
+
+#ifdef DEBUG_EEPRO100
+#define logout(fmt, args...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ##args)
+#else
+#define logout(fmt, args...) ((void)0)
+#endif
+
+/* Set flags to 0 to disable debug output. */
+#define MDI     0
+
+#define TRACE(flag, command) ((flag) ? (command) : (void)0)
+
+#define missing(text)       assert(!"feature is missing in this emulation: " text)
+
+#define MAX_ETH_FRAME_SIZE 1514
+
+/* This driver supports several different devices which are declared here. */
+#define i82551          0x82551
+#define i82557B         0x82557b
+#define i82557C         0x82557c
+#define i82558B         0x82558b
+#define i82559C         0x82559c
+#define i82559ER        0x82559e
+#define i82562          0x82562
+
+#define EEPROM_SIZE     64
+
+#define PCI_MEM_SIZE            (4 * KiB)
+#define PCI_IO_SIZE             64
+#define PCI_FLASH_SIZE          (128 * KiB)
+
+#define BIT(n) (1 << (n))
+#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
+
+/* The SCB accepts the following controls for the Tx and Rx units: */
+#define  CU_NOP         0x0000  /* No operation. */
+#define  CU_START       0x0010  /* CU start. */
+#define  CU_RESUME      0x0020  /* CU resume. */
+#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
+#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
+#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
+#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
+#define  CU_SRESUME     0x00a0  /* CU static resume. */
+
+#define  RU_NOP         0x0000
+#define  RX_START       0x0001
+#define  RX_RESUME      0x0002
+#define  RX_ABORT       0x0004
+#define  RX_ADDR_LOAD   0x0006
+#define  RX_RESUMENR    0x0007
+#define INT_MASK        0x0100
+#define DRVR_INT        0x0200  /* Driver generated interrupt. */
+
+typedef unsigned char bool;
+
+/* Offsets to the various registers.
+   All accesses need not be longword aligned. */
+enum speedo_offsets {
+    SCBStatus = 0,
+    SCBAck = 1,
+    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
+    SCBIntmask = 3,
+    SCBPointer = 4,             /* General purpose pointer. */
+    SCBPort = 8,                /* Misc. commands and operands.  */
+    SCBflash = 12, SCBeeprom = 14,      /* EEPROM and flash memory control. */
+    SCBCtrlMDI = 16,            /* MDI interface control. */
+    SCBEarlyRx = 20,            /* Early receive byte count. */
+};
+
+/* A speedo3 transmit buffer descriptor with two buffers... */
+typedef struct {
+    uint16_t status;
+    uint16_t command;
+    uint32_t link;              /* void * */
+    uint32_t tx_desc_addr;      /* transmit buffer decsriptor array address. */
+    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
+    uint8_t tx_threshold;       /* transmit threshold */
+    uint8_t tbd_count;          /* TBD number */
+    //~ /* This constitutes two "TBD" entries: hdr and data */
+    //~ uint32_t tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
+    //~ int32_t  tx_buf_size0;  /* Length of Tx hdr. */
+    //~ uint32_t tx_buf_addr1;  /* void *, data to be transmitted.  */
+    //~ int32_t  tx_buf_size1;  /* Length of Tx data. */
+} eepro100_tx_t;
+
+/* Receive frame descriptor. */
+typedef struct {
+    int16_t status;
+    uint16_t command;
+    uint32_t link;              /* struct RxFD * */
+    uint32_t rx_buf_addr;       /* void * */
+    uint16_t count;
+    uint16_t size;
+    char packet[MAX_ETH_FRAME_SIZE + 4];
+} eepro100_rx_t;
+
+typedef struct {
+    uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
+        tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
+        tx_multiple_collisions, tx_total_collisions;
+    uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors,
+        rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
+        rx_short_frame_errors;
+    uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
+    uint16_t xmt_tco_frames, rcv_tco_frames;
+    uint32_t complete;
+} eepro100_stats_t;
+
+typedef enum {
+    cu_idle = 0,
+    cu_suspended = 1,
+    cu_active = 2,
+    cu_lpq_active = 2,
+    cu_hqp_active = 3
+} cu_state_t;
+
+typedef enum {
+    ru_idle = 0,
+    ru_suspended = 1,
+    ru_no_resources = 2,
+    ru_ready = 4
+} ru_state_t;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+#define X(a,b)	b,a
+#else
+#define X(a,b)	a,b
+#endif
+
+typedef struct {
+#if 1
+    uint8_t cmd;
+    uint32_t start;
+    uint32_t stop;
+    uint8_t boundary;
+    uint8_t tsr;
+    uint8_t tpsr;
+    uint16_t tcnt;
+    uint16_t rcnt;
+    uint32_t rsar;
+    uint8_t rsr;
+    uint8_t rxcr;
+    uint8_t isr;
+    uint8_t dcfg;
+    uint8_t imr;
+    uint8_t phys[6];            /* mac address */
+    uint8_t curpag;
+    uint8_t mult[8];            /* multicast mask array */
+    int mmio_index;
+    PCIDevice *pci_dev;
+    VLANClientState *vc;
+#endif
+    uint8_t scb_stat;           /* SCB stat/ack byte */
+    uint8_t int_stat;           /* PCI interrupt status */
+    uint32_t region[3];         /* PCI region addresses */
+    uint8_t macaddr[6];
+    uint32_t statcounter[19];
+    uint16_t mdimem[32];
+    eeprom_t *eeprom;
+    uint32_t device;            /* device variant */
+    uint32_t pointer;
+    /* (cu_base + cu_offset) address the next command block in the command block list. */
+    uint32_t cu_base;           /* CU base address */
+    uint32_t cu_offset;         /* CU address offset */
+    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
+    uint32_t ru_base;           /* RU base address */
+    uint32_t ru_offset;         /* RU address offset */
+    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
+    eepro100_stats_t statistics;        /* statistical counters */
+#if 0
+    uint16_t status;
+#endif
+
+    /* Configuration bytes. */
+    uint8_t configuration[22];
+
+    /* Data in mem is always in the byte order of the controller (le). */
+    uint8_t mem[PCI_MEM_SIZE];
+} EEPRO100State;
+
+/* Default values for MDI (PHY) registers */
+static const uint16_t eepro100_mdi_default[] = {
+    /* MDI Registers 0 - 6, 7 */
+    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
+    /* MDI Registers 8 - 15 */
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    /* MDI Registers 16 - 31 */
+    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+/* Readonly mask for MDI (PHY) registers */
+static const uint16_t eepro100_mdi_mask[] = {
+    0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+#define POLYNOMIAL 0x04c11db6
+
+/* From FreeBSD */
+/* XXX: optimize */
+static int compute_mcast_idx(const uint8_t * ep)
+{
+    uint32_t crc;
+    int carry, i, j;
+    uint8_t b;
+
+    crc = 0xffffffff;
+    for (i = 0; i < 6; i++) {
+        b = *ep++;
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
+            crc <<= 1;
+            b >>= 1;
+            if (carry)
+                crc = ((crc ^ POLYNOMIAL) | carry);
+        }
+    }
+    return (crc >> 26);
+}
+
+#if defined(DEBUG_EEPRO100)
+static const char *nic_dump(const uint8_t * buf, unsigned size)
+{
+    static char dump[3 * 16 + 1];
+    char *p = &dump[0];
+    if (size > 16)
+        size = 16;
+    while (size-- > 0) {
+        p += sprintf(p, " %02x", *buf++);
+    }
+    return dump;
+}
+#endif                          /* DEBUG_EEPRO100 */
+
+enum scb_stat_ack {
+    stat_ack_not_ours = 0x00,
+    stat_ack_sw_gen = 0x04,
+    stat_ack_rnr = 0x10,
+    stat_ack_cu_idle = 0x20,
+    stat_ack_frame_rx = 0x40,
+    stat_ack_cu_cmd_done = 0x80,
+    stat_ack_not_present = 0xFF,
+    stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
+    stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
+};
+
+static void disable_interrupt(EEPRO100State * s)
+{
+    if (s->int_stat) {
+        logout("interrupt disabled\n");
+        qemu_irq_lower(s->pci_dev->irq[0]);
+        s->int_stat = 0;
+    }
+}
+
+static void enable_interrupt(EEPRO100State * s)
+{
+    if (!s->int_stat) {
+        logout("interrupt enabled\n");
+        qemu_irq_raise(s->pci_dev->irq[0]);
+        s->int_stat = 1;
+    }
+}
+
+static void eepro100_acknowledge(EEPRO100State * s)
+{
+    s->scb_stat &= ~s->mem[SCBAck];
+    s->mem[SCBAck] = s->scb_stat;
+    if (s->scb_stat == 0) {
+        disable_interrupt(s);
+    }
+}
+
+static void eepro100_interrupt(EEPRO100State * s, uint8_t stat)
+{
+    uint8_t mask = ~s->mem[SCBIntmask];
+    s->mem[SCBAck] |= stat;
+    stat = s->scb_stat = s->mem[SCBAck];
+    stat &= (mask | 0x0f);
+    //~ stat &= (~s->mem[SCBIntmask] | 0x0xf);
+    if (stat && (mask & 0x01)) {
+        /* SCB mask and SCB Bit M do not disable interrupt. */
+        enable_interrupt(s);
+    } else if (s->int_stat) {
+        disable_interrupt(s);
+    }
+}
+
+static void eepro100_cx_interrupt(EEPRO100State * s)
+{
+    /* CU completed action command. */
+    /* Transmit not ok (82557 only, not in emulation). */
+    eepro100_interrupt(s, 0x80);
+}
+
+static void eepro100_cna_interrupt(EEPRO100State * s)
+{
+    /* CU left the active state. */
+    eepro100_interrupt(s, 0x20);
+}
+
+static void eepro100_fr_interrupt(EEPRO100State * s)
+{
+    /* RU received a complete frame. */
+    eepro100_interrupt(s, 0x40);
+}
+
+#if 0
+static void eepro100_rnr_interrupt(EEPRO100State * s)
+{
+    /* RU is not ready. */
+    eepro100_interrupt(s, 0x10);
+}
+#endif
+
+static void eepro100_mdi_interrupt(EEPRO100State * s)
+{
+    /* MDI completed read or write cycle. */
+    eepro100_interrupt(s, 0x08);
+}
+
+static void eepro100_swi_interrupt(EEPRO100State * s)
+{
+    /* Software has requested an interrupt. */
+    eepro100_interrupt(s, 0x04);
+}
+
+#if 0
+static void eepro100_fcp_interrupt(EEPRO100State * s)
+{
+    /* Flow control pause interrupt (82558 and later). */
+    eepro100_interrupt(s, 0x01);
+}
+#endif
+
+static void pci_reset(EEPRO100State * s)
+{
+    uint32_t device = s->device;
+    uint8_t *pci_conf = s->pci_dev->config;
+
+    logout("%p\n", s);
+
+    /* PCI Vendor ID */
+    PCI_CONFIG_16(PCI_VENDOR_ID, 0x8086);
+    /* PCI Device ID */
+    PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+    /* PCI Command */
+    PCI_CONFIG_16(PCI_COMMAND, 0x0000);
+    /* PCI Status */
+    PCI_CONFIG_16(PCI_STATUS, 0x2800);
+    /* PCI Revision ID */
+    PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
+    /* PCI Class Code */
+    PCI_CONFIG_8(0x09, 0x00);
+    PCI_CONFIG_8(PCI_SUBCLASS_CODE, 0x00);      // ethernet network controller
+    PCI_CONFIG_8(PCI_CLASS_CODE, 0x02); // network controller
+    /* PCI Cache Line Size */
+    /* check cache line size!!! */
+    //~ PCI_CONFIG_8(0x0c, 0x00);
+    /* PCI Latency Timer */
+    PCI_CONFIG_8(0x0d, 0x20);   // latency timer = 32 clocks
+    /* PCI Header Type */
+    /* BIST (built-in self test) */
+#if defined(TARGET_I386)
+// !!! workaround for buggy bios
+//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0
+#endif
+#if 0
+    /* PCI Base Address Registers */
+    /* CSR Memory Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_0,
+                  PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH);
+    /* CSR I/O Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_ADDRESS_SPACE_IO);
+#if 0
+    /* Flash Memory Mapped Base Address */
+    PCI_CONFIG_32(PCI_BASE_ADDRESS_2, 0xfffe0000 | PCI_ADDRESS_SPACE_MEM);
+#endif
+#endif
+    /* Expansion ROM Base Address (depends on boot disable!!!) */
+    PCI_CONFIG_32(0x30, 0x00000000);
+    /* Capability Pointer */
+    PCI_CONFIG_8(0x34, 0xdc);
+    /* Interrupt Pin */
+    PCI_CONFIG_8(0x3d, 1);      // interrupt pin 0
+    /* Minimum Grant */
+    PCI_CONFIG_8(0x3e, 0x08);
+    /* Maximum Latency */
+    PCI_CONFIG_8(0x3f, 0x18);
+    /* Power Management Capabilities / Next Item Pointer / Capability ID */
+    PCI_CONFIG_32(0xdc, 0x7e210001);
+
+    switch (device) {
+    case i82551:
+        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);
+        break;
+    case i82557B:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);
+        break;
+    case i82557C:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);
+        break;
+    case i82558B:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);
+        break;
+    case i82559C:
+        PCI_CONFIG_16(PCI_DEVICE_ID, 0x1229);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        //~ PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
+        break;
+    case i82559ER:
+        //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1209);
+        PCI_CONFIG_16(PCI_STATUS, 0x2810);
+        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);
+        break;
+    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1029);
+    //~ PCI_CONFIG_16(PCI_DEVICE_ID, 0x1030);       /* 82559 InBusiness 10/100 */
+    default:
+        logout("Device %X is undefined!\n", device);
+    }
+
+    if (device == i82557C || device == i82558B || device == i82559C) {
+        logout("Get device id and revision from EEPROM!!!\n");
+    }
+}
+
+static void nic_selective_reset(EEPRO100State * s)
+{
+    size_t i;
+    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
+    //~ eeprom93xx_reset(s->eeprom);
+    memcpy(eeprom_contents, s->macaddr, 6);
+    eeprom_contents[0xa] = 0x4000;
+    uint16_t sum = 0;
+    for (i = 0; i < EEPROM_SIZE - 1; i++) {
+        sum += eeprom_contents[i];
+    }
+    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;
+
+    memset(s->mem, 0, sizeof(s->mem));
+    uint32_t val = BIT(21);
+    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
+
+    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
+    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
+}
+
+static void nic_reset(void *opaque)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+    logout("%p\n", s);
+    static int first;
+    if (!first) {
+        first = 1;
+    }
+    nic_selective_reset(s);
+}
+
+#if defined(DEBUG_EEPRO100)
+static const char *reg[PCI_IO_SIZE / 4] = {
+    "Command/Status",
+    "General Pointer",
+    "Port",
+    "EEPROM/Flash Control",
+    "MDI Control",
+    "Receive DMA Byte Count",
+    "Flow control register",
+    "General Status/Control"
+};
+
+static char *regname(uint32_t addr)
+{
+    static char buf[16];
+    if (addr < PCI_IO_SIZE) {
+        const char *r = reg[addr / 4];
+        if (r != 0) {
+            sprintf(buf, "%s+%u", r, addr % 4);
+        } else {
+            sprintf(buf, "0x%02x", addr);
+        }
+    } else {
+        sprintf(buf, "??? 0x%08x", addr);
+    }
+    return buf;
+}
+#endif                          /* DEBUG_EEPRO100 */
+
+#if 0
+static uint16_t eepro100_read_status(EEPRO100State * s)
+{
+    uint16_t val = s->status;
+    logout("val=0x%04x\n", val);
+    return val;
+}
+
+static void eepro100_write_status(EEPRO100State * s, uint16_t val)
+{
+    logout("val=0x%04x\n", val);
+    s->status = val;
+}
+#endif
+
+/*****************************************************************************
+ *
+ * Command emulation.
+ *
+ ****************************************************************************/
+
+#if 0
+static uint16_t eepro100_read_command(EEPRO100State * s)
+{
+    uint16_t val = 0xffff;
+    //~ logout("val=0x%04x\n", val);
+    return val;
+}
+#endif
+
+/* Commands that can be put in a command list entry. */
+enum commands {
+    CmdNOp = 0,
+    CmdIASetup = 1,
+    CmdConfigure = 2,
+    CmdMulticastList = 3,
+    CmdTx = 4,
+    CmdTDR = 5,                 /* load microcode */
+    CmdDump = 6,
+    CmdDiagnose = 7,
+
+    /* And some extra flags: */
+    CmdSuspend = 0x4000,        /* Suspend after completion. */
+    CmdIntr = 0x2000,           /* Interrupt after completion. */
+    CmdTxFlex = 0x0008,         /* Use "Flexible mode" for CmdTx command. */
+};
+
+static cu_state_t get_cu_state(EEPRO100State * s)
+{
+    return ((s->mem[SCBStatus] >> 6) & 0x03);
+}
+
+static void set_cu_state(EEPRO100State * s, cu_state_t state)
+{
+    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0x3f) + (state << 6);
+}
+
+static ru_state_t get_ru_state(EEPRO100State * s)
+{
+    return ((s->mem[SCBStatus] >> 2) & 0x0f);
+}
+
+static void set_ru_state(EEPRO100State * s, ru_state_t state)
+{
+    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0xc3) + (state << 2);
+}
+
+static void dump_statistics(EEPRO100State * s)
+{
+    /* Dump statistical data. Most data is never changed by the emulation
+     * and always 0, so we first just copy the whole block and then those
+     * values which really matter.
+     * Number of data should check configuration!!!
+     */
+    cpu_physical_memory_write(s->statsaddr, (uint8_t *) & s->statistics, 64);
+    stl_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
+    stl_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
+    stl_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
+    stl_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
+    //~ stw_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
+    //~ stw_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
+    //~ missing("CU dump statistical counters");
+}
+
+static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
+{
+    eepro100_tx_t tx;
+    uint32_t cb_address;
+    switch (val) {
+    case CU_NOP:
+        /* No operation. */
+        break;
+    case CU_START:
+        if (get_cu_state(s) != cu_idle) {
+            /* Intel documentation says that CU must be idle for the CU
+             * start command. Intel driver for Linux also starts the CU
+             * from suspended state. */
+            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);
+            //~ assert(!"wrong CU state");
+        }
+        set_cu_state(s, cu_active);
+        s->cu_offset = s->pointer;
+      next_command:
+        cb_address = s->cu_base + s->cu_offset;
+        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));
+        uint16_t status = le16_to_cpu(tx.status);
+        uint16_t command = le16_to_cpu(tx.command);
+        logout
+            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
+             val, status, command, tx.link);
+        bool bit_el = ((command & 0x8000) != 0);
+        bool bit_s = ((command & 0x4000) != 0);
+        bool bit_i = ((command & 0x2000) != 0);
+        bool bit_nc = ((command & 0x0010) != 0);
+        //~ bool bit_sf = ((command & 0x0008) != 0);
+        uint16_t cmd = command & 0x0007;
+        s->cu_offset = le32_to_cpu(tx.link);
+        switch (cmd) {
+        case CmdNOp:
+            /* Do nothing. */
+            break;
+        case CmdIASetup:
+            cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6);
+            logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));
+            break;
+        case CmdConfigure:
+            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],
+                                     sizeof(s->configuration));
+            logout("configuration: %s\n", nic_dump(&s->configuration[0], 16));
+            break;
+        case CmdMulticastList:
+            //~ missing("multicast list");
+            break;
+        case CmdTx:
+            (void)0;
+            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);
+            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);
+            logout
+                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
+                 tbd_array, tcb_bytes, tx.tbd_count);
+            assert(!bit_nc);
+            //~ assert(!bit_sf);
+            assert(tcb_bytes <= 2600);
+            /* Next assertion fails for local configuration. */
+            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
+            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
+                logout
+                    ("illegal values of TBD array address and TCB byte count!\n");
+            }
+            uint8_t buf[MAX_ETH_FRAME_SIZE + 4];
+            uint16_t size = 0;
+            uint32_t tbd_address = cb_address + 0x10;
+            assert(tcb_bytes <= sizeof(buf));
+            while (size < tcb_bytes) {
+                uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                tbd_address += 8;
+                logout
+                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
+                     tx_buffer_address, tx_buffer_size);
+                cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                         tx_buffer_size);
+                size += tx_buffer_size;
+            }
+            if (tbd_array == 0xffffffff) {
+                /* Simplified mode. Was already handled by code above. */
+            } else {
+                /* Flexible mode. */
+                uint8_t tbd_count = 0;
+                if (!(s->configuration[6] & BIT(4))) {
+                    /* Extended TCB. */
+                    assert(tcb_bytes == 0);
+                    for (; tbd_count < 2; tbd_count++) {
+                        uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                        tbd_address += 8;
+                        logout
+                            ("TBD (extended mode): buffer address 0x%08x, size 0x%04x\n",
+                             tx_buffer_address, tx_buffer_size);
+                        cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                                 tx_buffer_size);
+                        size += tx_buffer_size;
+                        if (tx_buffer_el & 1) {
+                            break;
+                        }
+                    }
+                }
+                tbd_address = tbd_array;
+                for (; tbd_count < tx.tbd_count; tbd_count++) {
+                    uint32_t tx_buffer_address = ldl_phys(tbd_address);
+                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
+                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
+                    tbd_address += 8;
+                    logout
+                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
+                         tx_buffer_address, tx_buffer_size);
+                    cpu_physical_memory_read(tx_buffer_address, &buf[size],
+                                             tx_buffer_size);
+                    size += tx_buffer_size;
+                    if (tx_buffer_el & 1) {
+                        break;
+                    }
+                }
+            }
+            qemu_send_packet(s->vc, buf, size);
+            s->statistics.tx_good_frames++;
+            /* Transmit with bad status would raise an CX/TNO interrupt.
+             * (82557 only). Emulation never has bad status. */
+            //~ eepro100_cx_interrupt(s);
+            break;
+        case CmdTDR:
+            logout("load microcode\n");
+            /* Starting with offset 8, the command contains
+             * 64 dwords microcode which we just ignore here. */
+            break;
+        default:
+            missing("undefined command");
+        }
+        /* Write new status (success). */
+        stw_phys(cb_address, status | 0x8000 | 0x2000);
+        if (bit_i) {
+            /* CU completed action. */
+            eepro100_cx_interrupt(s);
+        }
+        if (bit_el) {
+            /* CU becomes idle. */
+            set_cu_state(s, cu_idle);
+            eepro100_cna_interrupt(s);
+        } else if (bit_s) {
+            /* CU becomes suspended. */
+            set_cu_state(s, cu_suspended);
+            eepro100_cna_interrupt(s);
+        } else {
+            /* More entries in list. */
+            logout("CU list with at least one more entry\n");
+            goto next_command;
+        }
+        logout("CU list empty\n");
+        /* List is empty. Now CU is idle or suspended. */
+        break;
+    case CU_RESUME:
+        if (get_cu_state(s) != cu_suspended) {
+            logout("bad CU resume from CU state %u\n", get_cu_state(s));
+            /* Workaround for bad Linux eepro100 driver which resumes
+             * from idle state. */
+            //~ missing("cu resume");
+            set_cu_state(s, cu_suspended);
+        }
+        if (get_cu_state(s) == cu_suspended) {
+            logout("CU resuming\n");
+            set_cu_state(s, cu_active);
+            goto next_command;
+        }
+        break;
+    case CU_STATSADDR:
+        /* Load dump counters address. */
+        s->statsaddr = s->pointer;
+        logout("val=0x%02x (status address)\n", val);
+        break;
+    case CU_SHOWSTATS:
+        /* Dump statistical counters. */
+        dump_statistics(s);
+        break;
+    case CU_CMD_BASE:
+        /* Load CU base. */
+        logout("val=0x%02x (CU base address)\n", val);
+        s->cu_base = s->pointer;
+        break;
+    case CU_DUMPSTATS:
+        /* Dump and reset statistical counters. */
+        dump_statistics(s);
+        memset(&s->statistics, 0, sizeof(s->statistics));
+        break;
+    case CU_SRESUME:
+        /* CU static resume. */
+        missing("CU static resume");
+        break;
+    default:
+        missing("Undefined CU command");
+    }
+}
+
+static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
+{
+    switch (val) {
+    case RU_NOP:
+        /* No operation. */
+        break;
+    case RX_START:
+        /* RU start. */
+        if (get_ru_state(s) != ru_idle) {
+            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);
+            //~ assert(!"wrong RU state");
+        }
+        set_ru_state(s, ru_ready);
+        s->ru_offset = s->pointer;
+        logout("val=0x%02x (rx start)\n", val);
+        break;
+    case RX_RESUME:
+        /* Restart RU. */
+        if (get_ru_state(s) != ru_suspended) {
+            logout("RU state is %u, should be %u\n", get_ru_state(s),
+                   ru_suspended);
+            //~ assert(!"wrong RU state");
+        }
+        set_ru_state(s, ru_ready);
+        break;
+    case RX_ADDR_LOAD:
+        /* Load RU base. */
+        logout("val=0x%02x (RU base address)\n", val);
+        s->ru_base = s->pointer;
+        break;
+    default:
+        logout("val=0x%02x (undefined RU command)\n", val);
+        missing("Undefined SU command");
+    }
+}
+
+static void eepro100_write_command(EEPRO100State * s, uint8_t val)
+{
+    eepro100_ru_command(s, val & 0x0f);
+    eepro100_cu_command(s, val & 0xf0);
+    if ((val) == 0) {
+        logout("val=0x%02x\n", val);
+    }
+    /* Clear command byte after command was accepted. */
+    s->mem[SCBCmd] = 0;
+}
+
+/*****************************************************************************
+ *
+ * EEPROM emulation.
+ *
+ ****************************************************************************/
+
+#define EEPROM_CS       0x02
+#define EEPROM_SK       0x01
+#define EEPROM_DI       0x04
+#define EEPROM_DO       0x08
+
+static uint16_t eepro100_read_eeprom(EEPRO100State * s)
+{
+    uint16_t val;
+    memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
+    if (eeprom93xx_read(s->eeprom)) {
+        val |= EEPROM_DO;
+    } else {
+        val &= ~EEPROM_DO;
+    }
+    return val;
+}
+
+static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
+{
+    logout("write val=0x%02x\n", val);
+
+    /* mask unwriteable bits */
+    //~ val = SET_MASKED(val, 0x31, eeprom->value);
+
+    int eecs = ((val & EEPROM_CS) != 0);
+    int eesk = ((val & EEPROM_SK) != 0);
+    int eedi = ((val & EEPROM_DI) != 0);
+    eeprom93xx_write(eeprom, eecs, eesk, eedi);
+}
+
+static void eepro100_write_pointer(EEPRO100State * s, uint32_t val)
+{
+    s->pointer = le32_to_cpu(val);
+    logout("val=0x%08x\n", val);
+}
+
+/*****************************************************************************
+ *
+ * MDI emulation.
+ *
+ ****************************************************************************/
+
+#if defined(DEBUG_EEPRO100)
+static const char *mdi_op_name[] = {
+    "opcode 0",
+    "write",
+    "read",
+    "opcode 3"
+};
+
+static const char *mdi_reg_name[] = {
+    "Control",
+    "Status",
+    "PHY Identification (Word 1)",
+    "PHY Identification (Word 2)",
+    "Auto-Negotiation Advertisement",
+    "Auto-Negotiation Link Partner Ability",
+    "Auto-Negotiation Expansion"
+};
+#endif                          /* DEBUG_EEPRO100 */
+
+static uint32_t eepro100_read_mdi(EEPRO100State * s)
+{
+    uint32_t val;
+    memcpy(&val, &s->mem[0x10], sizeof(val));
+
+#ifdef DEBUG_EEPRO100
+    uint8_t raiseint = (val & BIT(29)) >> 29;
+    uint8_t opcode = (val & BITS(27, 26)) >> 26;
+    uint8_t phy = (val & BITS(25, 21)) >> 21;
+    uint8_t reg = (val & BITS(20, 16)) >> 16;
+    uint16_t data = (val & BITS(15, 0));
+#endif
+    /* Emulation takes no time to finish MDI transaction. */
+    val |= BIT(28);
+    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
+                      val, raiseint, mdi_op_name[opcode], phy,
+                      mdi_reg_name[reg], data));
+    return val;
+}
+
+//~ #define BITS(val, upper, lower) (val & ???)
+static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
+{
+    uint8_t raiseint = (val & BIT(29)) >> 29;
+    uint8_t opcode = (val & BITS(27, 26)) >> 26;
+    uint8_t phy = (val & BITS(25, 21)) >> 21;
+    uint8_t reg = (val & BITS(20, 16)) >> 16;
+    uint16_t data = (val & BITS(15, 0));
+    if (phy != 1) {
+        /* Unsupported PHY address. */
+        //~ logout("phy must be 1 but is %u\n", phy);
+        data = 0;
+    } else if (opcode != 1 && opcode != 2) {
+        /* Unsupported opcode. */
+        logout("opcode must be 1 or 2 but is %u\n", opcode);
+        data = 0;
+    } else if (reg > 6) {
+        /* Unsupported register. */
+        logout("register must be 0...6 but is %u\n", reg);
+        data = 0;
+    } else {
+        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
+                          val, raiseint, mdi_op_name[opcode], phy,
+                          mdi_reg_name[reg], data));
+        if (opcode == 1) {
+            /* MDI write */
+            switch (reg) {
+            case 0:            /* Control Register */
+                if (data & 0x8000) {
+                    /* Reset status and control registers to default. */
+                    s->mdimem[0] = eepro100_mdi_default[0];
+                    s->mdimem[1] = eepro100_mdi_default[1];
+                    data = s->mdimem[reg];
+                } else {
+                    /* Restart Auto Configuration = Normal Operation */
+                    data &= ~0x0200;
+                }
+                break;
+            case 1:            /* Status Register */
+                missing("not writable");
+                data = s->mdimem[reg];
+                break;
+            case 2:            /* PHY Identification Register (Word 1) */
+            case 3:            /* PHY Identification Register (Word 2) */
+                missing("not implemented");
+                break;
+            case 4:            /* Auto-Negotiation Advertisement Register */
+            case 5:            /* Auto-Negotiation Link Partner Ability Register */
+                break;
+            case 6:            /* Auto-Negotiation Expansion Register */
+            default:
+                missing("not implemented");
+            }
+            s->mdimem[reg] = data;
+        } else if (opcode == 2) {
+            /* MDI read */
+            switch (reg) {
+            case 0:            /* Control Register */
+                if (data & 0x8000) {
+                    /* Reset status and control registers to default. */
+                    s->mdimem[0] = eepro100_mdi_default[0];
+                    s->mdimem[1] = eepro100_mdi_default[1];
+                }
+                break;
+            case 1:            /* Status Register */
+                s->mdimem[reg] |= 0x0020;
+                break;
+            case 2:            /* PHY Identification Register (Word 1) */
+            case 3:            /* PHY Identification Register (Word 2) */
+            case 4:            /* Auto-Negotiation Advertisement Register */
+                break;
+            case 5:            /* Auto-Negotiation Link Partner Ability Register */
+                s->mdimem[reg] = 0x41fe;
+                break;
+            case 6:            /* Auto-Negotiation Expansion Register */
+                s->mdimem[reg] = 0x0001;
+                break;
+            }
+            data = s->mdimem[reg];
+        }
+        /* Emulation takes no time to finish MDI transaction.
+         * Set MDI bit in SCB status register. */
+        s->mem[SCBAck] |= 0x08;
+        val |= BIT(28);
+        if (raiseint) {
+            eepro100_mdi_interrupt(s);
+        }
+    }
+    val = (val & 0xffff0000) + data;
+    memcpy(&s->mem[0x10], &val, sizeof(val));
+}
+
+/*****************************************************************************
+ *
+ * Port emulation.
+ *
+ ****************************************************************************/
+
+#define PORT_SOFTWARE_RESET     0
+#define PORT_SELFTEST           1
+#define PORT_SELECTIVE_RESET    2
+#define PORT_DUMP               3
+#define PORT_SELECTION_MASK     3
+
+typedef struct {
+    uint32_t st_sign;           /* Self Test Signature */
+    uint32_t st_result;         /* Self Test Results */
+} eepro100_selftest_t;
+
+static uint32_t eepro100_read_port(EEPRO100State * s)
+{
+    return 0;
+}
+
+static void eepro100_write_port(EEPRO100State * s, uint32_t val)
+{
+    val = le32_to_cpu(val);
+    uint32_t address = (val & ~PORT_SELECTION_MASK);
+    uint8_t selection = (val & PORT_SELECTION_MASK);
+    switch (selection) {
+    case PORT_SOFTWARE_RESET:
+        nic_reset(s);
+        break;
+    case PORT_SELFTEST:
+        logout("selftest address=0x%08x\n", address);
+        eepro100_selftest_t data;
+        cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data));
+        data.st_sign = 0xffffffff;
+        data.st_result = 0;
+        cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data));
+        break;
+    case PORT_SELECTIVE_RESET:
+        logout("selective reset, selftest address=0x%08x\n", address);
+        nic_selective_reset(s);
+        break;
+    default:
+        logout("val=0x%08x\n", val);
+        missing("unknown port selection");
+    }
+}
+
+/*****************************************************************************
+ *
+ * General hardware emulation.
+ *
+ ****************************************************************************/
+
+static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
+{
+    uint8_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBAck:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBCmd:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        //~ val = eepro100_read_command(s);
+        break;
+    case SCBIntmask:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBPort + 3:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBeeprom:
+        val = eepro100_read_eeprom(s);
+        break;
+    case 0x1b:                 /* PMDR (power management driver register) */
+        val = 0;
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case 0x1d:                 /* general status register */
+        /* 100 Mbps full duplex, valid link */
+        val = 0x07;
+        logout("addr=General Status val=%02x\n", val);
+        break;
+    default:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        missing("unknown byte read");
+    }
+    return val;
+}
+
+static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
+{
+    uint16_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    logout("addr=%s val=0x%04x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        break;
+    case SCBeeprom:
+        val = eepro100_read_eeprom(s);
+        break;
+    default:
+        logout("addr=%s val=0x%04x\n", regname(addr), val);
+        missing("unknown word read");
+    }
+    return val;
+}
+
+static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
+{
+    uint32_t val;
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&val, &s->mem[addr], sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBStatus:
+        //~ val = eepro100_read_status(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBPointer:
+        //~ val = eepro100_read_pointer(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBPort:
+        val = eepro100_read_port(s);
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        break;
+    case SCBCtrlMDI:
+        val = eepro100_read_mdi(s);
+        break;
+    default:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        missing("unknown longword read");
+    }
+    return val;
+}
+
+static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    logout("addr=%s val=0x%02x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ eepro100_write_status(s, val);
+        break;
+    case SCBAck:
+        eepro100_acknowledge(s);
+        break;
+    case SCBCmd:
+        eepro100_write_command(s, val);
+        break;
+    case SCBIntmask:
+        if (val & BIT(1)) {
+            eepro100_swi_interrupt(s);
+        }
+        eepro100_interrupt(s, 0);
+        break;
+    case SCBPort + 3:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        break;
+    case SCBeeprom:
+        eepro100_write_eeprom(s->eeprom, val);
+        break;
+    default:
+        logout("addr=%s val=0x%02x\n", regname(addr), val);
+        missing("unknown byte write");
+    }
+}
+
+static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    logout("addr=%s val=0x%04x\n", regname(addr), val);
+
+    switch (addr) {
+    case SCBStatus:
+        //~ eepro100_write_status(s, val);
+        eepro100_acknowledge(s);
+        break;
+    case SCBCmd:
+        eepro100_write_command(s, val);
+        eepro100_write1(s, SCBIntmask, val >> 8);
+        break;
+    case SCBeeprom:
+        eepro100_write_eeprom(s->eeprom, val);
+        break;
+    default:
+        logout("addr=%s val=0x%04x\n", regname(addr), val);
+        missing("unknown word write");
+    }
+}
+
+static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
+{
+    if (addr <= sizeof(s->mem) - sizeof(val)) {
+        memcpy(&s->mem[addr], &val, sizeof(val));
+    }
+
+    switch (addr) {
+    case SCBPointer:
+        eepro100_write_pointer(s, val);
+        break;
+    case SCBPort:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        eepro100_write_port(s, val);
+        break;
+    case SCBCtrlMDI:
+        eepro100_write_mdi(s, val);
+        break;
+    default:
+        logout("addr=%s val=0x%08x\n", regname(addr), val);
+        missing("unknown longword write");
+    }
+}
+
+static uint32_t ioport_read1(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read1(s, addr - s->region[1]);
+}
+
+static uint32_t ioport_read2(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    return eepro100_read2(s, addr - s->region[1]);
+}
+
+static uint32_t ioport_read4(void *opaque, uint32_t addr)
+{
+    EEPRO100State *s = opaque;
+    return eepro100_read4(s, addr - s->region[1]);
+}
+
+static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write1(s, addr - s->region[1], val);
+}
+
+static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    eepro100_write2(s, addr - s->region[1], val);
+}
+
+static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    eepro100_write4(s, addr - s->region[1], val);
+}
+
+/***********************************************************/
+/* PCI EEPRO100 definitions */
+
+typedef struct PCIEEPRO100State {
+    PCIDevice dev;
+    EEPRO100State eepro100;
+} PCIEEPRO100State;
+
+static void pci_map(PCIDevice * pci_dev, int region_num,
+                    uint32_t addr, uint32_t size, int type)
+{
+    PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev;
+    EEPRO100State *s = &d->eepro100;
+
+    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+           region_num, addr, size, type);
+
+    assert(region_num == 1);
+    register_ioport_write(addr, size, 1, ioport_write1, s);
+    register_ioport_read(addr, size, 1, ioport_read1, s);
+    register_ioport_write(addr, size, 2, ioport_write2, s);
+    register_ioport_read(addr, size, 2, ioport_read2, s);
+    register_ioport_write(addr, size, 4, ioport_write4, s);
+    register_ioport_read(addr, size, 4, ioport_read4, s);
+
+    s->region[region_num] = addr;
+}
+
+static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write1(s, addr, val);
+}
+
+static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write2(s, addr, val);
+}
+
+static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
+    eepro100_write4(s, addr, val);
+}
+
+static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read1(s, addr);
+}
+
+static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read2(s, addr);
+}
+
+static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+    EEPRO100State *s = opaque;
+    addr -= s->region[0];
+    //~ logout("addr=%s\n", regname(addr));
+    return eepro100_read4(s, addr);
+}
+
+static CPUWriteMemoryFunc *pci_mmio_write[] = {
+    pci_mmio_writeb,
+    pci_mmio_writew,
+    pci_mmio_writel
+};
+
+static CPUReadMemoryFunc *pci_mmio_read[] = {
+    pci_mmio_readb,
+    pci_mmio_readw,
+    pci_mmio_readl
+};
+
+static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
+                         uint32_t addr, uint32_t size, int type)
+{
+    PCIEEPRO100State *d = (PCIEEPRO100State *) pci_dev;
+
+    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
+           region_num, addr, size, type);
+
+    if (region_num == 0) {
+        /* Map control / status registers. */
+        cpu_register_physical_memory(addr, size, d->eepro100.mmio_index);
+        d->eepro100.region[region_num] = addr;
+    }
+}
+
+static int nic_can_receive(void *opaque)
+{
+    EEPRO100State *s = opaque;
+    logout("%p\n", s);
+    return get_ru_state(s) == ru_ready;
+    //~ return !eepro100_buffer_full(s);
+}
+
+#define MIN_BUF_SIZE 60
+
+static void nic_receive(void *opaque, const uint8_t * buf, int size)
+{
+    /* TODO:
+     * - Magic packets should set bit 30 in power management driver register.
+     * - Interesting packets should set bit 29 in power management driver register.
+     */
+    EEPRO100State *s = opaque;
+    uint16_t rfd_status = 0xa000;
+    static const uint8_t broadcast_macaddr[6] =
+        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+    /* TODO: check multiple IA bit. */
+    assert(!(s->configuration[20] & BIT(6)));
+
+    if (s->configuration[8] & 0x80) {
+        /* CSMA is disabled. */
+        logout("%p received while CSMA is disabled\n", s);
+        return;
+    } else if (size < 64 && (s->configuration[7] & 1)) {
+        /* Short frame and configuration byte 7/0 (discard short receive) set:
+         * Short frame is discarded */
+        logout("%p received short frame (%d byte)\n", s, size);
+        s->statistics.rx_short_frame_errors++;
+        //~ return;
+    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) {
+        /* Long frame and configuration byte 18/3 (long receive ok) not set:
+         * Long frames are discarded. */
+        logout("%p received long frame (%d byte), ignored\n", s, size);
+        return;
+    } else if (memcmp(buf, s->macaddr, 6) == 0) {       // !!!
+        /* Frame matches individual address. */
+        /* TODO: check configuration byte 15/4 (ignore U/L). */
+        logout("%p received frame for me, len=%d\n", s, size);
+    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
+        /* Broadcast frame. */
+        logout("%p received broadcast, len=%d\n", s, size);
+        rfd_status |= 0x0002;
+    } else if (buf[0] & 0x01) { // !!!
+        /* Multicast frame. */
+        logout("%p received multicast, len=%d\n", s, size);
+        /* TODO: check multicast all bit. */
+        assert(!(s->configuration[21] & BIT(3)));
+        int mcast_idx = compute_mcast_idx(buf);
+        if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) {
+            return;
+        }
+        rfd_status |= 0x0002;
+    } else if (s->configuration[15] & 1) {
+        /* Promiscuous: receive all. */
+        logout("%p received frame in promiscuous mode, len=%d\n", s, size);
+        rfd_status |= 0x0004;
+    } else {
+        logout("%p received frame, ignored, len=%d,%s\n", s, size,
+               nic_dump(buf, size));
+        return;
+    }
+
+    if (get_ru_state(s) != ru_ready) {
+        /* No ressources available. */
+        logout("no ressources, state=%u\n", get_ru_state(s));
+        s->statistics.rx_resource_errors++;
+        //~ assert(!"no ressources");
+        return;
+    }
+    //~ !!!
+//~ $3 = {status = 0x0, command = 0xc000, link = 0x2d220, rx_buf_addr = 0x207dc, count = 0x0, size = 0x5f8, packet = {0x0 <repeats 1518 times>}}
+    eepro100_rx_t rx;
+    cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
+                             offsetof(eepro100_rx_t, packet));
+    uint16_t rfd_command = le16_to_cpu(rx.command);
+    uint16_t rfd_size = le16_to_cpu(rx.size);
+    assert(size <= rfd_size);
+    if (size < 64) {
+        rfd_status |= 0x0080;
+    }
+    logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command,
+           rx.link, rx.rx_buf_addr, rfd_size);
+    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
+             rfd_status);
+    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
+    /* Early receive interrupt not supported. */
+    //~ eepro100_er_interrupt(s);
+    /* Receive CRC Transfer not supported. */
+    assert(!(s->configuration[18] & 4));
+    /* TODO: check stripping enable bit. */
+    //~ assert(!(s->configuration[17] & 1));
+    cpu_physical_memory_write(s->ru_base + s->ru_offset +
+                              offsetof(eepro100_rx_t, packet), buf, size);
+    s->statistics.rx_good_frames++;
+    eepro100_fr_interrupt(s);
+    s->ru_offset = le32_to_cpu(rx.link);
+    if (rfd_command & 0x8000) {
+        /* EL bit is set, so this was the last frame. */
+        assert(0);
+    }
+    if (rfd_command & 0x4000) {
+        /* S bit is set. */
+        set_ru_state(s, ru_suspended);
+    }
+}
+
+static int nic_load(QEMUFile * f, void *opaque, int version_id)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+    int ret;
+
+    missing("NIC load");
+
+    if (version_id > 3)
+        return -EINVAL;
+
+    if (s->pci_dev && version_id >= 3) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
+    if (version_id >= 2) {
+        qemu_get_8s(f, &s->rxcr);
+    } else {
+        s->rxcr = 0x0c;
+    }
+
+    qemu_get_8s(f, &s->cmd);
+    qemu_get_be32s(f, &s->start);
+    qemu_get_be32s(f, &s->stop);
+    qemu_get_8s(f, &s->boundary);
+    qemu_get_8s(f, &s->tsr);
+    qemu_get_8s(f, &s->tpsr);
+    qemu_get_be16s(f, &s->tcnt);
+    qemu_get_be16s(f, &s->rcnt);
+    qemu_get_be32s(f, &s->rsar);
+    qemu_get_8s(f, &s->rsr);
+    qemu_get_8s(f, &s->isr);
+    qemu_get_8s(f, &s->dcfg);
+    qemu_get_8s(f, &s->imr);
+    qemu_get_buffer(f, s->phys, 6);
+    qemu_get_8s(f, &s->curpag);
+    qemu_get_buffer(f, s->mult, 8);
+    qemu_get_buffer(f, s->mem, sizeof(s->mem));
+
+    return 0;
+}
+
+static void nic_save(QEMUFile * f, void *opaque)
+{
+    EEPRO100State *s = (EEPRO100State *) opaque;
+
+    missing("NIC save");
+
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
+    qemu_put_8s(f, &s->rxcr);
+
+    qemu_put_8s(f, &s->cmd);
+    qemu_put_be32s(f, &s->start);
+    qemu_put_be32s(f, &s->stop);
+    qemu_put_8s(f, &s->boundary);
+    qemu_put_8s(f, &s->tsr);
+    qemu_put_8s(f, &s->tpsr);
+    qemu_put_be16s(f, &s->tcnt);
+    qemu_put_be16s(f, &s->rcnt);
+    qemu_put_be32s(f, &s->rsar);
+    qemu_put_8s(f, &s->rsr);
+    qemu_put_8s(f, &s->isr);
+    qemu_put_8s(f, &s->dcfg);
+    qemu_put_8s(f, &s->imr);
+    qemu_put_buffer(f, s->phys, 6);
+    qemu_put_8s(f, &s->curpag);
+    qemu_put_buffer(f, s->mult, 8);
+    qemu_put_buffer(f, s->mem, sizeof(s->mem));
+}
+
+static void nic_init(PCIBus * bus, NICInfo * nd,
+                     const char *name, uint32_t device)
+{
+    PCIEEPRO100State *d;
+    EEPRO100State *s;
+
+    logout("\n");
+
+    d = (PCIEEPRO100State *) pci_register_device(bus, name,
+                                                 sizeof(PCIEEPRO100State), -1,
+                                                 NULL, NULL);
+
+    s = &d->eepro100;
+    s->device = device;
+    s->pci_dev = &d->dev;
+
+    pci_reset(s);
+
+    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
+     * i82559 and later support 64 or 256 word EEPROM. */
+    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
+
+    /* Handler for memory-mapped I/O */
+    d->eepro100.mmio_index =
+        cpu_register_io_memory(0, pci_mmio_read, pci_mmio_write, s);
+
+    pci_register_io_region(&d->dev, 0, PCI_MEM_SIZE,
+                           PCI_ADDRESS_SPACE_MEM |
+                           PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_mmio_map);
+    pci_register_io_region(&d->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO,
+                           pci_map);
+    pci_register_io_region(&d->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM,
+                           pci_mmio_map);
+
+    memcpy(s->macaddr, nd->macaddr, 6);
+    logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));
+    assert(s->region[1] == 0);
+
+    nic_reset(s);
+
+    s->vc = qemu_new_vlan_client(nd->vlan, nic_receive, nic_can_receive, s);
+
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+             "eepro100 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             s->macaddr[0],
+             s->macaddr[1],
+             s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]);
+
+    qemu_register_reset(nic_reset, s);
+
+    /* XXX: instance number ? */
+    register_savevm(name, 0, 3, nic_save, nic_load, s);
+}
+
+void pci_i82551_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82551", i82551);
+    //~ uint8_t *pci_conf = d->dev.config;
+}
+
+void pci_i82557b_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82557b", i82557B);
+}
+
+void pci_i82559er_init(PCIBus * bus, NICInfo * nd, int devfn)
+{
+    nic_init(bus, nd, "i82559er", i82559ER);
+}
+
+/* eof */

Added: trunk/src/host/qemu-neo1973/hw/eeprom93xx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eeprom93xx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eeprom93xx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,312 @@
+/*
+ * QEMU EEPROM 93xx emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/* Emulation for serial EEPROMs:
+ * NMC93C06 256-Bit (16 x 16)
+ * NMC93C46 1024-Bit (64 x 16)
+ * NMC93C56 2028 Bit (128 x 16)
+ * NMC93C66 4096 Bit (256 x 16)
+ * Compatible devices include FM93C46 and others.
+ *
+ * Other drivers use these interface functions:
+ * eeprom93xx_new   - add a new EEPROM (with 16, 64 or 256 words)
+ * eeprom93xx_free  - destroy EEPROM
+ * eeprom93xx_read  - read data from the EEPROM
+ * eeprom93xx_write - write data to the EEPROM
+ * eeprom93xx_data  - get EEPROM data array for external manipulation
+ *
+ * Todo list:
+ * - No emulation of EEPROM timings.
+ */
+
+#include <assert.h>
+#include "eeprom93xx.h"
+
+/* Debug EEPROM emulation. */
+//~ #define DEBUG_EEPROM
+
+#ifdef DEBUG_EEPROM
+#define logout(fmt, args...) fprintf(stderr, "EEPROM\t%-24s" fmt, __func__, ##args)
+#else
+#define logout(fmt, args...) ((void)0)
+#endif
+
+static int eeprom_instance = 0;
+static const int eeprom_version = 20061112;
+
+#if 0
+typedef enum {
+  eeprom_read  = 0x80,   /* read register xx */
+  eeprom_write = 0x40,   /* write register xx */
+  eeprom_erase = 0xc0,   /* erase register xx */
+  eeprom_ewen  = 0x30,   /* erase / write enable */
+  eeprom_ewds  = 0x00,   /* erase / write disable */
+  eeprom_eral  = 0x20,   /* erase all registers */
+  eeprom_wral  = 0x10,   /* write all registers */
+  eeprom_amask = 0x0f,
+  eeprom_imask = 0xf0
+} eeprom_instruction_t;
+#endif
+
+#ifdef DEBUG_EEPROM
+static const char *opstring[] = {
+  "extended", "write", "read", "erase"
+};
+#endif
+
+struct _eeprom_t {
+    uint8_t  tick;
+    uint8_t  address;
+    uint8_t  command;
+    uint8_t  writeable;
+
+    uint8_t eecs;
+    uint8_t eesk;
+    uint8_t eedo;
+
+    uint8_t  addrbits;
+    uint8_t  size;
+    uint16_t data;
+    uint16_t contents[0];
+};
+
+/* Code for saving and restoring of EEPROM state. */
+
+static void eeprom_save(QEMUFile *f, void *opaque)
+{
+    /* Save EEPROM data. */
+    unsigned address;
+    eeprom_t *eeprom = (eeprom_t *)opaque;
+    qemu_put_buffer(f, (uint8_t *)eeprom, sizeof(*eeprom) - 2);
+    qemu_put_be16(f, eeprom->data);
+    for (address = 0; address < eeprom->size; address++) {
+        qemu_put_be16(f, eeprom->contents[address]);
+    }
+}
+
+static int eeprom_load(QEMUFile *f, void *opaque, int version_id)
+{
+    /* Load EEPROM data from saved data if version and EEPROM size
+       of data and current EEPROM are identical. */
+    eeprom_t *eeprom = (eeprom_t *)opaque;
+    int result = -EINVAL;
+    if (version_id == eeprom_version) {
+        unsigned address;
+        uint8_t size = eeprom->size;
+        qemu_get_buffer(f, (uint8_t *)eeprom, sizeof(*eeprom) - 2);
+        if (eeprom->size == size) {
+            eeprom->data = qemu_get_be16(f);
+            for (address = 0; address < eeprom->size; address++) {
+                eeprom->contents[address] = qemu_get_be16(f);
+            }
+            result = 0;
+        }
+    }
+    return result;
+}
+
+void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
+{
+    uint8_t tick = eeprom->tick;
+    uint8_t eedo = eeprom->eedo;
+    uint16_t address = eeprom->address;
+    uint8_t command = eeprom->command;
+
+    logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
+           eecs, eesk, eedi, eedo, tick);
+
+    if (! eeprom->eecs && eecs) {
+        /* Start chip select cycle. */
+        logout("Cycle start, waiting for 1st start bit (0)\n");
+        tick = 0;
+        command = 0x0;
+        address = 0x0;
+    } else if (eeprom->eecs && ! eecs) {
+        /* End chip select cycle. This triggers write / erase. */
+        if (eeprom->writeable) {
+            uint8_t subcommand = address >> (eeprom->addrbits - 2);
+            if (command == 0 && subcommand == 2) {
+                /* Erase all. */
+                for (address = 0; address < eeprom->size; address++) {
+                    eeprom->contents[address] = 0xffff;
+                }
+            } else if (command == 3) {
+                /* Erase word. */
+                eeprom->contents[address] = 0xffff;
+            } else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
+                if (command == 1) {
+                    /* Write word. */
+                    eeprom->contents[address] &= eeprom->data;
+                } else if (command == 0 && subcommand == 1) {
+                    /* Write all. */
+                    for (address = 0; address < eeprom->size; address++) {
+                        eeprom->contents[address] &= eeprom->data;
+                    }
+                }
+            }
+        }
+        /* Output DO is tristate, read results in 1. */
+        eedo = 1;
+    } else if (eecs && ! eeprom->eesk && eesk) {
+        /* Raising edge of clock shifts data in. */
+        if (tick == 0) {
+            /* Wait for 1st start bit. */
+            if (eedi == 0) {
+                logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n");
+                tick++;
+            } else {
+                logout("wrong 1st start bit (is 1, should be 0)\n");
+                tick = 2;
+                //~ assert(!"wrong start bit");
+            }
+        } else if (tick == 1) {
+            /* Wait for 2nd start bit. */
+            if (eedi != 0) {
+                logout("Got correct 2nd start bit, getting command + address\n");
+                tick++;
+            } else {
+                logout("1st start bit is longer than needed\n");
+            }
+        } else if (tick < 2 + 2) {
+            /* Got 2 start bits, transfer 2 opcode bits. */
+            tick++;
+            command <<= 1;
+            if (eedi) {
+                command += 1;
+            }
+        } else if (tick < 2 + 2 + eeprom->addrbits) {
+            /* Got 2 start bits and 2 opcode bits, transfer all address bits. */
+            tick++;
+            address = ((address << 1) | eedi);
+            if (tick == 2 + 2 + eeprom->addrbits) {
+                logout("%s command, address = 0x%02x (value 0x%04x)\n",
+                       opstring[command], address, eeprom->contents[address]);
+                if (command == 2) {
+                    eedo = 0;
+                }
+                address = address % eeprom->size;
+                if (command == 0) {
+                    /* Command code in upper 2 bits of address. */
+                    switch (address >> (eeprom->addrbits - 2)) {
+                        case 0:
+                            logout("write disable command\n");
+                            eeprom->writeable = 0;
+                            break;
+                        case 1:
+                            logout("write all command\n");
+                            break;
+                        case 2:
+                            logout("erase all command\n");
+                            break;
+                        case 3:
+                            logout("write enable command\n");
+                            eeprom->writeable = 1;
+                            break;
+                    }
+                } else {
+                    /* Read, write or erase word. */
+                    eeprom->data = eeprom->contents[address];
+                }
+            }
+        } else if (tick < 2 + 2 + eeprom->addrbits + 16) {
+            /* Transfer 16 data bits. */
+            tick++;
+            if (command == 2) {
+                /* Read word. */
+                eedo = ((eeprom->data & 0x8000) != 0);
+            }
+            eeprom->data <<= 1;
+            eeprom->data += eedi;
+        } else {
+            logout("additional unneeded tick, not processed\n");
+        }
+    }
+    /* Save status of EEPROM. */
+    eeprom->tick = tick;
+    eeprom->eecs = eecs;
+    eeprom->eesk = eesk;
+    eeprom->eedo = eedo;
+    eeprom->address = address;
+    eeprom->command = command;
+}
+
+uint16_t eeprom93xx_read(eeprom_t *eeprom)
+{
+    /* Return status of pin DO (0 or 1). */
+    logout("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo);
+    return (eeprom->eedo);
+}
+
+#if 0
+void eeprom93xx_reset(eeprom_t *eeprom)
+{
+    /* prepare eeprom */
+    logout("eeprom = 0x%p\n", eeprom);
+    eeprom->tick = 0;
+    eeprom->command = 0;
+}
+#endif
+
+eeprom_t *eeprom93xx_new(uint16_t nwords)
+{
+    /* Add a new EEPROM (with 16, 64 or 256 words). */
+    eeprom_t *eeprom;
+    uint8_t addrbits;
+
+    switch (nwords) {
+        case 16:
+        case 64:
+            addrbits = 6;
+            break;
+        case 128:
+        case 256:
+            addrbits = 8;
+            break;
+        default:
+            assert(!"Unsupported EEPROM size, fallback to 64 words!");
+            nwords = 64;
+            addrbits = 6;
+    }
+
+    eeprom = (eeprom_t *)qemu_mallocz(sizeof(*eeprom) + nwords * 2);
+    eeprom->size = nwords;
+    eeprom->addrbits = addrbits;
+    /* Output DO is tristate, read results in 1. */
+    eeprom->eedo = 1;
+    logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
+    register_savevm("eeprom", eeprom_instance, eeprom_version,
+                    eeprom_save, eeprom_load, eeprom);
+    return eeprom;
+}
+
+void eeprom93xx_free(eeprom_t *eeprom)
+{
+    /* Destroy EEPROM. */
+    logout("eeprom = 0x%p\n", eeprom);
+    qemu_free(eeprom);
+}
+
+uint16_t *eeprom93xx_data(eeprom_t *eeprom)
+{
+    /* Get EEPROM data array. */
+    return &eeprom->contents[0];
+}
+
+/* eof */

Added: trunk/src/host/qemu-neo1973/hw/eeprom93xx.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/eeprom93xx.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/eeprom93xx.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,43 @@
+/*
+ * QEMU EEPROM 93xx emulation
+ *
+ * Copyright (c) 2006-2007 Stefan Weil
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef EEPROM93XX_H
+#define EEPROM93XX_H
+
+#include "vl.h"
+
+typedef struct _eeprom_t eeprom_t;
+
+/* Create a new EEPROM with (nwords * 2) bytes. */
+eeprom_t *eeprom93xx_new(uint16_t nwords);
+
+/* Destroy an existing EEPROM. */
+void eeprom93xx_free(eeprom_t *eeprom);
+
+/* Read from the EEPROM. */
+uint16_t eeprom93xx_read(eeprom_t *eeprom);
+
+/* Write to the EEPROM. */
+void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi);
+
+/* Get EEPROM data array. */
+uint16_t *eeprom93xx_data(eeprom_t *eeprom);
+
+#endif /* EEPROM93XX_H */

Modified: trunk/src/host/qemu-neo1973/hw/es1370.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/es1370.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/es1370.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -324,7 +324,7 @@
     else {
         s->status = new_status & ~STAT_INTR;
     }
-    pci_set_irq (s->pci_dev, 0, !!level);
+    qemu_set_irq(s->pci_dev->irq[0], !!level);
 }
 
 static void es1370_reset (ES1370State *s)
@@ -350,7 +350,7 @@
             s->dac_voice[i] = NULL;
         }
     }
-    pci_set_irq (s->pci_dev, 0, 0);
+    qemu_irq_lower(s->pci_dev->irq[0]);
 }
 
 static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)

Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/esp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -507,15 +507,21 @@
     qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);
     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
+    qemu_put_be32s(f, &s->sense);
     qemu_put_be32s(f, &s->dma);
+    qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
+    qemu_put_be32s(f, &s->cmdlen);
+    qemu_put_be32s(f, &s->do_cmd);
+    qemu_put_be32s(f, &s->dma_left);
+    // There should be no transfers in progress, so dma_counter is not saved
 }
 
 static int esp_load(QEMUFile *f, void *opaque, int version_id)
 {
     ESPState *s = opaque;
     
-    if (version_id != 2)
-        return -EINVAL; // Cannot emulate 1
+    if (version_id != 3)
+        return -EINVAL; // Cannot emulate 2
 
     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
@@ -523,7 +529,12 @@
     qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);
     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
+    qemu_get_be32s(f, &s->sense);
     qemu_get_be32s(f, &s->dma);
+    qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
+    qemu_get_be32s(f, &s->cmdlen);
+    qemu_get_be32s(f, &s->do_cmd);
+    qemu_get_be32s(f, &s->dma_left);
 
     return 0;
 }
@@ -568,7 +579,7 @@
 
     esp_reset(s);
 
-    register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
+    register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
     qemu_register_reset(esp_reset, s);
 
     return s;

Modified: trunk/src/host/qemu-neo1973/hw/fdc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/fdc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/fdc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU Floppy disk emulator (Intel 82078)
  * 
- * Copyright (c) 2003 Jocelyn Mayer
+ * Copyright (c) 2003, 2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -368,7 +368,7 @@
     /* Controller's identification */
     uint8_t version;
     /* HW */
-    int irq_lvl;
+    qemu_irq irq;
     int dma_chann;
     uint32_t io_base;
     /* Controller state */
@@ -485,7 +485,100 @@
     fdctrl_write_mem,
 };
 
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
+static void fd_save (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    tmp = fd->drflags;
+    qemu_put_8s(f, &tmp);
+    qemu_put_8s(f, &fd->head);
+    qemu_put_8s(f, &fd->track);
+    qemu_put_8s(f, &fd->sect);
+    qemu_put_8s(f, &fd->dir);
+    qemu_put_8s(f, &fd->rw);
+}
+
+static void fdc_save (QEMUFile *f, void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    qemu_put_8s(f, &s->state);
+    qemu_put_8s(f, &s->dma_en);
+    qemu_put_8s(f, &s->cur_drv);
+    qemu_put_8s(f, &s->bootsel);
+    qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_put_be32s(f, &s->data_pos);
+    qemu_put_be32s(f, &s->data_len);
+    qemu_put_8s(f, &s->data_state);
+    qemu_put_8s(f, &s->data_dir);
+    qemu_put_8s(f, &s->int_status);
+    qemu_put_8s(f, &s->eot);
+    qemu_put_8s(f, &s->timer0);
+    qemu_put_8s(f, &s->timer1);
+    qemu_put_8s(f, &s->precomp_trk);
+    qemu_put_8s(f, &s->config);
+    qemu_put_8s(f, &s->lock);
+    qemu_put_8s(f, &s->pwrd);
+    fd_save(f, &s->drives[0]);
+    fd_save(f, &s->drives[1]);
+}
+
+static int fd_load (QEMUFile *f, fdrive_t *fd)
+{
+    uint8_t tmp;
+
+    qemu_get_8s(f, &tmp);
+    fd->drflags = tmp;
+    qemu_get_8s(f, &fd->head);
+    qemu_get_8s(f, &fd->track);
+    qemu_get_8s(f, &fd->sect);
+    qemu_get_8s(f, &fd->dir);
+    qemu_get_8s(f, &fd->rw);
+
+    return 0;
+}
+
+static int fdc_load (QEMUFile *f, void *opaque, int version_id)
+{
+    fdctrl_t *s = opaque;
+    int ret;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->state);
+    qemu_get_8s(f, &s->dma_en);
+    qemu_get_8s(f, &s->cur_drv);
+    qemu_get_8s(f, &s->bootsel);
+    qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
+    qemu_get_be32s(f, &s->data_pos);
+    qemu_get_be32s(f, &s->data_len);
+    qemu_get_8s(f, &s->data_state);
+    qemu_get_8s(f, &s->data_dir);
+    qemu_get_8s(f, &s->int_status);
+    qemu_get_8s(f, &s->eot);
+    qemu_get_8s(f, &s->timer0);
+    qemu_get_8s(f, &s->timer1);
+    qemu_get_8s(f, &s->precomp_trk);
+    qemu_get_8s(f, &s->config);
+    qemu_get_8s(f, &s->lock);
+    qemu_get_8s(f, &s->pwrd);
+
+    ret = fd_load(f, &s->drives[0]);
+    if (ret == 0)
+        ret = fd_load(f, &s->drives[1]);
+
+    return ret;
+}
+
+static void fdctrl_external_reset(void *opaque)
+{
+    fdctrl_t *s = opaque;
+
+    fdctrl_reset(s, 0);
+}
+
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, 
                        uint32_t io_base,
                        BlockDriverState **fds)
 {
@@ -501,7 +594,7 @@
                                           fdctrl_result_timer, fdctrl);
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
-    fdctrl->irq_lvl = irq_lvl;
+    fdctrl->irq = irq;
     fdctrl->dma_chann = dma_chann;
     fdctrl->io_base = io_base;
     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
@@ -525,6 +618,8 @@
         register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
         register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
     }
+    register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
+    qemu_register_reset(fdctrl_external_reset, fdctrl);
     for (i = 0; i < 2; i++) {
         fd_revalidate(&fdctrl->drives[i]);
     }
@@ -542,7 +637,7 @@
 static void fdctrl_reset_irq (fdctrl_t *fdctrl)
 {
     FLOPPY_DPRINTF("Reset interrupt\n");
-    pic_set_irq(fdctrl->irq_lvl, 0);
+    qemu_set_irq(fdctrl->irq, 0);
     fdctrl->state &= ~FD_CTRL_INTR;
 }
 
@@ -557,7 +652,7 @@
     }
 #endif
     if (~(fdctrl->state & FD_CTRL_INTR)) {
-        pic_set_irq(fdctrl->irq_lvl, 1);
+        qemu_set_irq(fdctrl->irq, 1);
         fdctrl->state |= FD_CTRL_INTR;
     }
     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);

Modified: trunk/src/host/qemu-neo1973/hw/grackle_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/grackle_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -80,12 +80,12 @@
     return (irq_num + (pci_dev->devfn >> 3)) & 3;
 }
 
-static void pci_grackle_set_irq(void *pic, int irq_num, int level)
+static void pci_grackle_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    heathrow_pic_set_irq(pic, irq_num + 8, level);
+    qemu_set_irq(pic[irq_num + 8], level);
 }
 
-PCIBus *pci_grackle_init(uint32_t base, void *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
 {
     GrackleState *s;
     PCIDevice *d;

Added: trunk/src/host/qemu-neo1973/hw/gt64xxx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/gt64xxx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,673 @@
+/*
+ * QEMU GT64120 PCI host
+ *
+ * Copyright (c) 2006,2007 Aurelien Jarno
+ * 
+ * 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 "vl.h"
+typedef target_phys_addr_t pci_addr_t;
+#include "pci_host.h"
+
+#define GT_REGS			(0x1000 >> 2)
+
+/* CPU Configuration */
+#define GT_CPU    		(0x000 >> 2)
+#define GT_MULTI    		(0x120 >> 2)
+
+/* CPU Address Decode */
+#define GT_SCS10LD    		(0x008 >> 2)
+#define GT_SCS10HD    		(0x010 >> 2)
+#define GT_SCS32LD    		(0x018 >> 2)
+#define GT_SCS32HD    		(0x020 >> 2)
+#define GT_CS20LD    		(0x028 >> 2)
+#define GT_CS20HD    		(0x030 >> 2)
+#define GT_CS3BOOTLD    	(0x038 >> 2)
+#define GT_CS3BOOTHD    	(0x040 >> 2)
+#define GT_PCI0IOLD    		(0x048 >> 2)
+#define GT_PCI0IOHD    		(0x050 >> 2)
+#define GT_PCI0M0LD    		(0x058 >> 2)
+#define GT_PCI0M0HD    		(0x060 >> 2)
+#define GT_ISD    		(0x068 >> 2)
+
+#define GT_PCI0M1LD    		(0x080 >> 2)
+#define GT_PCI0M1HD    		(0x088 >> 2)
+#define GT_PCI1IOLD    		(0x090 >> 2)
+#define GT_PCI1IOHD    		(0x098 >> 2)
+#define GT_PCI1M0LD    		(0x0a0 >> 2)
+#define GT_PCI1M0HD    		(0x0a8 >> 2)
+#define GT_PCI1M1LD    		(0x0b0 >> 2)
+#define GT_PCI1M1HD    		(0x0b8 >> 2)
+#define GT_PCI1M1LD    		(0x0b0 >> 2)
+#define GT_PCI1M1HD    		(0x0b8 >> 2)
+
+#define GT_SCS10AR    		(0x0d0 >> 2)
+#define GT_SCS32AR    		(0x0d8 >> 2)
+#define GT_CS20R    		(0x0e0 >> 2)
+#define GT_CS3BOOTR    		(0x0e8 >> 2)
+
+#define GT_PCI0IOREMAP    	(0x0f0 >> 2)
+#define GT_PCI0M0REMAP    	(0x0f8 >> 2)
+#define GT_PCI0M1REMAP    	(0x100 >> 2)
+#define GT_PCI1IOREMAP    	(0x108 >> 2)
+#define GT_PCI1M0REMAP    	(0x110 >> 2)
+#define GT_PCI1M1REMAP    	(0x118 >> 2)
+
+/* CPU Error Report */
+#define GT_CPUERR_ADDRLO    	(0x070 >> 2)
+#define GT_CPUERR_ADDRHI    	(0x078 >> 2)
+#define GT_CPUERR_DATALO    	(0x128 >> 2)		/* GT-64120A only  */
+#define GT_CPUERR_DATAHI    	(0x130 >> 2)		/* GT-64120A only  */
+#define GT_CPUERR_PARITY    	(0x138 >> 2)		/* GT-64120A only  */
+
+/* CPU Sync Barrier */
+#define GT_PCI0SYNC    		(0x0c0 >> 2)
+#define GT_PCI1SYNC    		(0x0c8 >> 2)
+
+/* SDRAM and Device Address Decode */
+#define GT_SCS0LD    		(0x400 >> 2)
+#define GT_SCS0HD    		(0x404 >> 2)
+#define GT_SCS1LD    		(0x408 >> 2)
+#define GT_SCS1HD    		(0x40c >> 2)
+#define GT_SCS2LD    		(0x410 >> 2)
+#define GT_SCS2HD    		(0x414 >> 2)
+#define GT_SCS3LD    		(0x418 >> 2)
+#define GT_SCS3HD    		(0x41c >> 2)
+#define GT_CS0LD    		(0x420 >> 2)
+#define GT_CS0HD    		(0x424 >> 2)
+#define GT_CS1LD    		(0x428 >> 2)
+#define GT_CS1HD    		(0x42c >> 2)
+#define GT_CS2LD    		(0x430 >> 2)
+#define GT_CS2HD    		(0x434 >> 2)
+#define GT_CS3LD    		(0x438 >> 2)
+#define GT_CS3HD    		(0x43c >> 2)
+#define GT_BOOTLD    		(0x440 >> 2)
+#define GT_BOOTHD    		(0x444 >> 2)
+#define GT_ADERR    		(0x470 >> 2)
+
+/* SDRAM Configuration */
+#define GT_SDRAM_CFG    	(0x448 >> 2)
+#define GT_SDRAM_OPMODE    	(0x474 >> 2)
+#define GT_SDRAM_BM    		(0x478 >> 2)
+#define GT_SDRAM_ADDRDECODE    	(0x47c >> 2)
+
+/* SDRAM Parameters */
+#define GT_SDRAM_B0    		(0x44c >> 2)
+#define GT_SDRAM_B1    		(0x450 >> 2)
+#define GT_SDRAM_B2    		(0x454 >> 2)
+#define GT_SDRAM_B3    		(0x458 >> 2)
+
+/* Device Parameters */
+#define GT_DEV_B0    		(0x45c >> 2)
+#define GT_DEV_B1    		(0x460 >> 2)
+#define GT_DEV_B2    		(0x464 >> 2)
+#define GT_DEV_B3    		(0x468 >> 2)
+#define GT_DEV_BOOT    		(0x46c >> 2)
+
+/* ECC */
+#define GT_ECC_ERRDATALO	(0x480 >> 2)		/* GT-64120A only  */
+#define GT_ECC_ERRDATAHI	(0x484 >> 2)		/* GT-64120A only  */
+#define GT_ECC_MEM		(0x488 >> 2)		/* GT-64120A only  */
+#define GT_ECC_CALC		(0x48c >> 2)		/* GT-64120A only  */
+#define GT_ECC_ERRADDR		(0x490 >> 2)		/* GT-64120A only  */
+
+/* DMA Record */
+#define GT_DMA0_CNT    		(0x800 >> 2)
+#define GT_DMA1_CNT    		(0x804 >> 2)
+#define GT_DMA2_CNT    		(0x808 >> 2)
+#define GT_DMA3_CNT    		(0x80c >> 2)
+#define GT_DMA0_SA    		(0x810 >> 2)
+#define GT_DMA1_SA    		(0x814 >> 2)
+#define GT_DMA2_SA    		(0x818 >> 2)
+#define GT_DMA3_SA    		(0x81c >> 2)
+#define GT_DMA0_DA    		(0x820 >> 2)
+#define GT_DMA1_DA    		(0x824 >> 2)
+#define GT_DMA2_DA    		(0x828 >> 2)
+#define GT_DMA3_DA    		(0x82c >> 2)
+#define GT_DMA0_NEXT    	(0x830 >> 2)
+#define GT_DMA1_NEXT    	(0x834 >> 2)
+#define GT_DMA2_NEXT    	(0x838 >> 2)
+#define GT_DMA3_NEXT    	(0x83c >> 2)
+#define GT_DMA0_CUR    		(0x870 >> 2)
+#define GT_DMA1_CUR    		(0x874 >> 2)
+#define GT_DMA2_CUR    		(0x878 >> 2)
+#define GT_DMA3_CUR    		(0x87c >> 2)
+
+/* DMA Channel Control */
+#define GT_DMA0_CTRL    	(0x840 >> 2)
+#define GT_DMA1_CTRL    	(0x844 >> 2)
+#define GT_DMA2_CTRL    	(0x848 >> 2)
+#define GT_DMA3_CTRL    	(0x84c >> 2)
+
+/* DMA Arbiter */
+#define GT_DMA_ARB    		(0x860 >> 2)
+
+/* Timer/Counter */
+#define GT_TC0    		(0x850 >> 2)
+#define GT_TC1    		(0x854 >> 2)
+#define GT_TC2    		(0x858 >> 2)
+#define GT_TC3    		(0x85c >> 2)
+#define GT_TC_CONTROL    	(0x864 >> 2)
+
+/* PCI Internal */
+#define GT_PCI0_CMD    		(0xc00 >> 2)
+#define GT_PCI0_TOR    		(0xc04 >> 2)
+#define GT_PCI0_BS_SCS10    	(0xc08 >> 2)
+#define GT_PCI0_BS_SCS32    	(0xc0c >> 2)
+#define GT_PCI0_BS_CS20    	(0xc10 >> 2)
+#define GT_PCI0_BS_CS3BT    	(0xc14 >> 2)
+#define GT_PCI1_IACK    	(0xc30 >> 2)
+#define GT_PCI0_IACK    	(0xc34 >> 2)
+#define GT_PCI0_BARE    	(0xc3c >> 2)
+#define GT_PCI0_PREFMBR    	(0xc40 >> 2)
+#define GT_PCI0_SCS10_BAR    	(0xc48 >> 2)
+#define GT_PCI0_SCS32_BAR    	(0xc4c >> 2)
+#define GT_PCI0_CS20_BAR    	(0xc50 >> 2)
+#define GT_PCI0_CS3BT_BAR    	(0xc54 >> 2)
+#define GT_PCI0_SSCS10_BAR    	(0xc58 >> 2)
+#define GT_PCI0_SSCS32_BAR    	(0xc5c >> 2)
+#define GT_PCI0_SCS3BT_BAR    	(0xc64 >> 2)
+#define GT_PCI1_CMD    		(0xc80 >> 2)
+#define GT_PCI1_TOR    		(0xc84 >> 2)
+#define GT_PCI1_BS_SCS10    	(0xc88 >> 2)
+#define GT_PCI1_BS_SCS32    	(0xc8c >> 2)
+#define GT_PCI1_BS_CS20    	(0xc90 >> 2)
+#define GT_PCI1_BS_CS3BT    	(0xc94 >> 2)
+#define GT_PCI1_BARE    	(0xcbc >> 2)
+#define GT_PCI1_PREFMBR    	(0xcc0 >> 2)
+#define GT_PCI1_SCS10_BAR    	(0xcc8 >> 2)
+#define GT_PCI1_SCS32_BAR    	(0xccc >> 2)
+#define GT_PCI1_CS20_BAR    	(0xcd0 >> 2)
+#define GT_PCI1_CS3BT_BAR    	(0xcd4 >> 2)
+#define GT_PCI1_SSCS10_BAR    	(0xcd8 >> 2)
+#define GT_PCI1_SSCS32_BAR    	(0xcdc >> 2)
+#define GT_PCI1_SCS3BT_BAR    	(0xce4 >> 2)
+#define GT_PCI1_CFGADDR    	(0xcf0 >> 2)
+#define GT_PCI1_CFGDATA    	(0xcf4 >> 2)
+#define GT_PCI0_CFGADDR    	(0xcf8 >> 2)
+#define GT_PCI0_CFGDATA    	(0xcfc >> 2)
+
+/* Interrupts */
+#define GT_INTRCAUSE    	(0xc18 >> 2)
+#define GT_INTRMASK    		(0xc1c >> 2)
+#define GT_PCI0_ICMASK    	(0xc24 >> 2)
+#define GT_PCI0_SERR0MASK    	(0xc28 >> 2)
+#define GT_CPU_INTSEL    	(0xc70 >> 2)
+#define GT_PCI0_INTSEL    	(0xc74 >> 2)
+#define GT_HINTRCAUSE    	(0xc98 >> 2)
+#define GT_HINTRMASK    	(0xc9c >> 2)
+#define GT_PCI0_HICMASK    	(0xca4 >> 2)
+#define GT_PCI1_SERR1MASK    	(0xca8 >> 2)
+
+
+typedef PCIHostState GT64120PCIState;
+
+typedef struct GT64120State {
+    GT64120PCIState *pci;
+    uint32_t regs[GT_REGS];
+    target_phys_addr_t PCI0IO_start;
+    target_phys_addr_t PCI0IO_length;
+} GT64120State;
+
+static void gt64120_pci_mapping(GT64120State *s)
+{
+    /* Update IO mapping */
+    if ((s->regs[GT_PCI0IOLD] & 0x7f) <= s->regs[GT_PCI0IOHD])
+    {
+      /* Unmap old IO address */	    
+      if (s->PCI0IO_length)
+      {
+        cpu_register_physical_memory(s->PCI0IO_start, s->PCI0IO_length, IO_MEM_UNASSIGNED);	     
+      }
+      /* Map new IO address */
+      s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
+      s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
+      isa_mem_base = s->PCI0IO_start;
+      isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length);
+    }
+}
+
+static void gt64120_writel (void *opaque, target_phys_addr_t addr,
+                            uint32_t val)
+{
+    GT64120State *s = opaque;
+    uint32_t saddr;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+
+    saddr = (addr & 0xfff) >> 2;
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_CPU:
+        s->regs[GT_CPU] = val;
+        break;
+    case GT_MULTI:
+	/* Read-only register as only one GT64xxx is present on the CPU bus */
+        break;
+
+    /* CPU Address Decode */
+    case GT_PCI0IOLD:
+        s->regs[GT_PCI0IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI0IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M0LD:
+        s->regs[GT_PCI0M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0M1LD:
+        s->regs[GT_PCI0M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI0M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1IOLD:
+        s->regs[GT_PCI1IOLD]    = val & 0x00007fff;
+        s->regs[GT_PCI1IOREMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M0LD:
+        s->regs[GT_PCI1M0LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M0REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI1M1LD:
+        s->regs[GT_PCI1M1LD]    = val & 0x00007fff;
+        s->regs[GT_PCI1M1REMAP] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+        s->regs[saddr] = val & 0x0000007f;
+        gt64120_pci_mapping(s);
+        break;
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        s->regs[saddr] = val & 0x000007ff;
+        gt64120_pci_mapping(s);
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+	/* Read-only registers, do nothing */
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+	/* Read-only registers, do nothing */
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Read-only registers, do nothing */
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+        s->regs[saddr] = val & 0x0401fc0f;
+        break;
+    case GT_PCI0_CFGADDR:
+        s->pci->config_reg = val & 0x80fffffc;
+        break;
+    case GT_PCI0_CFGDATA:
+        pci_host_data_writel(s->pci, 0, val);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Accept, but ignore the values. */
+        s->regs[saddr] = val;
+        break;
+
+    default:
+#if 0
+        printf ("gt64120_writel: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+}
+
+static uint32_t gt64120_readl (void *opaque,
+                               target_phys_addr_t addr)
+{
+    GT64120State *s = opaque;
+    uint32_t val;
+    uint32_t saddr;
+
+    val = 0;
+    saddr = (addr & 0xfff) >> 2;
+
+    switch (saddr) {
+
+    /* CPU Configuration */
+    case GT_MULTI:
+        /* Only one GT64xxx is present on the CPU bus, return
+           the initial value */
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Error Report */
+    case GT_CPUERR_ADDRLO:
+    case GT_CPUERR_ADDRHI:
+    case GT_CPUERR_DATALO:
+    case GT_CPUERR_DATAHI:
+    case GT_CPUERR_PARITY:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    /* CPU Sync Barrier */
+    case GT_PCI0SYNC:
+    case GT_PCI1SYNC:
+        /* Reading those register should empty all FIFO on the PCI
+           bus, which are not emulated. The return value should be
+           a random value that should be ignored. */
+        val = 0xc000ffee; 
+        break;
+
+    /* ECC */
+    case GT_ECC_ERRDATALO:
+    case GT_ECC_ERRDATAHI:
+    case GT_ECC_MEM:
+    case GT_ECC_CALC:
+    case GT_ECC_ERRADDR:
+        /* Emulated memory has no error, always return the initial
+           values */ 
+        val = s->regs[saddr];
+        break;
+
+    case GT_CPU:
+    case GT_PCI0IOLD:
+    case GT_PCI0M0LD:
+    case GT_PCI0M1LD:
+    case GT_PCI1IOLD:
+    case GT_PCI1M0LD:
+    case GT_PCI1M1LD:
+    case GT_PCI0IOHD:
+    case GT_PCI0M0HD:
+    case GT_PCI0M1HD:
+    case GT_PCI1IOHD:
+    case GT_PCI1M0HD:
+    case GT_PCI1M1HD:
+    case GT_PCI0_CMD:
+    case GT_PCI1_CMD:
+    case GT_PCI0IOREMAP:
+    case GT_PCI0M0REMAP:
+    case GT_PCI0M1REMAP:
+    case GT_PCI1IOREMAP:
+    case GT_PCI1M0REMAP:
+    case GT_PCI1M1REMAP:
+        val = s->regs[saddr];
+        break;
+    case GT_PCI0_IACK:
+        /* Read the IRQ number */ 
+        val = pic_read_irq(isa_pic);
+        break;
+
+    /* SDRAM Parameters */
+    case GT_SDRAM_B0:
+    case GT_SDRAM_B1:
+    case GT_SDRAM_B2:
+    case GT_SDRAM_B3:
+        /* We don't simulate electrical parameters of the SDRAM.
+           Just return the last written value. */
+        val = s->regs[saddr];
+        break;
+
+    /* PCI Internal */
+    case GT_PCI0_CFGADDR:
+        val = s->pci->config_reg;
+        break;
+    case GT_PCI0_CFGDATA:
+        val = pci_host_data_readl(s->pci, 0);
+        break;
+
+    default:
+        val = s->regs[saddr];
+#if 0
+        printf ("gt64120_readl: Bad register offset 0x%x\n", (int)addr);
+#endif
+        break;
+    }
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    return bswap32(val);
+#else
+    return val;
+#endif
+}
+
+static CPUWriteMemoryFunc *gt64120_write[] = {
+    &gt64120_writel,
+    &gt64120_writel,
+    &gt64120_writel,
+};
+
+static CPUReadMemoryFunc *gt64120_read[] = {
+    &gt64120_readl,
+    &gt64120_readl,
+    &gt64120_readl,
+};
+
+static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    int slot;
+
+    slot = (pci_dev->devfn >> 3);
+
+    switch (slot) {
+      /* PIIX4 USB */
+      case 10:
+        return 3;
+      /* AMD 79C973 Ethernet */
+      case 11:
+        return 0;
+      /* Crystal 4281 Sound */
+      case 12:
+        return 0;
+      /* PCI slot 1 to 4 */
+      case 18 ... 21:
+        return ((slot - 18) + irq_num) & 0x03;
+      /* Unknown device, don't do any translation */
+      default:
+        return irq_num;
+    }
+}
+
+extern PCIDevice *piix4_dev;
+static int pci_irq_levels[4];
+
+static void pci_gt64120_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+    int i, pic_irq, pic_level;
+
+    pci_irq_levels[irq_num] = level;
+
+    /* now we change the pic irq level according to the piix irq mappings */
+    /* XXX: optimize */
+    pic_irq = piix4_dev->config[0x60 + irq_num];
+    if (pic_irq < 16) {
+        /* The pic level is the logical OR of all the PCI irqs mapped
+           to it */
+        pic_level = 0;
+        for (i = 0; i < 4; i++) {
+            if (pic_irq == piix4_dev->config[0x60 + i])
+                pic_level |= pci_irq_levels[i];
+        }
+        qemu_set_irq(pic[pic_irq], pic_level);
+    }
+}
+
+
+void gt64120_reset(void *opaque)
+{
+    GT64120State *s = opaque;
+
+    /* CPU Configuration */
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_CPU]           = 0x00000000;
+#else
+    s->regs[GT_CPU]           = 0x00001000;
+#endif
+    s->regs[GT_MULTI]         = 0x00000000;
+
+    /* CPU Address decode FIXME: not complete*/
+    s->regs[GT_PCI0IOLD]      = 0x00000080;
+    s->regs[GT_PCI0IOHD]      = 0x0000000f;
+    s->regs[GT_PCI0M0LD]      = 0x00000090;
+    s->regs[GT_PCI0M0HD]      = 0x0000001f;
+    s->regs[GT_PCI0M1LD]      = 0x00000790;
+    s->regs[GT_PCI0M1HD]      = 0x0000001f;
+    s->regs[GT_PCI1IOLD]      = 0x00000100;
+    s->regs[GT_PCI1IOHD]      = 0x0000000f;
+    s->regs[GT_PCI1M0LD]      = 0x00000110;
+    s->regs[GT_PCI1M0HD]      = 0x0000001f;
+    s->regs[GT_PCI1M1LD]      = 0x00000120;
+    s->regs[GT_PCI1M1HD]      = 0x0000002f;
+    s->regs[GT_PCI0IOREMAP]   = 0x00000080;
+    s->regs[GT_PCI0M0REMAP]   = 0x00000090;
+    s->regs[GT_PCI0M1REMAP]   = 0x00000790;
+    s->regs[GT_PCI1IOREMAP]   = 0x00000100;
+    s->regs[GT_PCI1M0REMAP]   = 0x00000110;
+    s->regs[GT_PCI1M1REMAP]   = 0x00000120;
+
+    /* CPU Error Report */
+    s->regs[GT_CPUERR_ADDRLO] = 0x00000000;
+    s->regs[GT_CPUERR_ADDRHI] = 0x00000000;
+    s->regs[GT_CPUERR_DATALO] = 0xffffffff;
+    s->regs[GT_CPUERR_DATAHI] = 0xffffffff;
+    s->regs[GT_CPUERR_PARITY] = 0x000000ff;
+
+    /* ECC */
+    s->regs[GT_ECC_ERRDATALO] = 0x00000000;
+    s->regs[GT_ECC_ERRDATAHI] = 0x00000000;
+    s->regs[GT_ECC_MEM]       = 0x00000000;
+    s->regs[GT_ECC_CALC]      = 0x00000000;
+    s->regs[GT_ECC_ERRADDR]   = 0x00000000;
+
+    /* SDRAM Parameters */
+    s->regs[GT_SDRAM_B0]      = 0x00000005;    
+    s->regs[GT_SDRAM_B1]      = 0x00000005;    
+    s->regs[GT_SDRAM_B2]      = 0x00000005;    
+    s->regs[GT_SDRAM_B3]      = 0x00000005;    
+
+    /* PCI Internal FIXME: not complete*/
+#ifdef TARGET_WORDS_BIGENDIAN
+    s->regs[GT_PCI0_CMD]      = 0x00000000;
+    s->regs[GT_PCI1_CMD]      = 0x00000000;
+#else
+    s->regs[GT_PCI0_CMD]      = 0x00010001;
+    s->regs[GT_PCI1_CMD]      = 0x00010001;
+#endif
+    s->regs[GT_PCI0_IACK]     = 0x00000000;
+    s->regs[GT_PCI1_IACK]     = 0x00000000;
+
+    gt64120_pci_mapping(s);
+}
+
+static uint32_t gt64120_read_config(PCIDevice *d, uint32_t address, int len)
+{
+    uint32_t val = pci_default_read_config(d, address, len);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+static void gt64120_write_config(PCIDevice *d, uint32_t address, uint32_t val,
+                                 int len)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    pci_default_write_config(d, address, val, len);
+}
+
+PCIBus *pci_gt64120_init(qemu_irq *pic)
+{
+    GT64120State *s;
+    PCIDevice *d;
+    int gt64120;
+
+    s = qemu_mallocz(sizeof(GT64120State));
+    s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+    gt64120_reset(s);
+
+    s->pci->bus = pci_register_bus(pci_gt64120_set_irq, pci_gt64120_map_irq,
+                                   pic, 144, 4);
+
+    gt64120 = cpu_register_io_memory(0, gt64120_read,
+                                     gt64120_write, s);
+    cpu_register_physical_memory(0x1be00000LL, 0x1000, gt64120);
+
+    d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
+                            0, gt64120_read_config, gt64120_write_config);
+
+    d->config[0x00] = 0xab; // vendor_id
+    d->config[0x01] = 0x11;
+    d->config[0x02] = 0x20; // device_id
+    d->config[0x03] = 0x46;
+    d->config[0x04] = 0x06;
+    d->config[0x05] = 0x00;
+    d->config[0x06] = 0x80;
+    d->config[0x07] = 0xa2;
+    d->config[0x08] = 0x10;
+    d->config[0x09] = 0x00;
+    d->config[0x0A] = 0x80;
+    d->config[0x0B] = 0x05;
+    d->config[0x0C] = 0x08;
+    d->config[0x0D] = 0x40;
+    d->config[0x0E] = 0x00;
+    d->config[0x0F] = 0x00;
+    d->config[0x17] = 0x08;
+    d->config[0x1B] = 0x1c;
+    d->config[0x1F] = 0x1f;
+    d->config[0x23] = 0x14;
+    d->config[0x27] = 0x14;
+    d->config[0x3D] = 0x01;
+
+    return s->pci->bus;
+}

Modified: trunk/src/host/qemu-neo1973/hw/heathrow_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/heathrow_pic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,9 +32,9 @@
     uint32_t level_triggered;
 } HeathrowPIC;
 
-struct HeathrowPICS {
+typedef struct HeathrowPICS {
     HeathrowPIC pics[2];
-};
+} HeathrowPICS;
 
 static inline int check_irq(HeathrowPIC *pic)
 {
@@ -130,7 +130,7 @@
 };
 
 
-void heathrow_pic_set_irq(void *opaque, int num, int level)
+static void heathrow_pic_set_irq(void *opaque, int num, int level)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
@@ -156,7 +156,7 @@
     heathrow_pic_update(s);
 }
 
-HeathrowPICS *heathrow_pic_init(int *pmem_index)
+qemu_irq *heathrow_pic_init(int *pmem_index)
 {
     HeathrowPICS *s;
     
@@ -164,5 +164,5 @@
     s->pics[0].level_triggered = 0;
     s->pics[1].level_triggered = 0x1ff00000;
     *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
-    return s;
+    return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
 }

Added: trunk/src/host/qemu-neo1973/hw/i2c.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i2c.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i2c.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,117 @@
+/* 
+ * QEMU I2C bus interface.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the LGPL.
+ */
+
+#include "vl.h"
+
+struct i2c_bus
+{
+    i2c_slave *current_dev;
+    i2c_slave *dev;
+};
+
+/* Create a new I2C bus.  */
+i2c_bus *i2c_init_bus(void)
+{
+    i2c_bus *bus;
+
+    bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
+    return bus;
+}
+
+/* Create a new slave device.  */
+i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
+{
+    i2c_slave *dev;
+
+    if (size < sizeof(i2c_slave))
+        cpu_abort(cpu_single_env, "I2C struct too small");
+
+    dev = (i2c_slave *)qemu_mallocz(size);
+    dev->address = address;
+    dev->next = bus->dev;
+    bus->dev = dev;
+
+    return dev;
+}
+
+void i2c_set_slave_address(i2c_slave *dev, int address)
+{
+    dev->address = address;
+}
+
+/* Return nonzero if bus is busy.  */
+int i2c_bus_busy(i2c_bus *bus)
+{
+    return bus->current_dev != NULL;
+}
+
+/* Returns nonzero if the bus is already busy, or is the address is not
+   valid.  */
+/* TODO: Make this handle multiple masters.  */
+int i2c_start_transfer(i2c_bus *bus, int address, int recv)
+{
+    i2c_slave *dev;
+
+    for (dev = bus->dev; dev; dev = dev->next) {
+        if (dev->address == address)
+            break;
+    }
+
+    if (!dev)
+        return 1;
+
+    /* If the bus is already busy, assume this is a repeated
+       start condition.  */
+    bus->current_dev = dev;
+    dev->event(dev, recv ? I2C_START_RECV : I2C_START_SEND);
+    return 0;
+}
+
+void i2c_end_transfer(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return;
+
+    dev->event(dev, I2C_FINISH);
+
+    bus->current_dev = NULL;
+}
+
+int i2c_send(i2c_bus *bus, uint8_t data)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return -1;
+
+    return dev->send(dev, data);
+}
+
+int i2c_recv(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return -1;
+
+    return dev->recv(dev);
+}
+
+void i2c_nack(i2c_bus *bus)
+{
+    i2c_slave *dev = bus->current_dev;
+
+    if (!dev)
+        return;
+
+    dev->event(dev, I2C_NACK);
+}
+

Modified: trunk/src/host/qemu-neo1973/hw/i2c.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i2c.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i2c.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,187 +1,80 @@
-/*
- * Simplified I2C(tm) bus / SMBus(tm).
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This file is licensed under GNU GPL.
- */
+#ifndef QEMU_I2C_H
+#define QEMU_I2C_H
 
-#define I2C_MAX_MSG	4096
+/* The QEMU I2C implementation only supports simple transfers that complete
+   immediately.  It does not support slave devices that need to be able to
+   defer their response (eg. CPU slave interfaces where the data is supplied
+   by the device driver in response to an interrupt).  */
 
-struct i2c_slave_s {
-    uint8_t address;
-    int (*tx)(void *opaque, uint8_t *data, int len);
-    void (*start)(void *opaque, int dir);
-    void (*stop)(void *opaque);
-    void *opaque;
+enum i2c_event {
+    I2C_START_RECV,
+    I2C_START_SEND,
+    I2C_FINISH,
+    I2C_NACK /* Masker NACKed a recieve byte.  */
 };
 
-struct i2c_bus_s {
-    struct i2c_slave_s *slave[0x80];
-    uint8_t current;
-    int dir;
-};
+typedef struct i2c_slave i2c_slave;
 
-/* I2C master - drives the clock signal on a bus.  There can be multiple
- * masters on one bus.  */
-struct i2c_master_s {
-    struct i2c_bus_s *bus;
-    uint8_t message[I2C_MAX_MSG];
-    int message_len;
-    int ack;
+/* Master to slave.  */
+typedef int (*i2c_send_cb)(i2c_slave *s, uint8_t data);
+/* Slave to master.  */
+typedef int (*i2c_recv_cb)(i2c_slave *s);
+/* Notify the slave of a bus state change.  */
+typedef void (*i2c_event_cb)(i2c_slave *s, enum i2c_event event);
 
-    uint8_t data;
-};
-
-static inline int i2c_bus_start(struct i2c_bus_s *bus, uint8_t byte)
+struct i2c_slave
 {
-    struct i2c_slave_s *slave;
+    /* Callbacks to be set by the device.  */
+    i2c_event_cb event;
+    i2c_recv_cb recv;
+    i2c_send_cb send;
 
-    bus->current = byte >> 1;
-    bus->dir = byte & 1;
-    slave = bus->slave[bus->current];
+    /* Remaining fields for internal use by the I2C code.  */
+    int address;
+    void *next;
+};
 
-    return !slave;
-}
+typedef struct i2c_bus i2c_bus;
 
-static inline int i2c_start_submit(struct i2c_bus_s *bus)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
+i2c_bus *i2c_init_bus(void);
+i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size);
+void i2c_set_slave_address(i2c_slave *dev, int address);
+int i2c_bus_busy(i2c_bus *bus);
+int i2c_start_transfer(i2c_bus *bus, int address, int recv);
+void i2c_end_transfer(i2c_bus *bus);
+void i2c_nack(i2c_bus *bus);
+int i2c_send(i2c_bus *bus, uint8_t data);
+int i2c_recv(i2c_bus *bus);
 
-    if (slave->start)
-        slave->start(slave->opaque, bus->dir);
-    return 0;
-}
-
-static inline int i2c_stop_submit(struct i2c_bus_s *bus)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
-
-    if (slave->stop)
-        slave->stop(slave->opaque);
-    return 0;
-}
-
-static inline int i2c_msg_submit(struct i2c_bus_s *bus,
-                uint8_t message[], int len)
-{
-    struct i2c_slave_s *slave = bus->slave[bus->current];
-    if (!slave)
-        return 1;
-
-    return slave->tx ? slave->tx(slave->opaque, message, len) : 1;
-}
-
-static inline void i2c_master_submit(struct i2c_master_s *master,
-                int start, int stop)
-{
-    int ret = 0;
-
-    if (!master->bus) {
-        master->ack = 0;
-        return;
-    }
-
-    if (start) {
-        if (master->message_len)
-            if (!master->bus->dir) {	/* Master --> Slave */
-                i2c_start_submit(master->bus);
-                ret = i2c_msg_submit(master->bus,
-                                master->message, master->message_len);
-                master->message_len = 0;
-            }
-
-        ret = i2c_bus_start(master->bus, master->data);
-        master->message_len = 0;
-
-        if (master->bus->dir) {		/* Master <-- Slave */
-            i2c_start_submit(master->bus);
-            master->message_len = 1;
-            if (stop)
-                i2c_msg_submit(master->bus, master->message, 0);
-        }
-    } else if (stop < 2) {
-        if (!master->bus->dir) {	/* Master --> Slave */
-            if (master->message_len < I2C_MAX_MSG)
-                master->message[master->message_len ++] = master->data;
-        } else {			/* Master <-- Slave */
-            ret = i2c_msg_submit(master->bus,
-                            master->message, master->message_len);
-            master->data = master->message[0];
-        }
-    }
-
-    if (stop) {
-        if (!master->bus->dir) {	/* Master --> Slave */
-            i2c_start_submit(master->bus);
-            ret = i2c_msg_submit(master->bus,
-                            master->message, master->message_len);
-            master->message_len = 0;
-        }
-
-        i2c_stop_submit(master->bus);
-    }
-
-    master->ack = !ret;
-}
-
-/* Call with zero `addr' to detach.  */
-static inline void i2c_slave_attach(struct i2c_bus_s *bus, uint8_t addr,
-                struct i2c_slave_s *dev)
-{
-    if (addr >= 0x80)
-        cpu_abort(cpu_single_env, "bad I2C address");
-
-    if (dev->address)
-        bus->slave[dev->address] = 0;
-
-    dev->address = addr;
-
-    if (dev->address)
-        bus->slave[dev->address] = dev;
-}
-
-static inline void i2c_master_attach(struct i2c_bus_s *bus,
-                struct i2c_master_s *dev)
-{
-    dev->bus = bus;
-}
-
 /* max7310.c */
-struct i2c_slave_s *max7310_init(void);
-void max7310_reset(struct i2c_slave_s *i2c);
-void max7310_gpio_set(struct i2c_slave_s *i2c, int line, int level);
-void max7310_gpio_handler_set(struct i2c_slave_s *i2c, int line,
+i2c_slave *max7310_init(i2c_bus *bus);
+void max7310_reset(i2c_slave *i2c);
+void max7310_gpio_set(i2c_slave *i2c, int line, int level);
+void max7310_gpio_handler_set(i2c_slave *i2c, int line,
                 gpio_handler_t handler, void *opaque);
 
 /* wm8750.c */
-struct i2c_slave_s *wm8750_init(AudioState *audio);
-void wm8750_reset(struct i2c_slave_s *i2c);
-void wm8750_data_req_set(struct i2c_slave_s *i2c,
+i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio);
+void wm8750_reset(i2c_slave *i2c);
+void wm8750_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque);
 void wm8750_dac_dat(void *opaque, uint32_t sample);
 uint32_t wm8750_adc_dat(void *opaque);
 
 /* wm8753.c */
-struct i2c_slave_s *wm8753_init(AudioState *audio);
-void wm8753_reset(struct i2c_slave_s *i2c);
-void wm8753_data_req_set(struct i2c_slave_s *i2c,
+i2c_slave *wm8753_init(i2c_bus *bus, AudioState *audio);
+void wm8753_reset(i2c_slave *i2c);
+void wm8753_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque);
 void wm8753_dac_dat(void *opaque, uint32_t sample);
 uint32_t wm8753_adc_dat(void *opaque);
-void wm8753_gpio_set(struct i2c_slave_s *i2c, int line, int level);
-void wm8753_gpio_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque);
+qemu_irq *wm8753_gpio_in_get(i2c_slave *i2c);
+void wm8753_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler);
 
 /* pcf5060x.c */
-struct i2c_slave_s *pcf5060x_init(void *pic, int irq, int tsc);
-void pcf_reset(struct i2c_slave_s *i2c);
-void pcf_gpo_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque);
-void pcf_onkey_set(struct i2c_slave_s *i2c, int level);
-void pcf_exton_set(struct i2c_slave_s *i2c, int level);
+i2c_slave *pcf5060x_init(i2c_bus *bus, qemu_irq irq, int tsc);
+void pcf_reset(i2c_slave *i2c);
+void pcf_gpo_handler_set(i2c_slave *i2c, int line, qemu_irq handler);
+void pcf_onkey_set(i2c_slave *i2c, int level);
+void pcf_exton_set(i2c_slave *i2c, int level);
+#endif

Modified: trunk/src/host/qemu-neo1973/hw/i8254.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8254.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i8254.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -47,7 +47,7 @@
     /* irq handling */
     int64_t next_transition_time;
     QEMUTimer *irq_timer;
-    int irq;
+    qemu_irq irq;
 } PITChannelState;
 
 struct PITState {
@@ -366,7 +366,7 @@
         return;
     expire_time = pit_get_next_transition_time(s, current_time);
     irq_level = pit_get_out1(s, current_time);
-    pic_set_irq(s->irq, irq_level);
+    qemu_set_irq(s->irq, irq_level);
 #ifdef DEBUG_PIT
     printf("irq_level=%d next_delay=%f\n",
            irq_level, 
@@ -460,7 +460,7 @@
     }
 }
 
-PITState *pit_init(int base, int irq)
+PITState *pit_init(int base, qemu_irq irq)
 {
     PITState *pit = &pit_state;
     PITChannelState *s;

Modified: trunk/src/host/qemu-neo1973/hw/i8259.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/i8259.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/i8259.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -44,6 +44,7 @@
     uint8_t rotate_on_auto_eoi;
     uint8_t special_fully_nested_mode;
     uint8_t init4; /* true if 4 byte init */
+    uint8_t single_mode; /* true if slave pic is not initialized */
     uint8_t elcr; /* PIIX edge/trigger selection*/
     uint8_t elcr_mask;
     PicState2 *pics_state;
@@ -53,7 +54,7 @@
     /* 0 is master pic, 1 is slave pic */
     /* XXX: better separation between the two pics */
     PicState pics[2];
-    IRQRequestFunc *irq_request;
+    qemu_irq parent_irq;
     void *irq_request_opaque;
     /* IOAPIC callback support */
     SetIRQFunc *alt_irq_func;
@@ -159,22 +160,29 @@
         }
         printf("pic: cpu_interrupt\n");
 #endif
-        s->irq_request(s->irq_request_opaque, 1);
+        qemu_irq_raise(s->parent_irq);
     }
+
+/* all targets should do this rather than acking the IRQ in the cpu */
+#if defined(TARGET_MIPS)
+    else {
+        qemu_irq_lower(s->parent_irq);
+    }
+#endif
 }
 
 #ifdef DEBUG_IRQ_LATENCY
 int64_t irq_time[16];
 #endif
 
-void pic_set_irq_new(void *opaque, int irq, int level)
+void i8259_set_irq(void *opaque, int irq, int level)
 {
     PicState2 *s = opaque;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[irq]) {
 #if defined(DEBUG_PIC)
-        printf("pic_set_irq: irq=%d level=%d\n", irq, level);
+        printf("i8259_set_irq: irq=%d level=%d\n", irq, level);
 #endif
         irq_level[irq] = level;
 #ifdef DEBUG_IRQ_COUNT
@@ -195,12 +203,6 @@
     pic_update_irq(s);
 }
 
-/* obsolete function */
-void pic_set_irq(int irq, int level)
-{
-    pic_set_irq_new(isa_pic, irq, level);
-}
-
 /* acknowledge interrupt 'irq' */
 static inline void pic_intack(PicState *s, int irq)
 {
@@ -271,6 +273,7 @@
     s->rotate_on_auto_eoi = 0;
     s->special_fully_nested_mode = 0;
     s->init4 = 0;
+    s->single_mode = 0;
     /* Note: ELCR is not reset */
 }
 
@@ -288,11 +291,10 @@
             /* init */
             pic_reset(s);
             /* deassert a pending interrupt */
-            s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
+            qemu_irq_lower(s->pics_state->parent_irq);
             s->init_state = 1;
             s->init4 = val & 1;
-            if (val & 0x02)
-                hw_error("single mode not supported");
+            s->single_mode = val & 2;
             if (val & 0x08)
                 hw_error("level sensitive irq not supported");
         } else if (val & 0x08) {
@@ -349,7 +351,7 @@
             break;
         case 1:
             s->irq_base = val & 0xf8;
-            s->init_state = 2;
+            s->init_state = s->single_mode && s->init4 ? 3 : 2;
             break;
         case 2:
             if (s->init4) {
@@ -461,6 +463,7 @@
     qemu_put_8s(f, &s->rotate_on_auto_eoi);
     qemu_put_8s(f, &s->special_fully_nested_mode);
     qemu_put_8s(f, &s->init4);
+    qemu_put_8s(f, &s->single_mode);
     qemu_put_8s(f, &s->elcr);
 }
 
@@ -485,6 +488,7 @@
     qemu_get_8s(f, &s->rotate_on_auto_eoi);
     qemu_get_8s(f, &s->special_fully_nested_mode);
     qemu_get_8s(f, &s->init4);
+    qemu_get_8s(f, &s->single_mode);
     qemu_get_8s(f, &s->elcr);
     return 0;
 }
@@ -536,9 +540,10 @@
 #endif
 }
 
-PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque)
+qemu_irq *i8259_init(qemu_irq parent_irq)
 {
     PicState2 *s;
+
     s = qemu_mallocz(sizeof(PicState2));
     if (!s)
         return NULL;
@@ -546,11 +551,11 @@
     pic_init1(0xa0, 0x4d1, &s->pics[1]);
     s->pics[0].elcr_mask = 0xf8;
     s->pics[1].elcr_mask = 0xde;
-    s->irq_request = irq_request;
-    s->irq_request_opaque = irq_request_opaque;
+    s->parent_irq = parent_irq;
     s->pics[0].pics_state = s;
     s->pics[1].pics_state = s;
-    return s;
+    isa_pic = s;
+    return qemu_allocate_irqs(i8259_set_irq, s, 16);
 }
 
 void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,

Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,6 +2,7 @@
  * QEMU IDE disk and CD-ROM Emulator
  * 
  * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -311,9 +312,7 @@
     int mult_sectors;
     int identify_set;
     uint16_t identify_data[256];
-    SetIRQFunc *set_irq;
-    void *irq_opaque;
-    int irq;
+    qemu_irq irq;
     PCIDevice *pci_dev;
     struct BMDMAState *bmdma;
     int drive_serial;
@@ -411,6 +410,7 @@
 } PCIIDEState;
 
 static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 
 static void padstr(char *str, const char *src, int len)
 {
@@ -659,7 +659,7 @@
         if (bm) {
             bm->status |= BM_STATUS_INT;
         }
-        s->set_irq(s->irq_opaque, s->irq, 1);
+        qemu_irq_raise(s->irq);
     }
 }
 
@@ -878,7 +878,7 @@
     ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
     s->nsector -= n;
     if (s->nsector == 0) {
-        /* no more sector to write */
+        /* no more sectors to write */
         ide_transfer_stop(s);
     } else {
         n1 = s->nsector;
@@ -1148,11 +1148,17 @@
         size = max_size;
     s->lba = -1; /* no sector read */
     s->packet_transfer_size = size;
+    s->io_buffer_size = size;    /* dma: send the reply data as one chunk */
     s->elementary_transfer_size = 0;
     s->io_buffer_index = 0;
 
-    s->status = READY_STAT;
-    ide_atapi_cmd_reply_end(s);
+    if (s->atapi_dma) {
+    	s->status = READY_STAT | DRQ_STAT;
+	ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+    } else {
+    	s->status = READY_STAT;
+    	ide_atapi_cmd_reply_end(s);
+    }
 }
 
 /* start a CD-CDROM read command */
@@ -1184,14 +1190,23 @@
     }
 
     if (s->io_buffer_size > 0) {
-        if (s->cd_sector_size == 2352) {
-            n = 1;
-            cd_data_to_raw(s->io_buffer, s->lba);
-        } else {
-            n = s->io_buffer_size >> 11;
-        }
+	/*
+	 * For a cdrom read sector command (s->lba != -1),
+	 * adjust the lba for the next s->io_buffer_size chunk
+	 * and dma the current chunk.
+	 * For a command != read (s->lba == -1), just transfer
+	 * the reply data.
+	 */
+	if (s->lba != -1) {
+	    if (s->cd_sector_size == 2352) {
+		n = 1;
+		cd_data_to_raw(s->io_buffer, s->lba);
+	    } else {
+		n = s->io_buffer_size >> 11;
+	    }
+	    s->lba += n;
+	}
         s->packet_transfer_size -= s->io_buffer_size;
-        s->lba += n;
         if (dma_buf_rw(bm, 1) == 0)
             goto eot;
     }
@@ -1255,7 +1270,8 @@
                                int sector_size)
 {
 #ifdef DEBUG_IDE_ATAPI
-    printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
+    printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
+	lba, nb_sectors);
 #endif
     if (s->atapi_dma) {
         ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
@@ -1759,12 +1775,12 @@
                 /* Disable Read and Write Multiple */
                 s->mult_sectors = 0;
                 s->status = READY_STAT;
-            } else if (s->nsector > MAX_MULT_SECTORS || 
-                s->nsector == 0 ||
-                (s->nsector & (s->nsector - 1)) != 0) {
+            } else if ((s->nsector & 0xff) != 0 &&
+                ((s->nsector & 0xff) > MAX_MULT_SECTORS ||
+                 (s->nsector & (s->nsector - 1)) != 0)) {
                 ide_abort_command(s);
             } else {
-                s->mult_sectors = s->nsector;
+                s->mult_sectors = s->nsector & 0xff;
                 s->status = READY_STAT;
             }
             ide_set_irq(s);
@@ -1864,6 +1880,8 @@
                 goto abort_cmd;
             /* XXX: valid for CDROM ? */
             switch(s->feature) {
+            case 0xcc: /* reverting to power-on defaults enable */
+            case 0x66: /* reverting to power-on defaults disable */
             case 0x02: /* write cache enable */
             case 0x82: /* write cache disable */
             case 0xaa: /* read look-ahead enable */
@@ -1874,8 +1892,6 @@
             case 0x67: /* NOP */
             case 0x96: /* NOP */
             case 0x9a: /* NOP */
-            case 0x66: /* disable power on reset at soft reset */
-            case 0xcc: /* enable power on reset at soft reset */
                 s->status = READY_STAT | SEEK_STAT;
                 ide_set_irq(s);
                 break;
@@ -1915,7 +1931,7 @@
             ide_set_irq(s);
             break;
 	case WIN_STANDBYNOW1:
-	case WIN_STANDBYNOW2:
+        case WIN_STANDBYNOW2:
         case WIN_IDLEIMMEDIATE:
         case CFA_IDLEIMMEDIATE:
         case WIN_SETIDLE1:
@@ -2107,7 +2123,7 @@
             ret = 0;
         else
             ret = s->status;
-        s->set_irq(s->irq_opaque, s->irq, 0);
+        qemu_irq_lower(s->irq);
         break;
     }
 #ifdef DEBUG_IDE
@@ -2306,7 +2322,7 @@
 
 static void ide_init2(IDEState *ide_state,
                       BlockDriverState *hd0, BlockDriverState *hd1,
-                      SetIRQFunc *set_irq, void *irq_opaque, int irq)
+                      qemu_irq irq)
 {
     IDEState *s;
     static int drive_serial = 1;
@@ -2377,8 +2393,6 @@
             }
         }
         s->drive_serial = drive_serial++;
-        s->set_irq = set_irq;
-        s->irq_opaque = irq_opaque;
         s->irq = irq;
         s->sector_write_timer = qemu_new_timer(vm_clock, 
                                                ide_sector_write_timer_cb, s);
@@ -2405,7 +2419,7 @@
 /***********************************************************/
 /* ISA IDE definitions */
 
-void isa_ide_init(int iobase, int iobase2, int irq,
+void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
                   BlockDriverState *hd0, BlockDriverState *hd1)
 {
     IDEState *ide_state;
@@ -2414,7 +2428,7 @@
     if (!ide_state)
         return;
     
-    ide_init2(ide_state, hd0, hd1, pic_set_irq_new, isa_pic, irq);
+    ide_init2(ide_state, hd0, hd1, irq);
     ide_init_ioport(ide_state, iobase, iobase2);
 }
 
@@ -2454,7 +2468,6 @@
         return;
     bm->ide_if = s;
     bm->dma_cb = dma_cb;
-    bm->cur_addr = bm->addr;
     bm->cur_prd_last = 0;
     bm->cur_prd_addr = 0;
     bm->cur_prd_len = 0;
@@ -2587,6 +2600,7 @@
     printf("%s: 0x%08x\n", __func__, val);
 #endif
     bm->addr = val & ~3;
+    bm->cur_addr = bm->addr;
 }
 
 static void bmdma_map(PCIDevice *pci_dev, int region_num, 
@@ -2621,7 +2635,7 @@
                  !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
         ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
          !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
-    pci_set_irq((PCIDevice *)d, 0, pci_level);
+    qemu_set_irq(d->dev.irq[0], pci_level);
 }
 
 /* the PCI irq level is the logical OR of the two channels */
@@ -2645,6 +2659,7 @@
     PCIIDEState *d;
     uint8_t *pci_conf;
     int i;
+    qemu_irq *irq;
 
     d = (PCIIDEState *)pci_register_device(bus, "CMD646 IDE", 
                                            sizeof(PCIIDEState),
@@ -2684,10 +2699,10 @@
     
     for(i = 0; i < 4; i++)
         d->ide_if[i].pci_dev = (PCIDevice *)d;
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
-              cmd646_set_irq, d, 0);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
-              cmd646_set_irq, d, 1);
+
+    irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]);
 }
 
 static void pci_ide_save(QEMUFile* f, void *opaque)
@@ -2801,9 +2816,21 @@
     return 0;
 }
 
+static void piix3_reset(PCIIDEState *d)
+{
+    uint8_t *pci_conf = d->dev.config;
+
+    pci_conf[0x04] = 0x00;
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x80; /* FBC */
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
+}
+
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
-void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic)
 {
     PCIIDEState *d;
     uint8_t *pci_conf;
@@ -2825,13 +2852,13 @@
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
 
+    piix3_reset(d);
+
     pci_register_io_region((PCIDevice *)d, 4, 0x10, 
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1],
-              pic_set_irq_new, isa_pic, 14);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3],
-              pic_set_irq_new, isa_pic, 15);
+    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
@@ -2950,15 +2977,13 @@
 /* hd_table must contain 4 block drivers */
 /* PowerMac uses memory mapped registers, not I/O. Return the memory
    I/O index to access the ide. */
-int pmac_ide_init (BlockDriverState **hd_table,
-                   SetIRQFunc *set_irq, void *irq_opaque, int irq)
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq)
 {
     IDEState *ide_if;
     int pmac_ide_memory;
 
     ide_if = qemu_mallocz(sizeof(IDEState) * 2);
-    ide_init2(&ide_if[0], hd_table[0], hd_table[1],
-              set_irq, irq_opaque, irq);
+    ide_init2(&ide_if[0], hd_table[0], hd_table[1], irq);
     
     pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
                                              pmac_ide_write, &ide_if[0]);
@@ -2968,4 +2993,492 @@
 /***********************************************************/
 /* CF-ATA Microdrive */
 
-#include "md.c"
+#define METADATA_SIZE	0x20
+
+/* DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.  */
+struct md_s {
+    IDEState ide[2];
+    struct pcmcia_card_s card;
+    uint32_t attr_base;
+    uint32_t io_base;
+
+    /* Card state */
+    uint8_t opt;
+    uint8_t stat;
+    uint8_t pins;
+
+    uint8_t ctrl;
+    uint16_t io;
+    int cycle;
+};
+
+/* Register bitfields */
+enum md_opt {
+    OPT_MODE_MMAP	= 0,
+    OPT_MODE_IOMAP16	= 1,
+    OPT_MODE_IOMAP1	= 2,
+    OPT_MODE_IOMAP2	= 3,
+    OPT_MODE		= 0x3f,
+    OPT_LEVIREQ		= 0x40,
+    OPT_SRESET		= 0x80,
+};
+enum md_cstat {
+    STAT_INT		= 0x02,
+    STAT_PWRDWN		= 0x04,
+    STAT_XE		= 0x10,
+    STAT_IOIS8		= 0x20,
+    STAT_SIGCHG		= 0x40,
+    STAT_CHANGED	= 0x80,
+};
+enum md_pins {
+    PINS_MRDY		= 0x02,
+    PINS_CRDY		= 0x20,
+};
+enum md_ctrl {
+    CTRL_IEN		= 0x02,
+    CTRL_SRST		= 0x04,
+};
+
+static inline void md_interrupt_update(struct md_s *s)
+{
+    if (!s->card.slot)
+        return;
+
+    qemu_set_irq(s->card.slot->irq,
+                    !(s->stat & STAT_INT) &&	/* Inverted */
+                    !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
+                    !(s->opt & OPT_SRESET));
+}
+
+static void md_set_irq(void *opaque, int irq, int level)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (level)
+        s->stat |= STAT_INT;
+    else
+        s->stat &= ~STAT_INT;
+
+    md_interrupt_update(s);
+}
+
+static void md_reset(struct md_s *s)
+{
+    s->opt = OPT_MODE_MMAP;
+    s->stat = 0;
+    s->pins = 0;
+    s->cycle = 0;
+    s->ctrl = 0;
+    ide_reset(s->ide);
+}
+
+static uint8_t md_attr_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    if (at < s->attr_base) {
+        if (at < s->card.cis_len)
+            return s->card.cis[at];
+        else
+            return 0x00;
+    }
+
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00:	/* Configuration Option Register */
+        return s->opt;
+    case 0x02:	/* Card Configuration Status Register */
+        if (s->ctrl & CTRL_IEN)
+            return s->stat & ~STAT_INT;
+        else
+            return s->stat;
+    case 0x04:	/* Pin Replacement Register */
+        return (s->pins & PINS_CRDY) | 0x0c;
+    case 0x06:	/* Socket and Copy Register */
+        return 0x00;
+#ifdef VERBOSE
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+#endif
+    }
+
+    return 0;
+}
+
+static void md_attr_write(void *opaque, uint32_t at, uint8_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->attr_base;
+
+    switch (at) {
+    case 0x00:	/* Configuration Option Register */
+        s->opt = value & 0xcf;
+        if (value & OPT_SRESET)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    case 0x02:	/* Card Configuration Status Register */
+        if ((s->stat ^ value) & STAT_PWRDWN)
+            s->pins |= PINS_CRDY;
+        s->stat &= 0x82;
+        s->stat |= value & 0x74;
+        md_interrupt_update(s);
+        /* Word 170 in Identify Device must be equal to STAT_XE */
+        break;
+    case 0x04:	/* Pin Replacement Register */
+        s->pins &= PINS_CRDY;
+        s->pins |= value & PINS_MRDY;
+        break;
+    case 0x06:	/* Socket and Copy Register */
+        break;
+    default:
+        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
+    }
+}
+
+static uint16_t md_common_read(void *opaque, uint32_t at)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    uint16_t ret;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:	/* Even RD Data */
+    case 0x8:
+        return ide_data_readw(s->ide, 0);
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ret = s->io >> 8;
+        else {
+            s->io = ide_data_readw(s->ide, 0);
+            ret = s->io & 0xff;
+        }
+        s->cycle = !s->cycle;
+        return ret;
+    case 0x9:	/* Odd RD Data */
+        return s->io >> 8;
+    case 0xd:	/* Error */
+        return ide_ioport_read(s->ide, 0x1);
+    case 0xe:	/* Alternate Status */
+        if (s->ide->cur_drive->bs)
+            return s->ide->cur_drive->status;
+        else
+            return 0;
+    case 0xf:	/* Device Address */
+        return 0xc2 | ((~s->ide->select << 2) & 0x3c);
+    default:
+        return ide_ioport_read(s->ide, at);
+    }
+
+    return 0;
+}
+
+static void md_common_write(void *opaque, uint32_t at, uint16_t value)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    at -= s->io_base;
+
+    switch (s->opt & OPT_MODE) {
+    case OPT_MODE_MMAP:
+        if ((at & ~0x3ff) == 0x400)
+            at = 0;
+        break;
+    case OPT_MODE_IOMAP16:
+        at &= 0xf;
+        break;
+    case OPT_MODE_IOMAP1:
+        if ((at & ~0xf) == 0x3f0)
+            at -= 0x3e8;
+        else if ((at & ~0xf) == 0x1f0)
+            at -= 0x1f0;
+        break;
+    case OPT_MODE_IOMAP2:
+        if ((at & ~0xf) == 0x370)
+            at -= 0x368;
+        else if ((at & ~0xf) == 0x170)
+            at -= 0x170;
+    }
+
+    switch (at) {
+    case 0x0:	/* Even WR Data */
+    case 0x8:
+        ide_data_writew(s->ide, 0, value);
+        break;
+
+        /* TODO: 8-bit accesses */
+        if (s->cycle)
+            ide_data_writew(s->ide, 0, s->io | (value << 8));
+        else
+            s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0x9:
+        s->io = value & 0xff;
+        s->cycle = !s->cycle;
+        break;
+    case 0xd:	/* Features */
+        ide_ioport_write(s->ide, 0x1, value);
+        break;
+    case 0xe:	/* Device Control */
+        s->ctrl = value;
+        if (value & CTRL_SRST)
+            md_reset(s);
+        md_interrupt_update(s);
+        break;
+    default:
+        if (s->stat & STAT_PWRDWN) {
+            s->pins |= PINS_CRDY;
+            s->stat &= ~STAT_PWRDWN;
+        }
+        ide_ioport_write(s->ide, at, value);
+    }
+}
+
+static const uint8_t dscm1xxxx_cis[0x14a] = {
+    [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
+    [0x002] = 0x03,		/* Tuple length = 4 bytes */
+    [0x004] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x006] = 0x01,		/* Size = 2K bytes */
+    [0x008] = CISTPL_ENDMARK,
+
+    [0x00a] = CISTPL_DEVICE_OC,	/* Additional Device Information */
+    [0x00c] = 0x04,		/* Tuple length = 4 byest */
+    [0x00e] = 0x03,		/* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
+    [0x010] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
+    [0x012] = 0x01,		/* Size = 2K bytes */
+    [0x014] = CISTPL_ENDMARK,
+
+    [0x016] = CISTPL_JEDEC_C,	/* JEDEC ID */
+    [0x018] = 0x02,		/* Tuple length = 2 bytes */
+    [0x01a] = 0xdf,		/* PC Card ATA with no Vpp required */
+    [0x01c] = 0x01,
+
+    [0x01e] = CISTPL_MANFID,	/* Manufacture ID */
+    [0x020] = 0x04,		/* Tuple length = 4 bytes */
+    [0x022] = 0xa4,		/* TPLMID_MANF = 00a4 (IBM) */
+    [0x024] = 0x00,
+    [0x026] = 0x00,		/* PLMID_CARD = 0000 */
+    [0x028] = 0x00,
+
+    [0x02a] = CISTPL_VERS_1,	/* Level 1 Version */
+    [0x02c] = 0x12,		/* Tuple length = 23 bytes */
+    [0x02e] = 0x04,		/* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
+    [0x030] = 0x01,		/* Minor Version = 1 */
+    [0x032] = 'I',
+    [0x034] = 'B',
+    [0x036] = 'M',
+    [0x038] = 0x00,
+    [0x03a] = 'm',
+    [0x03c] = 'i',
+    [0x03e] = 'c',
+    [0x040] = 'r',
+    [0x042] = 'o',
+    [0x044] = 'd',
+    [0x046] = 'r',
+    [0x048] = 'i',
+    [0x04a] = 'v',
+    [0x04c] = 'e',
+    [0x04e] = 0x00,
+    [0x050] = CISTPL_ENDMARK,
+
+    [0x052] = CISTPL_FUNCID,	/* Function ID */
+    [0x054] = 0x02,		/* Tuple length = 2 bytes */
+    [0x056] = 0x04,		/* TPLFID_FUNCTION = Fixed Disk */
+    [0x058] = 0x01,		/* TPLFID_SYSINIT: POST = 1, ROM = 0 */
+
+    [0x05a] = CISTPL_FUNCE,	/* Function Extension */
+    [0x05c] = 0x02,		/* Tuple length = 2 bytes */
+    [0x05e] = 0x01,		/* TPLFE_TYPE = Disk Device Interface */
+    [0x060] = 0x01,		/* TPLFE_DATA = PC Card ATA Interface */
+
+    [0x062] = CISTPL_FUNCE,	/* Function Extension */
+    [0x064] = 0x03,		/* Tuple length = 3 bytes */
+    [0x066] = 0x02,		/* TPLFE_TYPE = Basic PC Card ATA Interface */
+    [0x068] = 0x08,		/* TPLFE_DATA: Rotating, Unique, Single */
+    [0x06a] = 0x0f,		/* TPLFE_DATA: Sleep, Standby, Idle, Auto */
+
+    [0x06c] = CISTPL_CONFIG,	/* Configuration */
+    [0x06e] = 0x05,		/* Tuple length = 5 bytes */
+    [0x070] = 0x01,		/* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
+    [0x072] = 0x07,		/* TPCC_LAST = 7 */
+    [0x074] = 0x00,		/* TPCC_RADR = 0200 */
+    [0x076] = 0x02,
+    [0x078] = 0x0f,		/* TPCC_RMSK = 200, 202, 204, 206 */
+
+    [0x07a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x07c] = 0x0b,		/* Tuple length = 11 bytes */
+    [0x07e] = 0xc0,		/* TPCE_INDX = Memory Mode, Default, Iface */
+    [0x080] = 0xc0,		/* TPCE_IF = Memory, no BVDs, no WP, READY */
+    [0x082] = 0xa1,		/* TPCE_FS = Vcc only, no I/O, Memory, Misc */
+    [0x084] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x086] = 0x55,		/* NomV: 5.0 V */
+    [0x088] = 0x4d,		/* MinV: 4.5 V */
+    [0x08a] = 0x5d,		/* MaxV: 5.5 V */
+    [0x08c] = 0x4e,		/* Peakl: 450 mA */
+    [0x08e] = 0x08,		/* TPCE_MS = 1 window, 1 byte, Host address */
+    [0x090] = 0x00,		/* Window descriptor: Window length = 0 */
+    [0x092] = 0x20,		/* TPCE_MI: support power down mode, RW */
+
+    [0x094] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x096] = 0x06,		/* Tuple length = 6 bytes */
+    [0x098] = 0x00,		/* TPCE_INDX = Memory Mode, no Default */
+    [0x09a] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x09c] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x09e] = 0xb5,		/* NomV: 3.3 V */
+    [0x0a0] = 0x1e,
+    [0x0a2] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x0a4] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0a6] = 0x0d,		/* Tuple length = 13 bytes */
+    [0x0a8] = 0xc1,		/* TPCE_INDX = I/O and Memory Mode, Default */
+    [0x0aa] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0ac] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0ae] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0b0] = 0x55,		/* NomV: 5.0 V */
+    [0x0b2] = 0x4d,		/* MinV: 4.5 V */
+    [0x0b4] = 0x5d,		/* MaxV: 5.5 V */
+    [0x0b6] = 0x4e,		/* Peakl: 450 mA */
+    [0x0b8] = 0x64,		/* TPCE_IO = 16-byte boundary, 16/8 accesses */
+    [0x0ba] = 0xf0,		/* TPCE_IR =  MASK, Level, Pulse, Share */
+    [0x0bc] = 0xff,		/* IRQ0..IRQ7 supported */
+    [0x0be] = 0xff,		/* IRQ8..IRQ15 supported */
+    [0x0c0] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x0c2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0c4] = 0x06,		/* Tuple length = 6 bytes */
+    [0x0c6] = 0x01,		/* TPCE_INDX = I/O and Memory Mode */
+    [0x0c8] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x0ca] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x0cc] = 0xb5,		/* NomV: 3.3 V */
+    [0x0ce] = 0x1e,
+    [0x0d0] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x0d2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0d4] = 0x12,		/* Tuple length = 18 bytes */
+    [0x0d6] = 0xc2,		/* TPCE_INDX = I/O Primary Mode */
+    [0x0d8] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x0da] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x0dc] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x0de] = 0x55,		/* NomV: 5.0 V */
+    [0x0e0] = 0x4d,		/* MinV: 4.5 V */
+    [0x0e2] = 0x5d,		/* MaxV: 5.5 V */
+    [0x0e4] = 0x4e,		/* Peakl: 450 mA */
+    [0x0e6] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x0e8] = 0x61,		/* Range: 2 fields, 2 bytes addr, 1 byte len */
+    [0x0ea] = 0xf0,		/* Field 1 address = 0x01f0 */
+    [0x0ec] = 0x01,
+    [0x0ee] = 0x07,		/* Address block length = 8 */
+    [0x0f0] = 0xf6,		/* Field 2 address = 0x03f6 */
+    [0x0f2] = 0x03,
+    [0x0f4] = 0x01,		/* Address block length = 2 */
+    [0x0f6] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x0f8] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x0fa] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x0fc] = 0x06,		/* Tuple length = 6 bytes */
+    [0x0fe] = 0x02,		/* TPCE_INDX = I/O Primary Mode, no Default */
+    [0x100] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x102] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x104] = 0xb5,		/* NomV: 3.3 V */
+    [0x106] = 0x1e,
+    [0x108] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x10a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x10c] = 0x12,		/* Tuple length = 18 bytes */
+    [0x10e] = 0xc3,		/* TPCE_INDX = I/O Secondary Mode, Default */
+    [0x110] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
+    [0x112] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
+    [0x114] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
+    [0x116] = 0x55,		/* NomV: 5.0 V */
+    [0x118] = 0x4d,		/* MinV: 4.5 V */
+    [0x11a] = 0x5d,		/* MaxV: 5.5 V */
+    [0x11c] = 0x4e,		/* Peakl: 450 mA */
+    [0x11e] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
+    [0x120] = 0x61,		/* Range: 2 fields, 2 byte addr, 1 byte len */
+    [0x122] = 0x70,		/* Field 1 address = 0x0170 */
+    [0x124] = 0x01,
+    [0x126] = 0x07,		/* Address block length = 8 */
+    [0x128] = 0x76,		/* Field 2 address = 0x0376 */
+    [0x12a] = 0x03,
+    [0x12c] = 0x01,		/* Address block length = 2 */
+    [0x12e] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
+    [0x130] = 0x20,		/* TPCE_MI = support power down mode */
+
+    [0x132] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
+    [0x134] = 0x06,		/* Tuple length = 6 bytes */
+    [0x136] = 0x03,		/* TPCE_INDX = I/O Secondary Mode */
+    [0x138] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
+    [0x13a] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
+    [0x13c] = 0xb5,		/* NomV: 3.3 V */
+    [0x13e] = 0x1e,
+    [0x140] = 0x3e,		/* Peakl: 350 mA */
+
+    [0x142] = CISTPL_NO_LINK,	/* No Link */
+    [0x144] = 0x00,		/* Tuple length = 0 bytes */
+
+    [0x146] = CISTPL_END,	/* Tuple End */
+};
+
+static int dscm1xxxx_attach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md->card.attr_read = md_attr_read;
+    md->card.attr_write = md_attr_write;
+    md->card.common_read = md_common_read;
+    md->card.common_write = md_common_write;
+    md->card.io_read = md_common_read;
+    md->card.io_write = md_common_write;
+
+    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
+    md->io_base = 0x0;
+
+    md_reset(md);
+    md_interrupt_update(md);
+
+    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
+    return 0;
+}
+
+static int dscm1xxxx_detach(void *opaque)
+{
+    struct md_s *md = (struct md_s *) opaque;
+    md_reset(md);
+    return 0;
+}
+
+struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
+{
+    struct md_s *md = (struct md_s *) qemu_mallocz(sizeof(struct md_s));
+    md->card.state = md;
+    md->card.attach = dscm1xxxx_attach;
+    md->card.detach = dscm1xxxx_detach;
+    md->card.cis = dscm1xxxx_cis;
+    md->card.cis_len = sizeof(dscm1xxxx_cis);
+
+    ide_init2(md->ide, bdrv, 0, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+    md->ide->is_cf = 1;
+    md->ide->mdata_size = METADATA_SIZE;
+    md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
+    return &md->card;
+}

Modified: trunk/src/host/qemu-neo1973/hw/integratorcp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/integratorcp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/integratorcp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * ARM Integrator CP System emulation.
  *
- * Copyright (c) 2005-2006 CodeSourcery.
+ * Copyright (c) 2005-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL
@@ -267,28 +267,22 @@
 
 typedef struct icp_pic_state
 {
-  arm_pic_handler handler;
   uint32_t base;
   uint32_t level;
   uint32_t irq_enabled;
   uint32_t fiq_enabled;
-  void *parent;
-  int parent_irq;
-  int parent_fiq;
+  qemu_irq parent_irq;
+  qemu_irq parent_fiq;
 } icp_pic_state;
 
 static void icp_pic_update(icp_pic_state *s)
 {
     uint32_t flags;
 
-    if (s->parent_irq != -1) {
-        flags = (s->level & s->irq_enabled);
-        pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
-    }
-    if (s->parent_fiq != -1) {
-        flags = (s->level & s->fiq_enabled);
-        pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
-    }
+    flags = (s->level & s->irq_enabled);
+    qemu_set_irq(s->parent_irq, flags != 0);
+    flags = (s->level & s->fiq_enabled);
+    qemu_set_irq(s->parent_fiq, flags != 0);
 }
 
 static void icp_pic_set_irq(void *opaque, int irq, int level)
@@ -345,11 +339,11 @@
         break;
     case 4: /* INT_SOFTSET */
         if (value & 1)
-            pic_set_irq_new(s, 0, 1);
+            icp_pic_set_irq(s, 0, 1);
         break;
     case 5: /* INT_SOFTCLR */
         if (value & 1)
-            pic_set_irq_new(s, 0, 0);
+            icp_pic_set_irq(s, 0, 0);
         break;
     case 10: /* FRQ_ENABLESET */
         s->fiq_enabled |= value;
@@ -380,25 +374,25 @@
    icp_pic_write
 };
 
-static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
-                                   int parent_irq, int parent_fiq)
+static qemu_irq *icp_pic_init(uint32_t base,
+                              qemu_irq parent_irq, qemu_irq parent_fiq)
 {
     icp_pic_state *s;
     int iomemtype;
+    qemu_irq *qi;
 
     s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
     if (!s)
         return NULL;
-    s->handler = icp_pic_set_irq;
+    qi = qemu_allocate_irqs(icp_pic_set_irq, s, 32);
     s->base = base;
-    s->parent = parent;
     s->parent_irq = parent_irq;
     s->parent_fiq = parent_fiq;
     iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
                                        icp_pic_writefn, s);
     cpu_register_physical_memory(base, 0x007fffff, iomemtype);
     /* ??? Save/restore.  */
-    return s;
+    return qi;
 }
 
 /* CP control registers.  */
@@ -471,15 +465,17 @@
 static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, uint32_t cpuid)
+                     const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
     uint32_t bios_offset;
-    icp_pic_state *pic;
-    void *cpu_pic;
+    qemu_irq *pic;
+    qemu_irq *cpu_pic;
 
     env = cpu_init();
-    cpu_arm_set_model(env, cpuid);
+    if (!cpu_model)
+        cpu_model = "arm926";
+    cpu_arm_set_model(env, cpu_model);
     bios_offset = ram_size + vga_ram_size;
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM shoud repeat to fill physical memory space.  */
@@ -490,57 +486,33 @@
 
     integratorcm_init(ram_size >> 20, bios_offset);
     cpu_pic = arm_pic_init_cpu(env);
-    pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
-    icp_pic_init(0xca000000, pic, 26, -1);
+    pic = icp_pic_init(0x14000000, cpu_pic[ARM_PIC_CPU_IRQ],
+                       cpu_pic[ARM_PIC_CPU_FIQ]);
+    icp_pic_init(0xca000000, pic[26], NULL);
     icp_pit_init(0x13000000, pic, 5);
-    pl011_init(0x16000000, pic, 1, serial_hds[0]);
-    pl011_init(0x17000000, pic, 2, serial_hds[1]);
+    pl011_init(0x16000000, pic[1], serial_hds[0]);
+    pl011_init(0x17000000, pic[2], serial_hds[1]);
     icp_control_init(0xcb000000);
-    pl050_init(0x18000000, pic, 3, 0);
-    pl050_init(0x19000000, pic, 4, 1);
+    pl050_init(0x18000000, pic[3], 0);
+    pl050_init(0x19000000, pic[4], 1);
+    pl181_init(0x1c000000, sd_bdrv, pic[23], pic[24]);
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "smc91c111") == 0) {
-            smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
+            smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
         }
     }
-    pl110_init(ds, 0xc0000000, pic, 22, 0);
+    pl110_init(ds, 0xc0000000, pic[22], 0);
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, 0x113, 0x0);
 }
 
-static void integratorcp926_init(int ram_size, int vga_ram_size,
-    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
-    const char *kernel_filename, const char *kernel_cmdline,
-    const char *initrd_filename)
-{
-    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
-                      snapshot, kernel_filename, kernel_cmdline,
-                      initrd_filename, ARM_CPUID_ARM926);
-}
-
-static void integratorcp1026_init(int ram_size, int vga_ram_size,
-    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
-    const char *kernel_filename, const char *kernel_cmdline,
-    const char *initrd_filename)
-{
-    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
-                      snapshot, kernel_filename, kernel_cmdline,
-                      initrd_filename, ARM_CPUID_ARM1026);
-}
-
-QEMUMachine integratorcp926_machine = {
-    "integratorcp926",
+QEMUMachine integratorcp_machine = {
+    "integratorcp",
     "ARM Integrator/CP (ARM926EJ-S)",
-    integratorcp926_init,
+    integratorcp_init,
 };
-
-QEMUMachine integratorcp1026_machine = {
-    "integratorcp1026",
-    "ARM Integrator/CP (ARM1026EJ-S)",
-    integratorcp1026_init,
-};

Added: trunk/src/host/qemu-neo1973/hw/irq.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/irq.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,57 @@
+/*
+ * QEMU IRQ/GPIO common code.
+ * 
+ * Copyright (c) 2007 CodeSourcery.
+ * 
+ * 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 "vl.h"
+
+struct IRQState {
+    qemu_irq_handler handler;
+    void *opaque;
+    int n;
+};
+
+void qemu_set_irq(qemu_irq irq, int level)
+{
+    if (!irq)
+        return;
+
+    irq->handler(irq->opaque, irq->n, level);
+}
+
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
+{
+    qemu_irq *s;
+    struct IRQState *p;
+    int i;
+
+    s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n);
+    p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n);
+    for (i = 0; i < n; i++) {
+        p->handler = handler;
+        p->opaque = opaque;
+        p->n = i;
+        s[i] = p;
+        p++;
+    }
+    return s;
+}
+

Added: trunk/src/host/qemu-neo1973/hw/irq.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/irq.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/irq.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,21 @@
+/* Generic IRQ/GPIO pin infrastructure.  */
+
+typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+
+typedef struct IRQState *qemu_irq;
+
+void qemu_set_irq(qemu_irq irq, int level);
+
+static inline void qemu_irq_raise(qemu_irq irq)
+{
+    qemu_set_irq(irq, 1);
+}
+
+static inline void qemu_irq_lower(qemu_irq irq)
+{
+    qemu_set_irq(irq, 0);
+}
+
+/* Returns an array of N IRQs.  */
+qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
+

Modified: trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -251,7 +251,7 @@
     uint32_t ia;
     uint32_t sbc;
     uint32_t csbc;
-    uint32_t scratch[13]; /* SCRATCHA-SCRATCHR */
+    uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
 
     /* Script ram is stored as 32-bit words in host byteorder.  */
     uint32_t script_ram[2048];
@@ -374,7 +374,7 @@
                 level, s->dstat, s->sist1, s->sist0);
         last_level = level;
     }
-    pci_set_irq(&s->pci_dev, 0, level);
+    qemu_set_irq(s->pci_dev.irq[0], level);
 }
 
 /* Stop SCRIPTS execution and raise a SCSI interrupt.  */
@@ -855,6 +855,7 @@
             offset = sxt24(addr);
             cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
             s->dbc = cpu_to_le32(buf[0]);
+            s->rbc = s->dbc;
             addr = cpu_to_le32(buf[1]);
         }
         if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
@@ -864,6 +865,8 @@
             break;
         }
         s->dnad = addr;
+        /* ??? Set ESA.  */
+        s->ia = s->dsp - 8;
         switch (s->sstat1 & 0x7) {
         case PHASE_DO:
             s->waiting = 2;
@@ -898,8 +901,6 @@
         s->sbc = s->dbc;
         s->rbc -= s->dbc;
         s->ua = addr + s->dbc;
-        /* ??? Set ESA.  */
-        s->ia = s->dsp - 8;
         break;
 
     case 1: /* IO or Read/Write instruction.  */
@@ -1038,7 +1039,7 @@
                 op0 |= op1;
                 break;
             case 3: /* XOR */
-                op0 |= op1;
+                op0 ^= op1;
                 break;
             case 4: /* AND */
                 op0 &= op1;
@@ -1046,6 +1047,7 @@
             case 5: /* SHR */
                 op1 = op0 & 1;
                 op0 = (op0 >> 1) | (s->carry << 7);
+                s->carry = op1;
                 break;
             case 6: /* ADD */
                 op0 += op1;
@@ -1388,7 +1390,7 @@
         break;
     case 0x02: /* SCNTL2 */
         val &= ~(LSI_SCNTL2_WSR | LSI_SCNTL2_WSS);
-        s->scntl3 = val;
+        s->scntl2 = val;
         break;
     case 0x03: /* SCNTL3 */
         s->scntl3 = val;
@@ -1433,10 +1435,13 @@
         if (val & LSI_ISTAT0_SRST) {
             lsi_soft_reset(s);
         }
+        break;
     case 0x16: /* MBOX0 */
         s->mbox0 = val;
+        break;
     case 0x17: /* MBOX1 */
         s->mbox1 = val;
+        break;
     case 0x1b: /* CTEST3 */
         s->ctest3 = val & 0x0f;
         break;
@@ -1453,19 +1458,19 @@
         }
         s->ctest5 = val;
         break;
-    case 0x2c: /* DSPS[0:7] */
+    case 0x2c: /* DSP[0:7] */
         s->dsp &= 0xffffff00;
         s->dsp |= val;
         break;
-    case 0x2d: /* DSPS[8:15] */
+    case 0x2d: /* DSP[8:15] */
         s->dsp &= 0xffff00ff;
         s->dsp |= val << 8;
         break;
-    case 0x2e: /* DSPS[16:23] */
+    case 0x2e: /* DSP[16:23] */
         s->dsp &= 0xff00ffff;
         s->dsp |= val << 16;
         break;
-    case 0x2f: /* DSPS[14:31] */
+    case 0x2f: /* DSP[24:31] */
         s->dsp &= 0x00ffffff;
         s->dsp |= val << 24;
         if ((s->dmode & LSI_DMODE_MAN) == 0
@@ -1765,7 +1770,7 @@
     lsi_reg_writeb(s, addr, val & 0xff);
     lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
     lsi_reg_writeb(s, addr + 2, (val >> 16) & 0xff);
-    lsi_reg_writeb(s, addr + 2, (val >> 24) & 0xff);
+    lsi_reg_writeb(s, addr + 3, (val >> 24) & 0xff);
 }
 
 static void lsi_io_mapfunc(PCIDevice *pci_dev, int region_num, 

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
  * 
- * Copyright (c) 2003-2005 Jocelyn Mayer
+ * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -41,7 +41,7 @@
     /* Model parameters */
     int type; // 8 = m48t08, 59 = m48t59
     /* Hardware parameters */
-    int      IRQ;
+    qemu_irq IRQ;
     int mem_index;
     uint32_t mem_base;
     uint32_t io_base;
@@ -100,7 +100,7 @@
     uint64_t next_time;
     m48t59_t *NVRAM = opaque;
 
-    pic_set_irq(NVRAM->IRQ, 1);
+    qemu_set_irq(NVRAM->IRQ, 1);
     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && 
 	(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
 	(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
@@ -137,7 +137,7 @@
 	next_time = 1 + mktime(&tm_now);
     }
     qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
-    pic_set_irq(NVRAM->IRQ, 0);
+    qemu_set_irq(NVRAM->IRQ, 0);
 }
 
 
@@ -173,8 +173,8 @@
         /* May it be a hw CPU Reset instead ? */
         qemu_system_reset_request();
     } else {
-	pic_set_irq(NVRAM->IRQ, 1);
-	pic_set_irq(NVRAM->IRQ, 0);
+	qemu_set_irq(NVRAM->IRQ, 1);
+	qemu_set_irq(NVRAM->IRQ, 0);
     }
 }
 
@@ -575,12 +575,47 @@
     &nvram_readl,
 };
 
+static void m48t59_save(QEMUFile *f, void *opaque)
+{
+    m48t59_t *s = opaque;
+
+    qemu_put_8s(f, &s->lock);
+    qemu_put_be16s(f, &s->addr);
+    qemu_put_buffer(f, s->buffer, s->size);
+}
+
+static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
+{
+    m48t59_t *s = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    qemu_get_8s(f, &s->lock);
+    qemu_get_be16s(f, &s->addr);
+    qemu_get_buffer(f, s->buffer, s->size);
+
+    return 0;
+}
+
+static void m48t59_reset(void *opaque)
+{
+    m48t59_t *NVRAM = opaque;
+
+    if (NVRAM->alrm_timer != NULL)
+        qemu_del_timer(NVRAM->alrm_timer);
+
+    if (NVRAM->wd_timer != NULL)
+        qemu_del_timer(NVRAM->wd_timer);
+}
+
 /* Initialisation routine */
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
+m48t59_t *m48t59_init (qemu_irq IRQ, target_ulong mem_base,
                        uint32_t io_base, uint16_t size,
                        int type)
 {
     m48t59_t *s;
+    target_ulong save_base;
 
     s = qemu_mallocz(sizeof(m48t59_t));
     if (!s)
@@ -610,5 +645,9 @@
     }
     s->lock = 0;
 
+    qemu_register_reset(m48t59_reset, s);
+    save_base = mem_base ? mem_base : io_base;
+    register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);
+
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/m48t59.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/m48t59.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -6,7 +6,7 @@
 void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val);
 uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr);
 void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
-m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
+m48t59_t *m48t59_init (qemu_irq IRQ, target_ulong mem_base,
                        uint32_t io_base, uint16_t size,
                        int type);
 

Modified: trunk/src/host/qemu-neo1973/hw/max111x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,17 +1,16 @@
 /*
- * MAX1110/1111 ADC chip emulation.
+ * Maxim MAX1110/1111 ADC chip emulation.
  *
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPLv2.
  */
 
 #include <vl.h>
 
 struct max111x_s {
-    void (*interrupt)(void *opaque);
-    void *opaque;
+    qemu_irq interrupt;
     uint8_t tb1, rb2, rb3;
     int cycle;
 
@@ -87,10 +86,10 @@
     s->rb3 = (measure << 6) & 0xc0;
 
     if (s->interrupt)
-        s->interrupt(s->opaque);
+        qemu_irq_raise(s->interrupt);
 }
 
-struct max111x_s *max111x_init(void (*cb)(void *opaque), void *opaque)
+static struct max111x_s *max111x_init(qemu_irq cb)
 {
     struct max111x_s *s;
     s = (struct max111x_s *)
@@ -98,7 +97,6 @@
     memset(s, 0, sizeof(struct max111x_s));
 
     s->interrupt = cb;
-    s->opaque = opaque;
 
     /* TODO: add a user interface for setting these */
     s->input[0] = 0xf0;
@@ -113,16 +111,16 @@
     return s;
 }
 
-struct max111x_s *max1110_init(void (*cb)(void *opaque), void *opaque)
+struct max111x_s *max1110_init(qemu_irq cb)
 {
-    struct max111x_s *s = max111x_init(cb, opaque);
+    struct max111x_s *s = max111x_init(cb);
     s->inputs = 8;
     return s;
 }
 
-struct max111x_s *max1111_init(void (*cb)(void *opaque), void *opaque)
+struct max111x_s *max1111_init(qemu_irq cb)
 {
-    struct max111x_s *s = max111x_init(cb, opaque);
+    struct max111x_s *s = max111x_init(cb);
     s->inputs = 4;
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/max7310.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,22 +10,24 @@
 #include "vl.h"
 
 struct max7310_s {
+    i2c_slave i2c;
+    int i2c_command_byte;
+    int len;
+
     uint8_t level;
     uint8_t direction;
     uint8_t polarity;
     uint8_t status;
     uint8_t command;
-    int i2c_dir;
-    struct i2c_slave_s i2c;
     struct {
         gpio_handler_t fn;
         void *opaque;
     } handler[8];
 };
 
-void max7310_reset(struct i2c_slave_s *i2c)
+void max7310_reset(i2c_slave *i2c)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     s->level &= s->direction;
     s->direction = 0xff;
     s->polarity = 0xf0;
@@ -33,91 +35,87 @@
     s->command = 0x00;
 }
 
-static void max7310_start(void *opaque, int dir)
+static int max7310_rx(i2c_slave *i2c)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
-    s->i2c_dir = dir;
-}
+    struct max7310_s *s = (struct max7310_s *) i2c;
 
-static int max7310_read(void *opaque, uint8_t *data, int len)
-{
-    struct max7310_s *s = (struct max7310_s *) opaque;
-
     switch (s->command) {
     case 0x00:	/* Input port */
-        memset(data, s->level ^ s->polarity, len);
+        return s->level ^ s->polarity;
         break;
 
     case 0x01:	/* Output port */
-        memset(data, s->level & ~s->direction, len);
+        return s->level & ~s->direction;
         break;
 
     case 0x02:	/* Polarity inversion */
-        memset(data, s->polarity, len);
-        break;
+        return s->polarity;
 
     case 0x03:	/* Configuration */
-        memset(data, s->direction, len);
-        break;
+        return s->direction;
 
     case 0x04:	/* Timeout */
-        memset(data, s->status, len);
+        return s->status;
         break;
 
     case 0xff:	/* Reserved */
-        memset(data, 0xff, len);
-        break;
+        return 0xff;
 
     default:
 #ifdef VERBOSE
         printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
 #endif
-        return 1;
+        break;
     }
-    return 0;
+    return 0xff;
 }
 
-static int max7310_write(void *opaque, uint8_t *data, int len)
+static int max7310_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     uint8_t diff;
     int line;
 
-    if (len >= 1)
-        s->command = data[0];
-
-    if (len < 2) {
+    if (s->len ++ > 1) {
 #ifdef VERBOSE
-        printf("%s: message too short (%i bytes)\n", __FUNCTION__, len);
+        printf("%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
 #endif
+        return 1;
+    }
+
+    if (s->i2c_command_byte) {
+        s->command = data;
+        s->i2c_command_byte = 0;
         return 0;
     }
 
     switch (s->command) {
     case 0x01:	/* Output port */
-        for (diff = (data[1] ^ s->level) & ~s->direction; diff;
+        for (diff = (data ^ s->level) & ~s->direction; diff;
                         diff &= ~(1 << line)) {
             line = ffs(diff) - 1;
             if (s->handler[line].fn)
-                s->handler[line].fn(line, (data[1] >> line) & 1,
+                s->handler[line].fn(line, (data >> line) & 1,
                                 s->handler[line].opaque);
         }
-        s->level = (s->level & s->direction) | (data[1] & ~s->direction);
+        s->level = (s->level & s->direction) | (data & ~s->direction);
         break;
 
     case 0x02:	/* Polarity inversion */
-        s->polarity = data[1];
+        s->polarity = data;
         break;
 
     case 0x03:	/* Configuration */
-        s->level &= ~(s->direction ^ data[1]);
-        s->direction = data[1];
+        s->level &= ~(s->direction ^ data);
+        s->direction = data;
         break;
 
     case 0x04:	/* Timeout */
-        s->status = data[1];
+        s->status = data;
         break;
 
+    case 0x00:	/* Input port - ignore writes */
+	break;
     default:
 #ifdef VERBOSE
         printf("%s: unknown register %02x\n", __FUNCTION__, s->command);
@@ -128,33 +126,43 @@
     return 0;
 }
 
-static int max7310_tx(void *opaque, uint8_t *data, int len)
+static void max7310_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct max7310_s *s = (struct max7310_s *) opaque;
-    if (len) {
-        if (s->i2c_dir)
-            return max7310_write(opaque, data, len);
-        else
-            return max7310_read(opaque, data, len);
+    struct max7310_s *s = (struct max7310_s *) i2c;
+    s->len = 0;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->i2c_command_byte = 1;
+        break;
+    case I2C_FINISH:
+        if (s->len == 1)
+#ifdef VERBOSE
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        break;
+    default:
+        break;
     }
-
-    return 0;
 }
 
-struct i2c_slave_s *max7310_init(void)
+/* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
+ * but also accepts sequences that are not SMBus so return an I2C device.  */
+struct i2c_slave *max7310_init(i2c_bus *bus)
 {
-    struct max7310_s *s = qemu_mallocz(sizeof(struct max7310_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = max7310_tx;
-    s->i2c.start = max7310_start;
+    struct max7310_s *s = (struct max7310_s *)
+            i2c_slave_init(bus, 0, sizeof(struct max7310_s));
+    s->i2c.event = max7310_event;
+    s->i2c.recv = max7310_rx;
+    s->i2c.send = max7310_tx;
 
     max7310_reset(&s->i2c);
     return &s->i2c;
 }
 
-void max7310_gpio_set(struct i2c_slave_s *i2c, int line, int level)
+void max7310_gpio_set(i2c_slave *i2c, int line, int level)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     if (line >= sizeof(s->handler) / sizeof(*s->handler) || line  < 0)
         cpu_abort(cpu_single_env, "bad GPIO line");
 
@@ -164,10 +172,10 @@
         s->level &= ~(s->direction & (1 << line));
 }
 
-void max7310_gpio_handler_set(struct i2c_slave_s *i2c, int line,
+void max7310_gpio_handler_set(i2c_slave *i2c, int line,
                 gpio_handler_t handler, void *opaque)
 {
-    struct max7310_s *s = (struct max7310_s *) i2c->opaque;
+    struct max7310_s *s = (struct max7310_s *) i2c;
     if (line >= sizeof(s->handler) / sizeof(*s->handler) || line  < 0)
         cpu_abort(cpu_single_env, "bad GPIO line");
 

Modified: trunk/src/host/qemu-neo1973/hw/mc146818rtc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mc146818rtc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mc146818rtc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,7 +54,9 @@
     uint8_t cmos_data[128];
     uint8_t cmos_index;
     struct tm current_tm;
-    int irq;
+    qemu_irq irq;
+    target_phys_addr_t base;
+    int it_shift;
     /* periodic timer */
     QEMUTimer *periodic_timer;
     int64_t next_periodic_time;
@@ -95,7 +97,7 @@
 
     rtc_timer_update(s, s->next_periodic_time);
     s->cmos_data[RTC_REG_C] |= 0xc0;
-    pic_set_irq(s->irq, 1);
+    qemu_irq_raise(s->irq);
 }
 
 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
@@ -314,14 +316,14 @@
              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0; 
-            pic_set_irq(s->irq, 1);
+            qemu_irq_raise(s->irq);
         }
     }
 
     /* update ended interrupt */
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
         s->cmos_data[RTC_REG_C] |= 0x90; 
-        pic_set_irq(s->irq, 1);
+        qemu_irq_raise(s->irq);
     }
 
     /* clear update in progress bit */
@@ -353,7 +355,7 @@
             break;
         case RTC_REG_C:
             ret = s->cmos_data[s->cmos_index];
-            pic_set_irq(s->irq, 0);
+            qemu_irq_lower(s->irq);
             s->cmos_data[RTC_REG_C] = 0x00; 
             break;
         default:
@@ -453,7 +455,7 @@
     return 0;
 }
 
-RTCState *rtc_init(int base, int irq)
+RTCState *rtc_init(int base, qemu_irq irq)
 {
     RTCState *s;
 
@@ -486,3 +488,109 @@
     return s;
 }
 
+/* Memory mapped interface */
+uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+
+    return cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
+}
+
+void cmos_mm_writeb (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
+}
+
+uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap16(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writew (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
+}
+
+uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    RTCState *s = opaque;
+    uint32_t val;
+
+    val = cmos_ioport_read(s, (addr - s->base) >> s->it_shift);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    return val;
+}
+
+void cmos_mm_writel (void *opaque,
+                     target_phys_addr_t addr, uint32_t value)
+{
+    RTCState *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    cmos_ioport_write(s, (addr - s->base) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *rtc_mm_read[] = {
+    &cmos_mm_readb,
+    &cmos_mm_readw,
+    &cmos_mm_readl,
+};
+
+static CPUWriteMemoryFunc *rtc_mm_write[] = {
+    &cmos_mm_writeb,
+    &cmos_mm_writew,
+    &cmos_mm_writel,
+};
+
+RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq)
+{
+    RTCState *s;
+    int io_memory;
+
+    s = qemu_mallocz(sizeof(RTCState));
+    if (!s)
+        return NULL;
+
+    s->irq = irq;
+    s->cmos_data[RTC_REG_A] = 0x26;
+    s->cmos_data[RTC_REG_B] = 0x02;
+    s->cmos_data[RTC_REG_C] = 0x00;
+    s->cmos_data[RTC_REG_D] = 0x80;
+    s->base = base;
+
+    rtc_set_date_from_host(s);
+
+    s->periodic_timer = qemu_new_timer(vm_clock,
+                                       rtc_periodic_timer, s);
+    s->second_timer = qemu_new_timer(vm_clock,
+                                     rtc_update_second, s);
+    s->second_timer2 = qemu_new_timer(vm_clock,
+                                      rtc_update_second2, s);
+
+    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+
+    io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
+    cpu_register_physical_memory(base, 2 << it_shift, io_memory);
+
+    register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+    return s;
+}

Deleted: trunk/src/host/qemu-neo1973/hw/md.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/md.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/md.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,499 +0,0 @@
-/*
- * DSCM-1XXXX Microdrive hard disk with CF+ II / PCMCIA interface.
- *
- * Copyright (c) 2006 Openedhand Ltd.
- * Written by Andrzej Zaborowski <balrog at zabor.org>
- *
- * This code is licensed under the GPLv2.
- */
-
-#include "vl.h"
-
-#define METADATA_SIZE	0x20
-
-struct md_s {
-    IDEState ide[2];
-    struct pcmcia_card_s card;
-    uint32_t attr_base;
-    uint32_t io_base;
-
-    /* Card state */
-    uint8_t opt;
-    uint8_t stat;
-    uint8_t pins;
-
-    uint8_t ctrl;
-    uint16_t io;
-    int cycle;
-};
-
-/* Register bitfields */
-enum md_opt {
-    OPT_MODE_MMAP	= 0,
-    OPT_MODE_IOMAP16	= 1,
-    OPT_MODE_IOMAP1	= 2,
-    OPT_MODE_IOMAP2	= 3,
-    OPT_MODE		= 0x3f,
-    OPT_LEVIREQ		= 0x40,
-    OPT_SRESET		= 0x80,
-};
-enum md_cstat {
-    STAT_INT		= 0x02,
-    STAT_PWRDWN		= 0x04,
-    STAT_XE		= 0x10,
-    STAT_IOIS8		= 0x20,
-    STAT_SIGCHG		= 0x40,
-    STAT_CHANGED	= 0x80,
-};
-enum md_pins {
-    PINS_MRDY		= 0x02,
-    PINS_CRDY		= 0x20,
-};
-enum md_ctrl {
-    CTRL_IEN		= 0x02,
-    CTRL_SRST		= 0x04,
-};
-
-static inline void md_interrupt_update(struct md_s *s)
-{
-    if (!s->card.slot)
-        return;
-
-    s->card.slot->set_irq(s->card.slot->opaque, 0,
-                    !(s->stat & STAT_INT) &&	/* Inverted */
-                    !(s->ctrl & (CTRL_IEN | CTRL_SRST)) &&
-                    !(s->opt & OPT_SRESET));
-}
-
-static void md_set_irq(void *opaque, int irq, int level)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    if (level)
-        s->stat |= STAT_INT;
-    else
-        s->stat &= ~STAT_INT;
-
-    md_interrupt_update(s);
-}
-
-static void md_reset(struct md_s *s)
-{
-    s->opt = OPT_MODE_MMAP;
-    s->stat = 0;
-    s->pins = 0;
-    s->cycle = 0;
-    s->ctrl = 0;
-    ide_reset(s->ide);
-}
-
-static uint8_t md_attr_read(void *opaque, uint16_t at)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    if (at < s->attr_base) {
-        if (at < s->card.cis_len)
-            return s->card.cis[at];
-        else
-            return 0x00;
-    }
-
-    at -= s->attr_base;
-
-    switch (at) {
-    case 0x00:	/* Configuration Option Register */
-        return s->opt;
-    case 0x02:	/* Card Configuration Status Register */
-        if (s->ctrl & CTRL_IEN)
-            return s->stat & ~STAT_INT;
-        else
-            return s->stat;
-    case 0x04:	/* Pin Replacement Register */
-        return (s->pins & PINS_CRDY) | 0x0c;
-    case 0x06:	/* Socket and Copy Register */
-        return 0x00;
-#ifdef VERBOSE
-    default:
-        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
-#endif
-    }
-
-    return 0;
-}
-
-static void md_attr_write(void *opaque, uint16_t at, uint8_t value)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    at -= s->attr_base;
-
-    switch (at) {
-    case 0x00:	/* Configuration Option Register */
-        s->opt = value & 0xcf;
-        if (value & OPT_SRESET)
-            md_reset(s);
-        md_interrupt_update(s);
-        break;
-    case 0x02:	/* Card Configuration Status Register */
-        if ((s->stat ^ value) & STAT_PWRDWN)
-            s->pins |= PINS_CRDY;
-        s->stat &= 0x82;
-        s->stat |= value & 0x74;
-        md_interrupt_update(s);
-        /* Word 170 in Identify Device must be equal to STAT_XE */
-        break;
-    case 0x04:	/* Pin Replacement Register */
-        s->pins &= PINS_CRDY;
-        s->pins |= value & PINS_MRDY;
-        break;
-    case 0x06:	/* Socket and Copy Register */
-        break;
-    default:
-        printf("%s: Bad attribute space register %02x\n", __FUNCTION__, at);
-    }
-}
-
-static uint16_t md_common_read(void *opaque, uint16_t at)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    uint16_t ret;
-    at -= s->io_base;
-
-    switch (s->opt & OPT_MODE) {
-    case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
-            at = 0;
-        break;
-    case OPT_MODE_IOMAP16:
-        at &= 0xf;
-        break;
-    case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
-            at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
-            at -= 0x1f0;
-        break;
-    case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
-            at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
-            at -= 0x170;
-    }
-
-    switch (at) {
-    case 0x0:	/* Even RD Data */
-    case 0x8:
-        return ide_data_readw(s->ide, 0);
-
-        /* TODO: 8-bit accesses */
-        if (s->cycle)
-            ret = s->io >> 8;
-        else {
-            s->io = ide_data_readw(s->ide, 0);
-            ret = s->io & 0xff;
-        }
-        s->cycle = !s->cycle;
-        return ret;
-    case 0x9:	/* Odd RD Data */
-        return s->io >> 8;
-    case 0xd:	/* Error */
-        return ide_ioport_read(s->ide, 0x1);
-    case 0xe:	/* Alternate Status */
-        if (s->ide->cur_drive->bs)
-            return s->ide->cur_drive->status;
-        else
-            return 0;
-    case 0xf:	/* Device Address */
-        return 0xc2 | ((~s->ide->select << 2) & 0x3c);
-    default:
-        return ide_ioport_read(s->ide, at);
-    }
-
-    return 0;
-}
-
-static void md_common_write(void *opaque, uint16_t at, uint16_t value)
-{
-    struct md_s *s = (struct md_s *) opaque;
-    at -= s->io_base;
-
-    switch (s->opt & OPT_MODE) {
-    case OPT_MODE_MMAP:
-        if ((at & ~0x3ff) == 0x400)
-            at = 0;
-        break;
-    case OPT_MODE_IOMAP16:
-        at &= 0xf;
-        break;
-    case OPT_MODE_IOMAP1:
-        if ((at & ~0xf) == 0x3f0)
-            at -= 0x3e8;
-        else if ((at & ~0xf) == 0x1f0)
-            at -= 0x1f0;
-        break;
-    case OPT_MODE_IOMAP2:
-        if ((at & ~0xf) == 0x370)
-            at -= 0x368;
-        else if ((at & ~0xf) == 0x170)
-            at -= 0x170;
-    }
-
-    switch (at) {
-    case 0x0:	/* Even WR Data */
-    case 0x8:
-        ide_data_writew(s->ide, 0, value);
-        break;
-
-        /* TODO: 8-bit accesses */
-        if (s->cycle)
-            ide_data_writew(s->ide, 0, s->io | (value << 8));
-        else
-            s->io = value & 0xff;
-        s->cycle = !s->cycle;
-        break;
-    case 0x9:
-        s->io = value & 0xff;
-        s->cycle = !s->cycle;
-        break;
-    case 0xd:	/* Features */
-        ide_ioport_write(s->ide, 0x1, value);
-        break;
-    case 0xe:	/* Device Control */
-        s->ctrl = value;
-        if (value & CTRL_SRST)
-            md_reset(s);
-        md_interrupt_update(s);
-        break;
-    default:
-        if (s->stat & STAT_PWRDWN) {
-            s->pins |= PINS_CRDY;
-            s->stat &= ~STAT_PWRDWN;
-        }
-        ide_ioport_write(s->ide, at, value);
-    }
-}
-
-static const uint8_t dscm1xxxx_cis[0x14a] = {
-    [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
-    [0x002] = 0x03,		/* Tuple length = 4 bytes */
-    [0x004] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
-    [0x006] = 0x01,		/* Size = 2K bytes */
-    [0x008] = CISTPL_ENDMARK,
-
-    [0x00a] = CISTPL_DEVICE_OC,	/* Additional Device Information */
-    [0x00c] = 0x04,		/* Tuple length = 4 byest */
-    [0x00e] = 0x03,		/* Conditions: Ext = 0, Vcc 3.3V, MWAIT = 1 */
-    [0x010] = 0xdb,		/* ID: DTYPE_FUNCSPEC, non WP, DSPEED_150NS */
-    [0x012] = 0x01,		/* Size = 2K bytes */
-    [0x014] = CISTPL_ENDMARK,
-
-    [0x016] = CISTPL_JEDEC_C,	/* JEDEC ID */
-    [0x018] = 0x02,		/* Tuple length = 2 bytes */
-    [0x01a] = 0xdf,		/* PC Card ATA with no Vpp required */
-    [0x01c] = 0x01,
-
-    [0x01e] = CISTPL_MANFID,	/* Manufacture ID */
-    [0x020] = 0x04,		/* Tuple length = 4 bytes */
-    [0x022] = 0xa4,		/* TPLMID_MANF = 00a4 (IBM) */
-    [0x024] = 0x00,
-    [0x026] = 0x00,		/* PLMID_CARD = 0000 */
-    [0x028] = 0x00,
-
-    [0x02a] = CISTPL_VERS_1,	/* Level 1 Version */
-    [0x02c] = 0x12,		/* Tuple length = 23 bytes */
-    [0x02e] = 0x04,		/* Major Version = JEIDA 4.2 / PCMCIA 2.1 */
-    [0x030] = 0x01,		/* Minor Version = 1 */
-    [0x032] = 'I',
-    [0x034] = 'B',
-    [0x036] = 'M',
-    [0x038] = 0x00,
-    [0x03a] = 'm',
-    [0x03c] = 'i',
-    [0x03e] = 'c',
-    [0x040] = 'r',
-    [0x042] = 'o',
-    [0x044] = 'd',
-    [0x046] = 'r',
-    [0x048] = 'i',
-    [0x04a] = 'v',
-    [0x04c] = 'e',
-    [0x04e] = 0x00,
-    [0x050] = CISTPL_ENDMARK,
-
-    [0x052] = CISTPL_FUNCID,	/* Function ID */
-    [0x054] = 0x02,		/* Tuple length = 2 bytes */
-    [0x056] = 0x04,		/* TPLFID_FUNCTION = Fixed Disk */
-    [0x058] = 0x01,		/* TPLFID_SYSINIT: POST = 1, ROM = 0 */
-
-    [0x05a] = CISTPL_FUNCE,	/* Function Extension */
-    [0x05c] = 0x02,		/* Tuple length = 2 bytes */
-    [0x05e] = 0x01,		/* TPLFE_TYPE = Disk Device Interface */
-    [0x060] = 0x01,		/* TPLFE_DATA = PC Card ATA Interface */
-
-    [0x062] = CISTPL_FUNCE,	/* Function Extension */
-    [0x064] = 0x03,		/* Tuple length = 3 bytes */
-    [0x066] = 0x02,		/* TPLFE_TYPE = Basic PC Card ATA Interface */
-    [0x068] = 0x08,		/* TPLFE_DATA: Rotating, Unique, Single */
-    [0x06a] = 0x0f,		/* TPLFE_DATA: Sleep, Standby, Idle, Auto */
-
-    [0x06c] = CISTPL_CONFIG,	/* Configuration */
-    [0x06e] = 0x05,		/* Tuple length = 5 bytes */
-    [0x070] = 0x01,		/* TPCC_RASZ = 2 bytes, TPCC_RMSZ = 1 byte */
-    [0x072] = 0x07,		/* TPCC_LAST = 7 */
-    [0x074] = 0x00,		/* TPCC_RADR = 0200 */
-    [0x076] = 0x02,
-    [0x078] = 0x0f,		/* TPCC_RMSK = 200, 202, 204, 206 */
-
-    [0x07a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x07c] = 0x0b,		/* Tuple length = 11 bytes */
-    [0x07e] = 0xc0,		/* TPCE_INDX = Memory Mode, Default, Iface */
-    [0x080] = 0xc0,		/* TPCE_IF = Memory, no BVDs, no WP, READY */
-    [0x082] = 0xa1,		/* TPCE_FS = Vcc only, no I/O, Memory, Misc */
-    [0x084] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x086] = 0x55,		/* NomV: 5.0 V */
-    [0x088] = 0x4d,		/* MinV: 4.5 V */
-    [0x08a] = 0x5d,		/* MaxV: 5.5 V */
-    [0x08c] = 0x4e,		/* Peakl: 450 mA */
-    [0x08e] = 0x08,		/* TPCE_MS = 1 window, 1 byte, Host address */
-    [0x090] = 0x00,		/* Window descriptor: Window length = 0 */
-    [0x092] = 0x20,		/* TPCE_MI: support power down mode, RW */
-
-    [0x094] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x096] = 0x06,		/* Tuple length = 6 bytes */
-    [0x098] = 0x00,		/* TPCE_INDX = Memory Mode, no Default */
-    [0x09a] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x09c] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x09e] = 0xb5,		/* NomV: 3.3 V */
-    [0x0a0] = 0x1e,
-    [0x0a2] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x0a4] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0a6] = 0x0d,		/* Tuple length = 13 bytes */
-    [0x0a8] = 0xc1,		/* TPCE_INDX = I/O and Memory Mode, Default */
-    [0x0aa] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x0ac] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x0ae] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x0b0] = 0x55,		/* NomV: 5.0 V */
-    [0x0b2] = 0x4d,		/* MinV: 4.5 V */
-    [0x0b4] = 0x5d,		/* MaxV: 5.5 V */
-    [0x0b6] = 0x4e,		/* Peakl: 450 mA */
-    [0x0b8] = 0x64,		/* TPCE_IO = 16-byte boundary, 16/8 accesses */
-    [0x0ba] = 0xf0,		/* TPCE_IR =  MASK, Level, Pulse, Share */
-    [0x0bc] = 0xff,		/* IRQ0..IRQ7 supported */
-    [0x0be] = 0xff,		/* IRQ8..IRQ15 supported */
-    [0x0c0] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x0c2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0c4] = 0x06,		/* Tuple length = 6 bytes */
-    [0x0c6] = 0x01,		/* TPCE_INDX = I/O and Memory Mode */
-    [0x0c8] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x0ca] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x0cc] = 0xb5,		/* NomV: 3.3 V */
-    [0x0ce] = 0x1e,
-    [0x0d0] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x0d2] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0d4] = 0x12,		/* Tuple length = 18 bytes */
-    [0x0d6] = 0xc2,		/* TPCE_INDX = I/O Primary Mode */
-    [0x0d8] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x0da] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x0dc] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x0de] = 0x55,		/* NomV: 5.0 V */
-    [0x0e0] = 0x4d,		/* MinV: 4.5 V */
-    [0x0e2] = 0x5d,		/* MaxV: 5.5 V */
-    [0x0e4] = 0x4e,		/* Peakl: 450 mA */
-    [0x0e6] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
-    [0x0e8] = 0x61,		/* Range: 2 fields, 2 bytes addr, 1 byte len */
-    [0x0ea] = 0xf0,		/* Field 1 address = 0x01f0 */
-    [0x0ec] = 0x01,
-    [0x0ee] = 0x07,		/* Address block length = 8 */
-    [0x0f0] = 0xf6,		/* Field 2 address = 0x03f6 */
-    [0x0f2] = 0x03,
-    [0x0f4] = 0x01,		/* Address block length = 2 */
-    [0x0f6] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
-    [0x0f8] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x0fa] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x0fc] = 0x06,		/* Tuple length = 6 bytes */
-    [0x0fe] = 0x02,		/* TPCE_INDX = I/O Primary Mode, no Default */
-    [0x100] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x102] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x104] = 0xb5,		/* NomV: 3.3 V */
-    [0x106] = 0x1e,
-    [0x108] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x10a] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x10c] = 0x12,		/* Tuple length = 18 bytes */
-    [0x10e] = 0xc3,		/* TPCE_INDX = I/O Secondary Mode, Default */
-    [0x110] = 0x41,		/* TPCE_IF = I/O and Memory, no BVD, no WP */
-    [0x112] = 0x99,		/* TPCE_FS = Vcc only, I/O, Interrupt, Misc */
-    [0x114] = 0x27,		/* NomV = 1, MinV = 1, MaxV = 1, Peakl = 1 */
-    [0x116] = 0x55,		/* NomV: 5.0 V */
-    [0x118] = 0x4d,		/* MinV: 4.5 V */
-    [0x11a] = 0x5d,		/* MaxV: 5.5 V */
-    [0x11c] = 0x4e,		/* Peakl: 450 mA */
-    [0x11e] = 0xea,		/* TPCE_IO = 1K boundary, 16/8 access, Range */
-    [0x120] = 0x61,		/* Range: 2 fields, 2 byte addr, 1 byte len */
-    [0x122] = 0x70,		/* Field 1 address = 0x0170 */
-    [0x124] = 0x01,
-    [0x126] = 0x07,		/* Address block length = 8 */
-    [0x128] = 0x76,		/* Field 2 address = 0x0376 */
-    [0x12a] = 0x03,
-    [0x12c] = 0x01,		/* Address block length = 2 */
-    [0x12e] = 0xee,		/* TPCE_IR = IRQ E, Level, Pulse, Share */
-    [0x130] = 0x20,		/* TPCE_MI = support power down mode */
-
-    [0x132] = CISTPL_CFTABLE_ENTRY,	/* 16-bit PC Card Configuration */
-    [0x134] = 0x06,		/* Tuple length = 6 bytes */
-    [0x136] = 0x03,		/* TPCE_INDX = I/O Secondary Mode */
-    [0x138] = 0x01,		/* TPCE_FS = Vcc only, no I/O, no Memory */
-    [0x13a] = 0x21,		/* NomV = 1, MinV = 0, MaxV = 0, Peakl = 1 */
-    [0x13c] = 0xb5,		/* NomV: 3.3 V */
-    [0x13e] = 0x1e,
-    [0x140] = 0x3e,		/* Peakl: 350 mA */
-
-    [0x142] = CISTPL_NO_LINK,	/* No Link */
-    [0x144] = 0x00,		/* Tuple length = 0 bytes */
-
-    [0x146] = CISTPL_END,	/* Tuple End */
-};
-
-static int dscm1xxxx_attach(void *opaque)
-{
-    struct md_s *md = (struct md_s *) opaque;
-    md->card.attr_read = md_attr_read;
-    md->card.attr_write = md_attr_write;
-    md->card.common_read = md_common_read;
-    md->card.common_write = md_common_write;
-    md->card.io_read = md_common_read;
-    md->card.io_write = md_common_write;
-
-    md->attr_base = md->card.cis[0x74] | (md->card.cis[0x76] << 8);
-    md->io_base = 0x0;
-
-    md_reset(md);
-    md_interrupt_update(md);
-
-    md->card.slot->card_string = "DSCM-1xxxx Hitachi Microdrive";
-    return 0;
-}
-
-static int dscm1xxxx_detach(void *opaque)
-{
-    struct md_s *md = (struct md_s *) opaque;
-    md_reset(md);
-    return 0;
-}
-
-struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv)
-{
-    struct md_s *md = (struct md_s *) qemu_mallocz(sizeof(struct md_s));
-    md->card.state = md;
-    md->card.attach = dscm1xxxx_attach;
-    md->card.detach = dscm1xxxx_detach;
-    md->card.cis = dscm1xxxx_cis;
-    md->card.cis_len = sizeof(dscm1xxxx_cis);
-
-    ide_init2(md->ide, bdrv, 0, md_set_irq, md, 0);
-    md->ide->is_cf = 1;
-    md->ide->mdata_size = METADATA_SIZE;
-    md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
-    return &md->card;
-}

Added: trunk/src/host/qemu-neo1973/hw/mips_int.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_int.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_int.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,44 @@
+#include "vl.h"
+#include "cpu.h"
+
+/* Raise IRQ to CPU if necessary. It must be called every time the active
+   IRQ may change */
+void cpu_mips_update_irq(CPUState *env)
+{
+    if ((env->CP0_Status & (1 << CP0St_IE)) &&
+        !(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM)) {
+        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
+            !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
+	}
+    } else
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+}
+
+static void cpu_mips_irq_request(void *opaque, int irq, int level)
+{
+    CPUState *env = (CPUState *)opaque;
+
+    if (irq < 0 || irq > 7)
+        return;
+
+    if (level) {
+        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+    } else {
+        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+    }
+    cpu_mips_update_irq(env);
+}
+
+void cpu_mips_irq_init_cpu(CPUState *env)
+{
+    qemu_irq *qi;
+    int i;
+
+    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
+    for (i = 0; i < 8; i++) {
+        env->irq[i] = qi[i];
+    }
+}

Added: trunk/src/host/qemu-neo1973/hw/mips_malta.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_malta.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,883 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2006 Aurelien Jarno
+ *
+ * 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 "vl.h"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
+#else
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
+#endif
+
+#define ENVP_ADDR (int32_t)0x80002000
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
+
+#define ENVP_NB_ENTRIES	 	16
+#define ENVP_ENTRY_SIZE	 	256
+
+
+extern FILE *logfile;
+
+typedef struct {
+    uint32_t leds;
+    uint32_t brk;
+    uint32_t gpout;
+    uint32_t i2cin;
+    uint32_t i2coe;
+    uint32_t i2cout;
+    uint32_t i2csel;
+    CharDriverState *display;
+    char display_text[9];
+    SerialState *uart;
+} MaltaFPGAState;
+
+static PITState *pit;
+
+/* Malta FPGA */
+static void malta_fpga_update_display(void *opaque)
+{
+    char leds_text[9];
+    int i;
+    MaltaFPGAState *s = opaque;
+
+    for (i = 7 ; i >= 0 ; i--) {
+        if (s->leds & (1 << i))
+            leds_text[i] = '#';
+	else
+            leds_text[i] = ' ';
+    }
+    leds_text[8] = '\0';
+
+    qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
+    qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
+}
+
+/*
+ * EEPROM 24C01 / 24C02 emulation.
+ *
+ * Emulation for serial EEPROMs:
+ * 24C01 - 1024 bit (128 x 8)
+ * 24C02 - 2048 bit (256 x 8)
+ *
+ * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
+ */
+
+//~ #define DEBUG
+
+#if defined(DEBUG)
+#  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
+#else
+#  define logout(fmt, args...) ((void)0)
+#endif
+
+struct _eeprom24c0x_t {
+  uint8_t tick;
+  uint8_t address;
+  uint8_t command;
+  uint8_t ack;
+  uint8_t scl;
+  uint8_t sda;
+  uint8_t data;
+  //~ uint16_t size;
+  uint8_t contents[256];
+};
+
+typedef struct _eeprom24c0x_t eeprom24c0x_t;
+
+static eeprom24c0x_t eeprom = {
+    contents: {
+        /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
+        /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
+        /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
+        /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
+        /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
+        /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
+        /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
+    },
+};
+
+static uint8_t eeprom24c0x_read()
+{
+    logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
+        eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
+    return eeprom.sda;
+}
+
+static void eeprom24c0x_write(int scl, int sda)
+{
+    if (eeprom.scl && scl && (eeprom.sda != sda)) {
+        logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
+        if (!sda) {
+            eeprom.tick = 1;
+            eeprom.command = 0;
+        }
+    } else if (eeprom.tick == 0 && !eeprom.ack) {
+        /* Waiting for start. */
+        logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    } else if (!eeprom.scl && scl) {
+        logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
+                eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+        if (eeprom.ack) {
+            logout("\ti2c ack bit = 0\n");
+            sda = 0;
+            eeprom.ack = 0;
+        } else if (eeprom.sda == sda) {
+            uint8_t bit = (sda != 0);
+            logout("\ti2c bit = %d\n", bit);
+            if (eeprom.tick < 9) {
+                eeprom.command <<= 1;
+                eeprom.command += bit;
+                eeprom.tick++;
+                if (eeprom.tick == 9) {
+                    logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
+                    eeprom.ack = 1;
+                }
+            } else if (eeprom.tick < 17) {
+                if (eeprom.command & 1) {
+                    sda = ((eeprom.data & 0x80) != 0);
+                }
+                eeprom.address <<= 1;
+                eeprom.address += bit;
+                eeprom.tick++;
+                eeprom.data <<= 1;
+                if (eeprom.tick == 17) {
+                    eeprom.data = eeprom.contents[eeprom.address];
+                    logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
+                    eeprom.ack = 1;
+                    eeprom.tick = 0;
+                }
+            } else if (eeprom.tick >= 17) {
+                sda = 0;
+            }
+        } else {
+            logout("\tsda changed with raising scl\n");
+        }
+    } else {
+        logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+    }
+    eeprom.scl = scl;
+    eeprom.sda = sda;
+}
+
+static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t val = 0;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        val = 0x00000000;		/* All switches closed */
+	break;
+
+    /* STATUS Register */
+    case 0x00208:
+#ifdef TARGET_WORDS_BIGENDIAN
+        val = 0x00000012;
+#else
+        val = 0x00000010;
+#endif
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        val = 0x00;
+        break;
+
+    /* LEDBAR Register */
+    case 0x00408:
+        val = s->leds;
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        val = s->brk;
+        break;
+
+    /* UART Registers */
+    case 0x00900:
+    case 0x00908:
+    case 0x00910:
+    case 0x00918:
+    case 0x00920:
+    case 0x00928:
+    case 0x00930:
+    case 0x00938:
+        val = serial_mm_readb(s->uart, addr);
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        val = s->gpout;
+        break;
+
+    /* XXX: implement a real I2C controller */
+
+    /* GPINP Register */
+    case 0x00a08:
+        /* IN = OUT until a real I2C control is implemented */
+        if (s->i2csel)
+            val = s->i2cout;
+        else
+            val = 0x00;
+        break;
+
+    /* I2CINP Register */
+    case 0x00b00:
+        val = ((s->i2cin & ~1) | eeprom24c0x_read());
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        val = s->i2coe;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        val = s->i2cout;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        val = s->i2csel;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
+		addr);
+#endif
+        break;
+    }
+    return val;
+}
+
+static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
+                              uint32_t val)
+{
+    MaltaFPGAState *s = opaque;
+    uint32_t saddr;
+
+    saddr = (addr & 0xfffff);
+
+    switch (saddr) {
+
+    /* SWITCH Register */
+    case 0x00200:
+        break;
+
+    /* JMPRS Register */
+    case 0x00210:
+        break;
+
+    /* LEDBAR Register */
+    /* XXX: implement a 8-LED array */
+    case 0x00408:
+        s->leds = val & 0xff;
+        break;
+
+    /* ASCIIWORD Register */
+    case 0x00410:
+        snprintf(s->display_text, 9, "%08X", val);
+        malta_fpga_update_display(s);
+        break;
+
+    /* ASCIIPOS0 to ASCIIPOS7 Registers */
+    case 0x00418:
+    case 0x00420:
+    case 0x00428:
+    case 0x00430:
+    case 0x00438:
+    case 0x00440:
+    case 0x00448:
+    case 0x00450:
+        s->display_text[(saddr - 0x00418) >> 3] = (char) val;
+        malta_fpga_update_display(s);
+        break;
+
+    /* SOFTRES Register */
+    case 0x00500:
+        if (val == 0x42)
+            qemu_system_reset_request ();
+        break;
+
+    /* BRKRES Register */
+    case 0x00508:
+        s->brk = val & 0xff;
+        break;
+
+    /* UART Registers */
+    case 0x00900:
+    case 0x00908:
+    case 0x00910:
+    case 0x00918:
+    case 0x00920:
+    case 0x00928:
+    case 0x00930:
+    case 0x00938:
+        serial_mm_writeb(s->uart, addr, val);
+        break;
+
+    /* GPOUT Register */
+    case 0x00a00:
+        s->gpout = val & 0xff;
+        break;
+
+    /* I2COE Register */
+    case 0x00b08:
+        s->i2coe = val & 0x03;
+        break;
+
+    /* I2COUT Register */
+    case 0x00b10:
+        eeprom24c0x_write(val & 0x02, val & 0x01);
+        s->i2cout = val;
+        break;
+
+    /* I2CSEL Register */
+    case 0x00b18:
+        s->i2csel = val & 0x01;
+        break;
+
+    default:
+#if 0
+        printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
+		addr);
+#endif
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *malta_fpga_read[] = {
+   malta_fpga_readl,
+   malta_fpga_readl,
+   malta_fpga_readl
+};
+
+static CPUWriteMemoryFunc *malta_fpga_write[] = {
+   malta_fpga_writel,
+   malta_fpga_writel,
+   malta_fpga_writel
+};
+
+void malta_fpga_reset(void *opaque)
+{
+    MaltaFPGAState *s = opaque;
+
+    s->leds   = 0x00;
+    s->brk    = 0x0a;
+    s->gpout  = 0x00;
+    s->i2cin  = 0x3;
+    s->i2coe  = 0x0;
+    s->i2cout = 0x3;
+    s->i2csel = 0x1;
+
+    s->display_text[8] = '\0';
+    snprintf(s->display_text, 9, "        ");
+    malta_fpga_update_display(s);
+}
+
+MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
+{
+    MaltaFPGAState *s;
+    CharDriverState *uart_chr;
+    int malta;
+
+    s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
+
+    malta = cpu_register_io_memory(0, malta_fpga_read,
+                                   malta_fpga_write, s);
+
+    cpu_register_physical_memory(base, 0x100000, malta);
+
+    s->display = qemu_chr_open("vc");
+    qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "\n");
+    qemu_chr_printf(s->display, "Malta ASCII\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+    qemu_chr_printf(s->display, "+        +\r\n");
+    qemu_chr_printf(s->display, "+--------+\r\n");
+
+    uart_chr = qemu_chr_open("vc");
+    qemu_chr_printf(uart_chr, "CBUS UART\r\n");
+    s->uart = serial_mm_init(base, 3, env->irq[2], uart_chr, 0);
+
+    malta_fpga_reset(s);
+    qemu_register_reset(malta_fpga_reset, s);
+
+    return s;
+}
+
+/* Audio support */
+#ifdef HAS_AUDIO
+static void audio_init (PCIBus *pci_bus)
+{
+    struct soundhw *c;
+    int audio_enabled = 0;
+
+    for (c = soundhw; !audio_enabled && c->name; ++c) {
+        audio_enabled = c->enabled;
+    }
+
+    if (audio_enabled) {
+        AudioState *s;
+
+        s = AUD_init ();
+        if (s) {
+            for (c = soundhw; c->name; ++c) {
+                if (c->enabled) {
+                    if (c->isa) {
+                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);
+                        exit(1);
+                    }
+                    else {
+                        if (pci_bus) {
+                            c->init.init_pci (pci_bus, s);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
+/* Network support */
+static void network_init (PCIBus *pci_bus)
+{
+    int i;
+    NICInfo *nd;
+
+    for(i = 0; i < nb_nics; i++) {
+        nd = &nd_table[i];
+        if (!nd->model) {
+            nd->model = "pcnet";
+        }
+        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
+            /* The malta board has a PCNet card using PCI SLOT 11 */
+            pci_nic_init(pci_bus, nd, 88);
+        } else {
+            pci_nic_init(pci_bus, nd, -1);
+        }
+    }
+}
+
+/* ROM and pseudo bootloader
+
+   The following code implements a very very simple bootloader. It first
+   loads the registers a0 to a3 to the values expected by the OS, and
+   then jump at the kernel address.
+
+   The bootloader should pass the locations of the kernel arguments and
+   environment variables tables. Those tables contain the 32-bit address
+   of NULL terminated strings. The environment variables table should be
+   terminated by a NULL address.
+
+   For a simpler implementation, the number of kernel arguments is fixed
+   to two (the name of the kernel and the command line), and the two
+   tables are actually the same one.
+
+   The registers a0 to a3 should contain the following values:
+     a0 - number of kernel arguments
+     a1 - 32-bit address of the kernel arguments table
+     a2 - 32-bit address of the environment variables table
+     a3 - RAM size in bytes
+*/
+
+static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
+{
+    uint32_t *p;
+
+    /* Small bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset);
+    stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON service vector */
+    stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */					
+    stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
+    stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */					
+    stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
+    stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
+    stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
+    stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
+    stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
+    stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
+    stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
+
+
+    /* Second part of the bootloader */
+    p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
+    stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
+    stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
+    stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
+    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */
+    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
+    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */
+    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */
+
+    /* Load BAR registers as done by YAMON */
+    stl_raw(p++, 0x3c09bbe0);                                      /* lui t1, 0xbbe0 */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c000);                                      /* lui t0, 0xc000 */
+#else
+    stl_raw(p++, 0x340800c0);                                      /* ori t0, r0, 0x00c0 */
+#endif
+    stl_raw(p++, 0xad280048);                                      /* sw t0, 0x0048(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c084000);                                      /* lui t0, 0x4000 */
+#else
+    stl_raw(p++, 0x34080040);                                      /* ori t0, r0, 0x0040 */
+#endif
+    stl_raw(p++, 0xad280050);                                      /* sw t0, 0x0050(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c088000);                                      /* lui t0, 0x8000 */
+#else
+    stl_raw(p++, 0x34080080);                                      /* ori t0, r0, 0x0080 */
+#endif
+    stl_raw(p++, 0xad280058);                                      /* sw t0, 0x0058(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c083f00);                                      /* lui t0, 0x3f00 */
+#else
+    stl_raw(p++, 0x3408003f);                                      /* ori t0, r0, 0x003f */
+#endif
+    stl_raw(p++, 0xad280060);                                      /* sw t0, 0x0060(t1) */
+
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c08c100);                                      /* lui t0, 0xc100 */
+#else
+    stl_raw(p++, 0x340800c1);                                      /* ori t0, r0, 0x00c1 */
+#endif
+    stl_raw(p++, 0xad280080);                                      /* sw t0, 0x0080(t1) */
+#ifdef TARGET_WORDS_BIGENDIAN
+    stl_raw(p++, 0x3c085e00);                                      /* lui t0, 0x5e00 */
+#else
+    stl_raw(p++, 0x3408005e);                                      /* ori t0, r0, 0x005e */
+#endif
+    stl_raw(p++, 0xad280088);                                      /* sw t0, 0x0088(t1) */
+
+    /* Jump to kernel code */
+    stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff));    /* lui ra, high(kernel_entry) */
+    stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff));            /* ori ra, ra, low(kernel_entry) */
+    stl_raw(p++, 0x03e00008);                                      /* jr ra */
+    stl_raw(p++, 0x00000000);                                      /* nop */
+
+    /* YAMON subroutines */
+    p = (uint32_t *) (phys_ram_base + bios_offset + 0x800);
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0x24020000);                                     /* li v0,0 */
+   /* 808 YAMON print */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x10800005);                                     /* beqz a0,834 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x08000205);                                     /* j 814 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x83c YAMON print_count */
+    stl_raw(p++, 0x03e06821);                                     /* move t5,ra */
+    stl_raw(p++, 0x00805821);                                     /* move t3,a0 */
+    stl_raw(p++, 0x00a05021);                                     /* move t2,a1 */
+    stl_raw(p++, 0x00c06021);                                     /* move t4,a2 */
+    stl_raw(p++, 0x91440000);                                     /* lbu a0,0(t2) */
+    stl_raw(p++, 0x0ff0021c);                                     /* jal 870 */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x254a0001);                                     /* addiu t2,t2,1 */
+    stl_raw(p++, 0x258cffff);                                     /* addiu t4,t4,-1 */
+    stl_raw(p++, 0x1580fffa);                                     /* bnez t4,84c */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x01a00008);                                     /* jr t5 */
+    stl_raw(p++, 0x01602021);                                     /* move a0,t3 */
+    /* 0x870 */
+    stl_raw(p++, 0x3c08b800);                                     /* lui t0,0xb400 */
+    stl_raw(p++, 0x350803f8);                                     /* ori t0,t0,0x3f8 */
+    stl_raw(p++, 0x91090005);                                     /* lbu t1,5(t0) */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x31290040);                                     /* andi t1,t1,0x40 */
+    stl_raw(p++, 0x1120fffc);                                     /* beqz t1,878 <outch+0x8> */
+    stl_raw(p++, 0x00000000);                                     /* nop */
+    stl_raw(p++, 0x03e00008);                                     /* jr ra */
+    stl_raw(p++, 0xa1040000);                                     /* sb a0,0(t0) */
+
+}
+
+static void prom_set(int index, const char *string, ...)
+{
+    va_list ap;
+    int32_t *p;
+    int32_t table_addr;
+    char *s;
+
+    if (index >= ENVP_NB_ENTRIES)
+        return;
+
+    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
+    p += index;
+
+    if (string == NULL) {
+        stl_raw(p, 0);
+        return;
+    }
+
+    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;
+    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);
+
+    stl_raw(p, table_addr);
+
+    va_start(ap, string);
+    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);
+    va_end(ap);
+}
+
+/* Kernel */
+static int64_t load_kernel (CPUState *env)
+{
+    int64_t kernel_entry, kernel_low, kernel_high;
+    int index = 0;
+    long initrd_size;
+    ram_addr_t initrd_offset;
+
+    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND,
+                 &kernel_entry, &kernel_low, &kernel_high) < 0) {
+        fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                env->kernel_filename);
+      exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (env->initrd_filename) {
+        initrd_size = get_image_size (env->initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > env->ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        env->initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image(env->initrd_filename,
+                                     phys_ram_base + initrd_offset);
+        }
+        if (initrd_size == (target_ulong) -1) {
+            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+                    env->initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Store command line.  */
+    prom_set(index++, env->kernel_filename);
+    if (initrd_size > 0)
+        prom_set(index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
+                 PHYS_TO_VIRT(initrd_offset), initrd_size,
+                 env->kernel_cmdline);
+    else
+        prom_set(index++, env->kernel_cmdline);
+
+    /* Setup minimum environment variables */
+    prom_set(index++, "memsize");
+    prom_set(index++, "%i", env->ram_size);
+    prom_set(index++, "modetty0");
+    prom_set(index++, "38400n8r");
+    prom_set(index++, NULL);
+
+    return kernel_entry;
+}
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+
+    /* The bootload does not need to be rewritten as it is located in a
+       read only location. The kernel location and the arguments table
+       location does not change. */
+    if (env->kernel_filename) {
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+        load_kernel (env);
+    }
+}
+
+static
+void mips_malta_init (int ram_size, int vga_ram_size, int boot_device,
+                      DisplayState *ds, const char **fd_filename, int snapshot,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename, const char *cpu_model)
+{
+    char buf[1024];
+    unsigned long bios_offset;
+    int64_t kernel_entry;
+    PCIBus *pci_bus;
+    CPUState *env;
+    RTCState *rtc_state;
+    /* fdctrl_t *floppy_controller; */
+    MaltaFPGAState *malta_fpga;
+    int ret;
+    mips_def_t *def;
+    qemu_irq *i8259;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
+    env = cpu_init();
+    cpu_mips_register(env, def);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* allocate RAM */
+    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+    /* Map the bios at two physical locations, as on the real board */
+    bios_offset = ram_size + vga_ram_size;
+    cpu_register_physical_memory(0x1e000000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+    cpu_register_physical_memory(0x1fc00000LL,
+                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);
+
+    /* Load a BIOS image except if a kernel image has been specified. In
+       the later case, just write a small bootloader to the flash
+       location. */
+    if (kernel_filename) {
+        env->ram_size = ram_size;
+        env->kernel_filename = kernel_filename;
+        env->kernel_cmdline = kernel_cmdline;
+        env->initrd_filename = initrd_filename;
+        kernel_entry = load_kernel(env);
+        env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
+        write_bootloader(env, bios_offset, kernel_entry);
+    } else {
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        ret = load_image(buf, phys_ram_base + bios_offset);
+        if (ret < 0 || ret > BIOS_SIZE) {
+            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+                    buf);
+            exit(1);
+        }
+    }
+
+    /* Board ID = 0x420 (Malta Board with CoreLV)
+       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
+       map to the board ID. */
+    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);
+
+    /* Init internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+    cpu_mips_irqctrl_init();
+
+    /* FPGA */
+    malta_fpga = malta_fpga_init(0x1f000000LL, env);
+
+    /* Interrupt controller */
+    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
+    i8259 = i8259_init(env->irq[2]);
+
+    /* Northbridge */
+    pci_bus = pci_gt64120_init(i8259);
+
+    /* Southbridge */
+    piix4_init(pci_bus, 80);
+    pci_piix3_ide_init(pci_bus, bs_table, 81, i8259);
+    usb_uhci_init(pci_bus, 82);
+    piix4_pm_init(pci_bus, 83);
+    pit = pit_init(0x40, i8259[0]);
+    DMA_init(0);
+
+    /* Super I/O */
+    i8042_init(i8259[1], i8259[12], 0x60);
+    rtc_state = rtc_init(0x70, i8259[8]);
+    if (serial_hds[0])
+        serial_init(0x3f8, i8259[4], serial_hds[0]);
+    if (serial_hds[1])
+        serial_init(0x2f8, i8259[3], serial_hds[1]);
+    if (parallel_hds[0])
+        parallel_init(0x378, i8259[7], parallel_hds[0]);
+    /* XXX: The floppy controller does not work correctly, something is
+       probably wrong.
+    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); */
+
+    /* Sound card */
+#ifdef HAS_AUDIO
+    audio_init(pci_bus);
+#endif
+
+    /* Network card */
+    network_init(pci_bus);
+
+    /* Optional PCI video card */
+    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size,
+                        ram_size, vga_ram_size);
+}
+
+QEMUMachine mips_malta_machine = {
+    "malta",
+    "MIPS Malta Core LV",
+    mips_malta_init,
+};

Added: trunk/src/host/qemu-neo1973/hw/mips_pica61.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_pica61.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,179 @@
+/*
+ * QEMU Malta board support
+ *
+ * Copyright (c) 2007 Hervé Poussineau
+ *
+ * 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 "vl.h"
+
+#ifdef TARGET_WORDS_BIGENDIAN
+#define BIOS_FILENAME "mips_bios.bin"
+#else
+#define BIOS_FILENAME "mipsel_bios.bin"
+#endif
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
+#else
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
+#endif
+
+#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
+
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
+static uint32_t serial_base[MAX_SERIAL_PORTS] = { 0x80006000, 0x80007000 };
+static int serial_irq[MAX_SERIAL_PORTS] = { 8, 9 };
+
+extern FILE *logfile;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+    cpu_reset(env);
+}
+
+static
+void mips_pica61_init (int ram_size, int vga_ram_size, int boot_device,
+                    DisplayState *ds, const char **fd_filename, int snapshot,
+                    const char *kernel_filename, const char *kernel_cmdline,
+                    const char *initrd_filename, const char *cpu_model)
+{
+    char buf[1024];
+    unsigned long bios_offset;
+    int bios_size;
+    CPUState *env;
+    int i;
+    mips_def_t *def;
+    int available_ram;
+    qemu_irq *i8259;
+
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        /* FIXME: All wrong, this maybe should be R3000 for the older PICAs. */
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
+    env = cpu_init();
+    cpu_mips_register(env, def);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    qemu_register_reset(main_cpu_reset, env);
+
+    /* allocate RAM (limited to 256 MB) */
+    if (ram_size < 256 * 1024 * 1024)
+        available_ram = ram_size;
+    else
+        available_ram = 256 * 1024 * 1024;
+    cpu_register_physical_memory(0, available_ram, IO_MEM_RAM);
+
+    /* load a BIOS image */
+    bios_offset = ram_size + vga_ram_size;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+    bios_size = load_image(buf, phys_ram_base + bios_offset);
+    if ((bios_size <= 0) || (bios_size > BIOS_SIZE)) {
+        /* fatal */
+        fprintf(stderr, "qemu: Error, could not load MIPS bios '%s'\n",
+                buf);
+        exit(1);
+    }
+    cpu_register_physical_memory(0x1fc00000,
+                                     BIOS_SIZE, bios_offset | IO_MEM_ROM);
+
+    /* Device map
+     *
+     * addr 0xe0004000: mc146818
+     * addr 0xe0005000 intr 6: ps2 keyboard
+     * addr 0xe0005000 intr 7: ps2 mouse
+     * addr 0xe0006000 intr 8: ns16550a,
+     * addr 0xe0007000 intr 9: ns16550a
+     * isa_io_base 0xe2000000 isa_mem_base 0xe3000000
+     */
+
+    /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
+    cpu_mips_clock_init(env);
+    cpu_mips_irqctrl_init();
+
+    /* Register 64 KB of ISA IO space at 0x10000000 */
+    isa_mmio_init(0x10000000, 0x00010000);
+    isa_mem_base = 0x11000000;
+
+    /* PC style IRQ (i8259/i8254) and DMA (i8257) */
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    i8259 = i8259_init(env->irq[2]);
+    rtc_mm_init(0x80004070, 1, i8259[14]);
+    pit_init(0x40, 0);
+
+    /* Keyboard (i8042) */
+    i8042_mm_init(i8259[6], i8259[7], 0x80005060, 0);
+
+    /* IDE controller */
+    for(i = 0; i < 2; i++)
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
+                     bs_table[2 * i], bs_table[2 * i + 1]);
+
+    /* Network controller */
+    /* FIXME: missing NS SONIC DP83932 */
+
+    /* SCSI adapter */
+    /* FIXME: missing NCR 53C94 */
+
+    /* ISA devices (floppy, serial, parallel) */
+    fdctrl_init(i8259[1], 1, 1, 0x80003000, fd_table);
+    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (serial_hds[i]) {
+            serial_mm_init(serial_base[i], 0, i8259[serial_irq[i]], serial_hds[i], 1);
+        }
+    }
+    for (i = 0; i < MAX_PARALLEL_PORTS; i++) {
+        if (parallel_hds[i]) {
+            /* FIXME: memory mapped! parallel_init(0x80008000, i8259[17], parallel_hds[i]); */
+        }
+    }
+
+    /* Sound card */
+    /* FIXME: missing Jazz sound, IRQ 18 */
+
+    /* LED indicator */
+    /* FIXME: missing LED indicator */
+
+    /* NVRAM */
+    ds1225y_init(0x80009000, "nvram");
+
+    /* Video card */
+    /* FIXME: This card is not the real one which was in the original PICA,
+     * but let's do with what Qemu currenly emulates... */
+    isa_vga_mm_init(ds, phys_ram_base + ram_size, ram_size, vga_ram_size,
+                    0x40000000, 0x60000000, 0);
+}
+
+QEMUMachine mips_pica61_machine = {
+    "pica61",
+    "Acer Pica 61",
+    mips_pica61_init,
+};

Modified: trunk/src/host/qemu-neo1973/hw/mips_r4k.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_r4k.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,11 +14,11 @@
 #else
 #define BIOS_FILENAME "mipsel_bios.bin"
 #endif
-//#define BIOS_FILENAME "system.bin"
-#ifdef MIPS_HAS_MIPS64
-#define INITRD_LOAD_ADDR (int64_t)(int32_t)0x80800000
+
+#ifdef TARGET_MIPS64
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
 #else
-#define INITRD_LOAD_ADDR (int32_t)0x80800000
+#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
 #endif
 
 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
@@ -35,18 +35,6 @@
 static PITState *pit; /* PIT i8254 */
 
 /*i8254 PIT is attached to the IRQ0 at PIC i8259 */
-/*The PIC is attached to the MIPS CPU INT0 pin */
-static void pic_irq_request(void *opaque, int level)
-{
-    CPUState *env = first_cpu;
-    if (level) {
-        env->CP0_Cause |= 0x00000400;
-        cpu_interrupt(env, CPU_INTERRUPT_HARD);
-    } else {
-	env->CP0_Cause &= ~0x00000400;
-        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-    }
-}
 
 static void mips_qemu_writel (void *opaque, target_phys_addr_t addr,
 			      uint32_t val)
@@ -80,10 +68,12 @@
 		  const char *kernel_cmdline,
 		  const char *initrd_filename)
 {
-    int64_t entry = 0;
+    int64_t entry, kernel_low, kernel_high;
     long kernel_size, initrd_size;
+    ram_addr_t initrd_offset;
 
-    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
+    kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND,
+                           &entry, &kernel_low, &kernel_high);
     if (kernel_size >= 0) {
         if ((entry & ~0x7fffffffULL) == 0x80000000)
             entry = (int32_t)entry;
@@ -96,9 +86,20 @@
 
     /* load initrd */
     initrd_size = 0;
+    initrd_offset = 0;
     if (initrd_filename) {
-        initrd_size = load_image(initrd_filename,
-                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
+        initrd_size = get_image_size (initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+            if (initrd_offset + initrd_size > ram_size) {
+                fprintf(stderr,
+                        "qemu: memory too small for initial ram disk '%s'\n",
+                        initrd_filename);
+                exit(1);
+            }
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_offset);
+        }
         if (initrd_size == (target_ulong) -1) {
             fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                     initrd_filename);
@@ -110,8 +111,8 @@
     if (initrd_size > 0) {
         int ret;
         ret = sprintf(phys_ram_base + (16 << 20) - 256,
-                      "rd_start=0x" TLSZ " rd_size=%li ",
-                      INITRD_LOAD_ADDR,
+                      "rd_start=0x" TARGET_FMT_lx " rd_size=%li ",
+                      PHYS_TO_VIRT((uint32_t)initrd_offset),
                       initrd_size);
         strcpy (phys_ram_base + (16 << 20) - 256 + ret, kernel_cmdline);
     }
@@ -119,8 +120,8 @@
         strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
     }
 
-    *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
-    *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
+    *(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
 }
 
 static void main_cpu_reset(void *opaque)
@@ -133,19 +134,33 @@
                      env->kernel_cmdline, env->initrd_filename);
 }
 
+static
 void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
                     DisplayState *ds, const char **fd_filename, int snapshot,
                     const char *kernel_filename, const char *kernel_cmdline,
-                    const char *initrd_filename)
+                    const char *initrd_filename, const char *cpu_model)
 {
     char buf[1024];
     unsigned long bios_offset;
     int bios_size;
     CPUState *env;
-    static RTCState *rtc_state;
+    RTCState *rtc_state;
     int i;
+    mips_def_t *def;
+    qemu_irq *i8259;
 
+    /* init CPUs */
+    if (cpu_model == NULL) {
+#ifdef TARGET_MIPS64
+        cpu_model = "R4000";
+#else
+        cpu_model = "24Kf";
+#endif
+    }
+    if (mips_find_by_name(cpu_model, &def) != 0)
+        def = NULL;
     env = cpu_init();
+    cpu_mips_register(env, def);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
     qemu_register_reset(main_cpu_reset, env);
 
@@ -154,7 +169,7 @@
 
     if (!mips_qemu_iomemtype) {
         mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
-						     mips_qemu_write, NULL);
+                                                     mips_qemu_write, NULL);
     }
     cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
 
@@ -166,7 +181,7 @@
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
-	cpu_register_physical_memory((uint32_t)(0x1fc00000),
+	cpu_register_physical_memory(0x1fc00000,
 				     BIOS_SIZE, bios_offset | IO_MEM_ROM);
     } else {
 	/* not fatal */
@@ -184,22 +199,24 @@
     }
 
     /* Init CPU internal devices */
+    cpu_mips_irq_init_cpu(env);
     cpu_mips_clock_init(env);
     cpu_mips_irqctrl_init();
 
-    rtc_state = rtc_init(0x70, 8);
+    /* The PIC is attached to the MIPS CPU INT0 pin */
+    i8259 = i8259_init(env->irq[2]);
 
+    rtc_state = rtc_init(0x70, i8259[8]);
+
     /* Register 64 KB of ISA IO space at 0x14000000 */
     isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
-    isa_pic = pic_init(pic_irq_request, env);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(0x40, i8259[0]);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(&pic_set_irq_new, isa_pic,
-                        serial_io[i], serial_irq[i], serial_hds[i]);
+            serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]);
         }
     }
 
@@ -209,7 +226,7 @@
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
-            isa_ne2000_init(0x300, 9, &nd_table[0]);
+            isa_ne2000_init(0x300, i8259[9], &nd_table[0]);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
@@ -217,8 +234,11 @@
     }
 
     for(i = 0; i < 2; i++)
-        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                      bs_table[2 * i], bs_table[2 * i + 1]);
+
+    i8042_init(i8259[1], i8259[12], 0x60);
+    ds1225y_init(0x9000, "nvram");
 }
 
 QEMUMachine mips_machine = {

Modified: trunk/src/host/qemu-neo1973/hw/mips_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/mips_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,7 +10,7 @@
     static uint32_t seed = 0;
     uint32_t idx;
     seed = seed * 314159 + 1;
-    idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
+    idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
     return idx;
 }
 
@@ -22,11 +22,11 @@
                            100 * 1000 * 1000, ticks_per_sec);
 }
 
-static void cpu_mips_update_count (CPUState *env, uint32_t count,
-                                   uint32_t compare)
+void cpu_mips_store_count (CPUState *env, uint32_t count)
 {
     uint64_t now, next;
     uint32_t tmp;
+    uint32_t compare = env->CP0_Compare;
 
     tmp = count;
     if (count == compare)
@@ -49,16 +49,21 @@
     qemu_mod_timer(env->timer, next);
 }
 
-void cpu_mips_store_count (CPUState *env, uint32_t value)
+static void cpu_mips_update_count (CPUState *env, uint32_t count)
 {
-    cpu_mips_update_count(env, value, env->CP0_Compare);
+    if (env->CP0_Cause & (1 << CP0Ca_DC))
+        return;
+
+    cpu_mips_store_count(env, count);
 }
 
 void cpu_mips_store_compare (CPUState *env, uint32_t value)
 {
-    cpu_mips_update_count(env, cpu_mips_get_count(env), value);
-    env->CP0_Cause &= ~0x00008000;
-    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    env->CP0_Compare = value;
+    cpu_mips_update_count(env, cpu_mips_get_count(env));
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+        env->CP0_Cause &= ~(1 << CP0Ca_TI);
+    qemu_irq_lower(env->irq[7]);
 }
 
 static void mips_timer_cb (void *opaque)
@@ -71,15 +76,15 @@
         fprintf(logfile, "%s\n", __func__);
     }
 #endif
-    cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
-    env->CP0_Cause |= 0x00008000;
-    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    cpu_mips_update_count(env, cpu_mips_get_count(env));
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+        env->CP0_Cause |= 1 << CP0Ca_TI;
+    qemu_irq_raise(env->irq[7]);
 }
 
 void cpu_mips_clock_init (CPUState *env)
 {
     env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
     env->CP0_Compare = 0;
-    cpu_mips_update_count(env, 1, 0);
+    cpu_mips_update_count(env, 1);
 }
-

Modified: trunk/src/host/qemu-neo1973/hw/modem.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -11,9 +11,6 @@
 struct modem_s {
     int enable;
     CharDriverState chr;
-    IOCanRWHandler *can_read;
-    IOReadHandler *read;
-    void *opaque;
     int cmd_len;
     char cmd[1024];
 #define FIFO_LEN	4096
@@ -31,24 +28,15 @@
     s->baud_delay = ticks_per_sec;
 }
 
-static void modem_add_read_handler(CharDriverState *chr,
-                IOCanRWHandler *modem_can_read, IOReadHandler *modem_read,
-                void *opaque)
-{
-    struct modem_s *s = (struct modem_s *) chr->opaque;
-
-    s->can_read = modem_can_read;
-    s->read = modem_read;
-    s->opaque = opaque;
-}
-
 static inline void modem_fifo_wake(struct modem_s *s)
 {
     if (!s->enable || !s->out_len)
         return;
 
-    if (s->can_read && s->can_read(s->opaque) && s->read) {
-        s->read(s->opaque, s->outfifo + s->out_start ++, 1);
+    if (s->chr.chr_can_read && s->chr.chr_can_read(s->chr.handler_opaque) &&
+                    s->chr.chr_read) {
+        s->chr.chr_read(s->chr.handler_opaque,
+                        s->outfifo + s->out_start ++, 1);
         s->out_len --;
         s->out_start &= FIFO_LEN - 1;
     }
@@ -440,7 +428,6 @@
     s->chr.opaque = s;
     s->chr.chr_write = modem_write;
     s->chr.chr_ioctl = modem_ioctl;
-    s->chr.chr_add_read_handler = modem_add_read_handler;
     s->out_tm = qemu_new_timer(vm_clock, modem_out_tick, s);
 
     return &s->chr;

Modified: trunk/src/host/qemu-neo1973/hw/nand.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/nand.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/nand.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -6,7 +6,7 @@
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #ifndef NAND_IO
@@ -396,24 +396,14 @@
 {
     int pagesize;
     struct nand_flash_s *s;
-    BlockDriverState *bs = 0;
 
     if (nand_flash_ids[chip_id].size == 0) {
         cpu_abort(cpu_single_env, "%s: Unsupported NAND chip ID.\n",
                         __FUNCTION__);
     }
 
-    if (mtd_filename) {
-        bs = bdrv_new("mtd");
-        if (bdrv_open(bs, mtd_filename, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
-                        qemu_key_check(bs, mtd_filename)) {
-            bdrv_delete(bs);
-            bs = 0;
-        }
-    }
- 
     s = (struct nand_flash_s *) qemu_mallocz(sizeof(struct nand_flash_s));
-    s->bdrv = bs;
+    s->bdrv = mtd_bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
     s->size = nand_flash_ids[s->chip_id].size << 20;
@@ -442,13 +432,13 @@
 
     pagesize = 1 << s->oob_shift;
     s->mem_oob = 1;
-    if (bs && bdrv_getlength(bs) >=
+    if (s->bdrv && bdrv_getlength(s->bdrv) >=
                     (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
         pagesize = 0;
         s->mem_oob = 0;
     }
 
-    if (!bs)
+    if (!s->bdrv)
         pagesize += 1 << s->page_shift;
     if (pagesize)
         s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize),

Modified: trunk/src/host/qemu-neo1973/hw/ne2000.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ne2000.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ne2000.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -136,7 +136,7 @@
     uint8_t phys[6]; /* mac address */
     uint8_t curpag;
     uint8_t mult[8]; /* multicast mask array */
-    int irq;
+    qemu_irq irq;
     PCIDevice *pci_dev;
     VLANClientState *vc;
     uint8_t macaddr[6];
@@ -164,16 +164,10 @@
     int isr;
     isr = (s->isr & s->imr) & 0x7f;
 #if defined(DEBUG_NE2000)
-    printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
-	   s->irq, isr ? 1 : 0, s->isr, s->imr);
+    printf("NE2000: Set IRQ to %d (%02x %02x)\n",
+	   isr ? 1 : 0, s->isr, s->imr);
 #endif
-    if (s->irq == 16) {
-        /* PCI irq */
-        pci_set_irq(s->pci_dev, 0, (isr != 0));
-    } else {
-        /* ISA irq */
-        pic_set_irq(s->irq, (isr != 0));
-    }
+    qemu_set_irq(s->irq, (isr != 0));
 }
 
 #define POLYNOMIAL 0x04c11db6
@@ -206,7 +200,7 @@
 
     index = s->curpag << 8;
     boundary = s->boundary << 8;
-    if (index <= boundary)
+    if (index < boundary)
         avail = boundary - index;
     else
         avail = (s->stop - s->start) - (index - boundary);
@@ -647,6 +641,7 @@
 static void ne2000_save(QEMUFile* f,void* opaque)
 {
 	NE2000State* s=(NE2000State*)opaque;
+        int tmp;
 
         if (s->pci_dev)
             pci_device_save(s->pci_dev, f);
@@ -669,7 +664,8 @@
 	qemu_put_buffer(f, s->phys, 6);
 	qemu_put_8s(f, &s->curpag);
 	qemu_put_buffer(f, s->mult, 8);
-	qemu_put_be32s(f, &s->irq);
+        tmp = 0;
+	qemu_put_be32s(f, &tmp); /* ignored, was irq */
 	qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
 }
 
@@ -677,6 +673,7 @@
 {
 	NE2000State* s=(NE2000State*)opaque;
         int ret;
+        int tmp;
 
         if (version_id > 3)
             return -EINVAL;
@@ -709,13 +706,13 @@
 	qemu_get_buffer(f, s->phys, 6);
 	qemu_get_8s(f, &s->curpag);
 	qemu_get_buffer(f, s->mult, 8);
-	qemu_get_be32s(f, &s->irq);
+	qemu_get_be32s(f, &tmp); /* ignored */
 	qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
 
 	return 0;
 }
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd)
+void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
 {
     NE2000State *s;
     
@@ -781,7 +778,7 @@
     register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
 }
 
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCINE2000State *d;
     NE2000State *s;
@@ -789,7 +786,7 @@
     
     d = (PCINE2000State *)pci_register_device(bus,
                                               "NE2000", sizeof(PCINE2000State),
-                                              -1, 
+                                              devfn, 
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; // Realtek 8029
@@ -804,7 +801,7 @@
     pci_register_io_region(&d->dev, 0, 0x100, 
                            PCI_ADDRESS_SPACE_IO, ne2000_map);
     s = &d->ne2000;
-    s->irq = 16; // PCI interrupt
+    s->irq = d->dev.irq[0];
     s->pci_dev = (PCIDevice *)d;
     memcpy(s->macaddr, nd->macaddr, 6);
     ne2000_reset(s);

Modified: trunk/src/host/qemu-neo1973/hw/neo1973.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/neo1973.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -56,15 +56,15 @@
 
 struct neo_board_s {
     struct s3c_state_s *cpu;
-    struct i2c_slave_s *pmu;
-    struct i2c_slave_s *wm;
-    struct i2c_slave_s *lcm;
+    i2c_slave *pmu;
+    i2c_slave *wm;
+    i2c_slave *lcm;
     CharDriverState *modem;
-    void *kbd_pic;
+    qemu_irq *kbd_pic;
 };
 
 /* Handlers for output ports */
-static void neo_bl_switch(int line, int level, void *opaque)
+static void neo_bl_switch(void *opaque, int line, int level)
 {
     neo_printf("LCD Backlight now %s.\n", level ? "on" : "off");
 }
@@ -80,46 +80,46 @@
 #endif
 }
 
-static void neo_gpspwr_switch(int line, int level, void *opaque)
+static void neo_gpspwr_switch(void *opaque, int line, int level)
 {
     neo_printf("GPS powered %s.\n", level ? "up" : "down");
 }
 
-static void neo_modem_rst_switch(int line, int level, void *opaque)
+static void neo_modem_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("Modem reset.\n");
 }
 
-static void neo_modem_switch(int line, int level, void *opaque)
+static void neo_modem_switch(void *opaque, int line, int level)
 {
     struct neo_board_s *s = (struct neo_board_s *) opaque;
     modem_enable(s->modem, level);
     neo_printf("Modem powered %s.\n", level ? "up" : "down");
 }
 
-static void neo_lcd_rst_switch(int line, int level, void *opaque)
+static void neo_lcd_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("LCD reset.\n");
 }
 
-static void neo_vib_switch(int line, int level, void *opaque)
+static void neo_vib_switch(void *opaque, int line, int level)
 {
     neo_printf("%s.\n", level ? "Buzz, buzz" : "Vibrator stopped");
 }
 
-static void neo_gsm_switch(int line, int level, void *opaque)
+static void neo_gsm_switch(void *opaque, int line, int level)
 {
     neo_printf("GSM %sabled.\n", level ? "dis" : "en");
 }
 
-static void neo_bt_switch(int line, int level, void *opaque)
+static void neo_bt_switch(void *opaque, int line, int level)
 {
     neo_printf("Bluetooth transciever %sabled.\n", level ? "en" : "dis");
 }
 
-static void neo_gps_switch(int line, int level, void *opaque)
+static void neo_gps_switch(void *opaque, int line, int level)
 {
     neo_printf("GPS %sV supply is now %s.\n",
 #ifdef GTA01Bv3
@@ -130,19 +130,19 @@
                     level ? "on" : "off");
 }
 
-static void neo_gps_rst_switch(int line, int level, void *opaque)
+static void neo_gps_rst_switch(void *opaque, int line, int level)
 {
     if (level)
         neo_printf("GPS reset.\n");
 }
 
 /* Handlers for input ports */
-static void neo_mmc_cover_switch(void *pic, int in)
+static void neo_mmc_cover_switch(void *irq, int in)
 {
-    pic_set_irq_new(pic, GTA01_IRQ_nSD_DETECT, !in);
+    qemu_set_irq((qemu_irq) irq, !in);
 }
 
-static void neo_mmc_writeprotect_switch(void *pic, int wp)
+static void neo_mmc_writeprotect_switch(void *irq, int wp)
 {
 }
 
@@ -152,10 +152,10 @@
     struct neo_board_s *s = (struct neo_board_s *) opaque;
     switch (keycode & 0x7f) {
     case 0x1c:	/* Return */
-        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_911_KEY, !(keycode & 0x80));
+        qemu_set_irq(s->kbd_pic[GTA01_IRQ_911_KEY], !(keycode & 0x80));
         break;
     case 0x39:	/* Space */
-        pic_set_irq_new(s->kbd_pic, GTA01_IRQ_HOLD_KEY, !(keycode & 0x80));
+        qemu_set_irq(s->kbd_pic[GTA01_IRQ_HOLD_KEY], !(keycode & 0x80));
         pcf_onkey_set(s->pmu, !(keycode & 80));	/* Active LOW */
         break;
     }
@@ -163,45 +163,47 @@
 
 static void neo_kbd_init(struct neo_board_s *s)
 {
-    s->kbd_pic = s->cpu->io;
+    s->kbd_pic = s3c_gpio_in_get(s->cpu->io);
     qemu_add_kbd_event_handler(neo_kbd_handler, s);
 }
 
 static void neo_gpio_setup(struct neo_board_s *s)
 {
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BACKLIGHT,
-                    neo_bl_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_PWRON,
-                    neo_gpspwr_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_RST,
-                    neo_modem_rst_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_MODEM_ON,
-                    neo_modem_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_LCD_RESET,
-                    neo_lcd_rst_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON,
-                    neo_vib_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON2,
-                    neo_vib_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01v3_GPIO_nGSM_EN,
-                    neo_gsm_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01Bv2_GPIO_nGSM_EN,
-                    neo_gsm_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_BT_EN,
-                    neo_bt_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_2V8,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V3,
-                    neo_gps_switch, s);
-    s3c_gpio_handler_set(s->cpu->io, GTA01_GPIO_GPS_RESET,
-                    neo_gps_rst_switch, s);
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_BACKLIGHT,
+                    *qemu_allocate_irqs(neo_bl_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_PWRON,
+                    *qemu_allocate_irqs(neo_gpspwr_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_MODEM_RST,
+                    *qemu_allocate_irqs(neo_modem_rst_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_MODEM_ON,
+                    *qemu_allocate_irqs(neo_modem_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_LCD_RESET,
+                    *qemu_allocate_irqs(neo_lcd_rst_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON,
+                    *qemu_allocate_irqs(neo_vib_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_VIBRATOR_ON2,
+                    *qemu_allocate_irqs(neo_vib_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01v3_GPIO_nGSM_EN,
+                    *qemu_allocate_irqs(neo_gsm_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01Bv2_GPIO_nGSM_EN,
+                    *qemu_allocate_irqs(neo_gsm_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_BT_EN,
+                    *qemu_allocate_irqs(neo_bt_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_2V8,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_EN_3V3,
+                    *qemu_allocate_irqs(neo_gps_switch, s, 1));
+    s3c_gpio_out_set(s->cpu->io, GTA01_GPIO_GPS_RESET,
+                    *qemu_allocate_irqs(neo_gps_rst_switch, s, 1));
 
     s3c_timers_cmp_handler_set(s->cpu->timers, 0, neo_bl_intensity, s);
 
     /* MMC/SD host */
-    s3c_mmci_handlers(s->cpu->mmci, s->cpu->io, neo_mmc_writeprotect_switch,
+    s3c_mmci_handlers(s->cpu->mmci,
+                    s3c_gpio_in_get(s->cpu->io)[GTA01_IRQ_nSD_DETECT],
+                    neo_mmc_writeprotect_switch,
                     neo_mmc_cover_switch);
 }
 
@@ -214,48 +216,47 @@
 
 /* National Semiconductor LM4857 Boomer audio amplifier */
 struct lm4857_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
+    i2c_slave i2c;
     uint8_t regs[4];
 };
 
-void lm_reset(struct i2c_slave_s *i2c)
+void lm_reset(i2c_slave *i2c)
 {
-    struct lm4857_s *s = (struct lm4857_s *) i2c->opaque;
+    struct lm4857_s *s = (struct lm4857_s *) i2c;
     memset(s->regs, 0, sizeof(s->regs));
 }
 
-static void lm_start(void *opaque, int dir)
+static void lm_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct lm4857_s *s = (struct lm4857_s *) opaque;
-    s->i2c_dir = dir;
 }
 
-static int lm_tx(void *opaque, uint8_t *data, int len)
+static int lm_rx(i2c_slave *i2c)
 {
-    struct lm4857_s *s = (struct lm4857_s *) opaque;
+    return 0x00;
+}
+
+static int lm_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct lm4857_s *s = (struct lm4857_s *) i2c;
     int reg, value;
-    if (s->i2c_dir)
-        return 1;
 
-    while (len --) {
-        reg = *data >> 6;
-        value = *(data ++) & 0x3f;
+    reg = data >> 6;
+    value = data & 0x3f;
 
-        if ((reg == 1 || reg == 2) && ((s->regs[reg] ^ value) & (1 << 5)))
-            printf("%s: 3D enhance %s.\n", __FUNCTION__,
-                            (value & (1 << 5)) ? "On" : "Off");
-        s->regs[reg] = value;
-    }
+    if ((reg == 1 || reg == 2) && ((s->regs[reg] ^ value) & (1 << 5)))
+        printf("%s: 3D enhance %s.\n", __FUNCTION__,
+                        (value & (1 << 5)) ? "On" : "Off");
+    s->regs[reg] = value;
     return 0;
 }
 
-struct i2c_slave_s *lm4857_init()
+i2c_slave *lm4857_init(i2c_bus *bus)
 {
-    struct lm4857_s *s = qemu_mallocz(sizeof(struct lm4857_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = lm_tx;
-    s->i2c.start = lm_start;
+    struct lm4857_s *s = (struct lm4857_s *)
+            i2c_slave_init(bus, 0, sizeof(struct lm4857_s));
+    s->i2c.event = lm_event;
+    s->i2c.send = lm_tx;
+    s->i2c.recv = lm_rx;
 
     lm_reset(&s->i2c);
 
@@ -269,34 +270,32 @@
 
 static void neo_i2c_setup(struct neo_board_s *s)
 {
-    struct i2c_bus_s *bus = (struct i2c_bus_s *)
-            qemu_mallocz(sizeof(struct i2c_bus_s));
+    /* Attach the CPU on one end of our I2C bus.  */
+    i2c_bus *bus = s3c_i2c_bus(s->cpu->i2c);
 #ifdef HAS_AUDIO
     AudioState *audio;
 #endif
 
-    s->pmu = pcf5060x_init(s->cpu->pic, GTA01_IRQ_PCF50606, 0);
-    s->lcm = lm4857_init();
-
-    /* Attach the CPU on one end of our I2C bus.  */
-    i2c_master_attach(bus, s3c_i2c_master(s->cpu->i2c));
-
     /* Attach a PCF50606 to the bus */
-    i2c_slave_attach(bus, NEO_PMU_ADDR, s->pmu);
+    s->pmu = pcf5060x_init(bus,
+                    s3c_gpio_in_get(s->cpu->io)[GTA01_IRQ_PCF50606], 0);
+    i2c_set_slave_address(s->pmu, NEO_PMU_ADDR);
 
     /* Attach a LM4857 to the bus */
-    i2c_slave_attach(bus, NEO_AMP_ADDR, s->lcm);
+    s->lcm = lm4857_init(bus);
+    i2c_set_slave_address(s->lcm, NEO_AMP_ADDR);
 
 #ifdef HAS_AUDIO
     audio = AUD_init();
     if (!audio)
         return;
-    s->wm = wm8753_init(audio);
 
     /* Attach a WM8750 to the bus */
-    i2c_slave_attach(bus, NEO_WM_ADDR, s->wm);
+    s->wm = wm8753_init(bus, audio);
+    i2c_set_slave_address(s->wm, NEO_WM_ADDR);
+
     /* .. and to the sound interface.  */
-    s->cpu->i2s->opaque = s->wm->opaque;
+    s->cpu->i2s->opaque = s->wm;
     s->cpu->i2s->codec_out = wm8753_dac_dat;
     s->cpu->i2s->codec_in = wm8753_adc_dat;
     wm8753_data_req_set(s->wm, s->cpu->i2s->data_req, s->cpu->i2s);
@@ -329,23 +328,23 @@
 static void neo_init(int ram_size, int vga_ram_size, int boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+                const char *initrd_filename, const char *cpu_model)
 {
     uint32_t neo_ram = 0x08000000;
     struct neo_board_s *s = (struct neo_board_s *)
             qemu_mallocz(sizeof(struct neo_board_s));
 
-    s->cpu = s3c2410_init(ds);
-
-    /* Setup memory */
-    if (ram_size < neo_ram + s->cpu->free_ram_start) {
+    /* Setup CPU & memory */
+    if (ram_size < neo_ram + S3C_SRAM_SIZE) {
         fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        neo_ram + s->cpu->free_ram_start);
+                        neo_ram + S3C_SRAM_SIZE);
         exit(1);
     }
-    cpu_register_physical_memory(S3C_RAM_BASE, neo_ram,
-                    s->cpu->free_ram_start | IO_MEM_RAM);
-    s->cpu->free_ram_start += neo_ram;
+    if (cpu_model && strcmp(cpu_model, "arm920t")) {
+        fprintf(stderr, "This platform requires an ARM920T core\n");
+        exit(2);
+    }
+    s->cpu = s3c2410_init(neo_ram, ds);
 
     s3c_nand_register(s->cpu, nand_init(NAND_MFR_SAMSUNG, 0x76));
 
@@ -370,9 +369,9 @@
                     initrd_filename, 0x49e, S3C_RAM_BASE);
 #else
     load_image("u-boot.bin",
-                    phys_ram_base + S3C_SRAM_SIZE + 0x03f80000);
+                    phys_ram_base + 0x03f80000);
     load_image(kernel_filename,
-                    phys_ram_base + S3C_SRAM_SIZE + 0x02000000);
+                    phys_ram_base + 0x02000000);
     s->cpu->env->regs[15] = S3C_RAM_BASE | 0x03f80000;
 #endif
 

Modified: trunk/src/host/qemu-neo1973/hw/openpic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/openpic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/openpic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -159,10 +159,10 @@
     uint32_t pcsr; /* CPU sensitivity register */
     IRQ_queue_t raised;
     IRQ_queue_t servicing;
-    CPUState *env;
+    qemu_irq *irqs;
 } IRQ_dst_t;
 
-struct openpic_t {
+typedef struct openpic_t {
     PCIDevice pci_dev;
     int mem_index;
     /* Global registers */
@@ -170,6 +170,7 @@
     uint32_t glbc; /* Global configuration register  */
     uint32_t micr; /* MPIC interrupt configuration register */
     uint32_t veni; /* Vendor identification register */
+    uint32_t pint; /* Processor initialization register */
     uint32_t spve; /* Spurious vector register */
     uint32_t tifr; /* Timer frequency reporting register */
     /* Source registers */
@@ -195,7 +196,9 @@
 	uint32_t mbr;    /* Mailbox register */
     } mailboxes[MAX_MAILBOXES];
 #endif
-};
+    /* IRQ out is used when in bypass mode (not implemented) */
+    qemu_irq irq_out;
+} openpic_t;
 
 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
 {
@@ -254,19 +257,34 @@
     priority = IPVP_PRIORITY(src->ipvp);
     if (priority <= dst->pctp) {
 	/* 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;
     }
     set_bit(&src->ipvp, IPVP_ACTIVITY);
     IRQ_setbit(&dst->raised, n_IRQ);
-    if (priority > dst->raised.priority) {
-        IRQ_get_next(opp, &dst->raised);
-        DPRINTF("Raise CPU IRQ\n");
-        cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
+    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;
     }
+    IRQ_get_next(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;
+    }
+    DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
+    qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
 }
 
 /* update pic state because registers for n_IRQ have changed value */
@@ -279,27 +297,34 @@
 
     if (!src->pending) {
         /* no irq pending */
+        DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
         return;
     }
     if (test_bit(&src->ipvp, IPVP_MASK)) {
 	/* Interrupt source is disabled */
+        DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
 	return;
     }
     if (IPVP_PRIORITY(src->ipvp) == 0) {
 	/* Priority set to zero */
+        DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
 	return;
     }
     if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
         /* IRQ already active */
+        DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
         return;
     }
     if (src->ide == 0x00000000) {
 	/* No target */
+        DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
 	return;
     }
 
-    if (!test_bit(&src->ipvp, IPVP_MODE) ||
-        src->ide == (1 << src->last_cpu)) {
+    if (src->ide == (1 << src->last_cpu)) {
+        /* Only one CPU is allowed to receive this IRQ */
+        IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
+    } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
         /* Directed delivery mode */
         for (i = 0; i < opp->nb_cpus; i++) {
             if (test_bit(&src->ide, i))
@@ -307,9 +332,8 @@
         }
     } else {
         /* Distributed delivery mode */
-        /* XXX: incorrect code */
-        for (i = src->last_cpu; i < src->last_cpu; i++) {
-            if (i == MAX_IRQ)
+        for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
+            if (i == opp->nb_cpus)
                 i = 0;
             if (test_bit(&src->ide, i)) {
                 IRQ_local_pipe(opp, i, n_IRQ);
@@ -320,7 +344,7 @@
     }
 }
 
-void openpic_set_irq(void *opaque, int n_IRQ, int level)
+static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
@@ -349,6 +373,7 @@
     /* Initialise controller registers */
     opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
     opp->veni = VENI;
+    opp->pint = 0x00000000;
     opp->spve = 0x000000FF;
     opp->tifr = 0x003F7A00;
     /* ? */
@@ -359,7 +384,7 @@
 	opp->src[i].ide  = 0x00000000;
     }
     /* Initialise IRQ destinations */
-    for (i = 0; i < opp->nb_cpus; i++) {
+    for (i = 0; i < MAX_CPU; i++) {
 	opp->dst[i].pctp      = 0x0000000F;
 	opp->dst[i].pcsr      = 0x00000000;
 	memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
@@ -510,6 +535,8 @@
 static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
 {
     openpic_t *opp = opaque;
+    IRQ_dst_t *dst;
+    int idx;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
@@ -529,11 +556,18 @@
     case 0x80: /* VENI */
 	break;
     case 0x90: /* PINT */
-        /* XXX: Should be able to reset any CPU */
-        if (val & 1) {
-            DPRINTF("Reset CPU IRQ\n");
-            //            cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
+        for (idx = 0; idx < opp->nb_cpus; idx++) {
+            if ((val & (1 << idx)) && !(opp->pint & (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))) {
+                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;
 	break;
 #if MAX_IPI > 0
     case 0xA0: /* IPI_IPVP */
@@ -734,7 +768,7 @@
     openpic_t *opp = opaque;
     IRQ_src_t *src;
     IRQ_dst_t *dst;
-    int idx, n_IRQ;
+    int idx, s_IRQ, n_IRQ;
 
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
@@ -769,21 +803,21 @@
 	break;
     case 0xB0: /* PEOI */
         DPRINTF("PEOI\n");
-	n_IRQ = IRQ_get_next(opp, &dst->servicing);
-	IRQ_resetbit(&dst->servicing, n_IRQ);
+	s_IRQ = IRQ_get_next(opp, &dst->servicing);
+	IRQ_resetbit(&dst->servicing, s_IRQ);
 	dst->servicing.next = -1;
-	src = &opp->src[n_IRQ];
 	/* Set up next servicing IRQ */
-	IRQ_get_next(opp, &dst->servicing);
-	/* Check queued interrupts. */
-	n_IRQ = IRQ_get_next(opp, &dst->raised);
-	if (n_IRQ != -1) {
-	    src = &opp->src[n_IRQ];
-	    if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
-                DPRINTF("Raise CPU IRQ\n");
-                cpu_interrupt(dst->env, CPU_INTERRUPT_HARD);
-            }
-	}
+	s_IRQ = IRQ_get_next(opp, &dst->servicing);
+        /* Check queued interrupts. */
+        n_IRQ = IRQ_get_next(opp, &dst->raised);
+        src = &opp->src[n_IRQ];
+        if (n_IRQ != -1 &&
+            (s_IRQ == -1 ||
+             IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
+            DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
+                    idx, n_IRQ);
+            qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_INT]);
+        }
 	break;
     default:
         break;
@@ -814,11 +848,13 @@
 	retval = idx;
 	break;
     case 0xA0: /* PIAC */
+        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);
 	if (n_IRQ == -1) {
 	    /* No more interrupt pending */
-            retval = opp->spve;
+            retval = IPVP_VECTOR(opp->spve);
 	} else {
 	    src = &opp->src[n_IRQ];
 	    if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
@@ -963,8 +999,8 @@
 #endif
 }
 
-openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
-                         CPUPPCState **envp)
+qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out)
 {
     openpic_t *opp;
     uint8_t *pci_conf;
@@ -994,7 +1030,6 @@
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
     }
-
     opp->mem_index = cpu_register_io_memory(0, openpic_read,
                                             openpic_write, opp);
     
@@ -1019,9 +1054,11 @@
         opp->src[i].type = IRQ_INTERNAL;
     }
     for (i = 0; i < nb_cpus; i++)
-        opp->dst[i].env = envp[i];
+        opp->dst[i].irqs = irqs[i];
+    opp->irq_out = irq_out;
     openpic_reset(opp);
     if (pmem_index)
         *pmem_index = opp->mem_index;
-    return opp;
+
+    return qemu_allocate_irqs(openpic_set_irq, opp, MAX_IRQ);
 }

Modified: trunk/src/host/qemu-neo1973/hw/parallel.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/parallel.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/parallel.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,6 +2,7 @@
  * QEMU Parallel PORT emulation
  * 
  * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2007 Marko Kohtala
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +26,18 @@
 
 //#define DEBUG_PARALLEL
 
+#ifdef DEBUG_PARALLEL
+#define pdebug(fmt, arg...) printf("pp: " fmt, ##arg)
+#else
+#define pdebug(fmt, arg...) ((void)0)
+#endif
+
+#define PARA_REG_DATA 0
+#define PARA_REG_STS 1
+#define PARA_REG_CTR 2
+#define PARA_REG_EPP_ADDR 3
+#define PARA_REG_EPP_DATA 4
+
 /*
  * These are the definitions for the Printer Status Register
  */
@@ -33,129 +46,362 @@
 #define PARA_STS_PAPER	0x20	/* Out of paper */
 #define PARA_STS_ONLINE	0x10	/* Online */
 #define PARA_STS_ERROR	0x08	/* Error complement */
+#define PARA_STS_TMOUT	0x01	/* EPP timeout */
 
 /*
  * These are the definitions for the Printer Control Register
  */
+#define PARA_CTR_DIR	0x20	/* Direction (1=read, 0=write) */
 #define PARA_CTR_INTEN	0x10	/* IRQ Enable */
 #define PARA_CTR_SELECT	0x08	/* Select In complement */
 #define PARA_CTR_INIT	0x04	/* Initialize Printer complement */
 #define PARA_CTR_AUTOLF	0x02	/* Auto linefeed complement */
 #define PARA_CTR_STROBE	0x01	/* Strobe complement */
 
+#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)
+
 struct ParallelState {
-    uint8_t data;
-    uint8_t status; /* read only register */
+    uint8_t dataw;
+    uint8_t datar;
+    uint8_t status;
     uint8_t control;
-    int irq;
+    qemu_irq irq;
     int irq_pending;
     CharDriverState *chr;
     int hw_driver;
+    int epp_timeout;
+    uint32_t last_read_offset; /* For debugging */
 };
 
 static void parallel_update_irq(ParallelState *s)
 {
     if (s->irq_pending)
-        pic_set_irq(s->irq, 1);
+        qemu_irq_raise(s->irq);
     else
-        pic_set_irq(s->irq, 0);
+        qemu_irq_lower(s->irq);
 }
 
-static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static void
+parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
 {
     ParallelState *s = opaque;
     
+    pdebug("write addr=0x%02x val=0x%02x\n", addr, val);
+
     addr &= 7;
-#ifdef DEBUG_PARALLEL
-    printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
-#endif
     switch(addr) {
-    case 0:
-        if (s->hw_driver) {
-            s->data = val;
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
-        } else {
-            s->data = val;
-            parallel_update_irq(s);
-        }
+    case PARA_REG_DATA:
+	s->dataw = val;
+	parallel_update_irq(s);
         break;
-    case 2:
-        if (s->hw_driver) {
-            s->control = val;
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
-        } else {
-            if ((val & PARA_CTR_INIT) == 0 ) {
-                s->status = PARA_STS_BUSY;
-                s->status |= PARA_STS_ACK;
-                s->status |= PARA_STS_ONLINE;
-                s->status |= PARA_STS_ERROR;
-            }
-            else if (val & PARA_CTR_SELECT) {
-                if (val & PARA_CTR_STROBE) {
-                    s->status &= ~PARA_STS_BUSY;
-                    if ((s->control & PARA_CTR_STROBE) == 0)
-                        qemu_chr_write(s->chr, &s->data, 1);
-                } else {
-                    if (s->control & PARA_CTR_INTEN) {
-                        s->irq_pending = 1;
-                    }
-                }
-            }
-            parallel_update_irq(s);
-            s->control = val;
-        }
+    case PARA_REG_CTR:
+	if ((val & PARA_CTR_INIT) == 0 ) {
+	    s->status = PARA_STS_BUSY;
+	    s->status |= PARA_STS_ACK;
+	    s->status |= PARA_STS_ONLINE;
+	    s->status |= PARA_STS_ERROR;
+	}
+	else if (val & PARA_CTR_SELECT) {
+	    if (val & PARA_CTR_STROBE) {
+		s->status &= ~PARA_STS_BUSY;
+		if ((s->control & PARA_CTR_STROBE) == 0)
+		    qemu_chr_write(s->chr, &s->dataw, 1);
+	    } else {
+		if (s->control & PARA_CTR_INTEN) {
+		    s->irq_pending = 1;
+		}
+	    }
+	}
+	parallel_update_irq(s);
+	s->control = val;
         break;
     }
 }
 
-static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
+static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 {
     ParallelState *s = opaque;
+    uint8_t parm = val;
+
+    /* Sometimes programs do several writes for timing purposes on old
+       HW. Take care not to waste time on writes that do nothing. */
+
+    s->last_read_offset = ~0U;
+
+    addr &= 7;
+    switch(addr) {
+    case PARA_REG_DATA:
+        if (s->dataw == val)
+	    return;
+	pdebug("wd%02x\n", val);
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
+	s->dataw = val;
+        break;
+    case PARA_REG_STS:
+	pdebug("ws%02x\n", val);
+	if (val & PARA_STS_TMOUT)
+	    s->epp_timeout = 0;
+	break;
+    case PARA_REG_CTR:
+        val |= 0xc0;
+        if (s->control == val)
+	    return;
+	pdebug("wc%02x\n", val);
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
+	s->control = val;
+        break;
+    case PARA_REG_EPP_ADDR:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
+	    /* Controls not correct for EPP address cycle, so do nothing */
+	    pdebug("wa%02x s\n", val);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("wa%02x t\n", val);
+	    }
+	    else
+		pdebug("wa%02x\n", val);
+	}
+	break;
+    case PARA_REG_EPP_DATA:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT)
+	    /* Controls not correct for EPP data cycle, so do nothing */
+	    pdebug("we%02x s\n", val);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("we%02x t\n", val);
+	    }
+	    else
+		pdebug("we%02x\n", val);
+	}
+	break;
+    }
+}
+
+static void
+parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
+{
+    ParallelState *s = opaque;
+    uint16_t eppdata = cpu_to_le16(val);
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("we%04x s\n", val);
+	return;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("we%04x t\n", val);
+    }
+    else
+	pdebug("we%04x\n", val);
+}
+
+static void
+parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
+{
+    ParallelState *s = opaque;
+    uint32_t eppdata = cpu_to_le32(val);
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != PARA_CTR_INIT) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("we%08x s\n", val);
+	return;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("we%08x t\n", val);
+    }
+    else
+	pdebug("we%08x\n", val);
+}
+
+static uint32_t parallel_ioport_read_sw(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
     uint32_t ret = 0xff;
 
     addr &= 7;
     switch(addr) {
-    case 0:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
-        } 
-        ret = s->data; 
+    case PARA_REG_DATA:
+	if (s->control & PARA_CTR_DIR)
+	    ret = s->datar;
+	else
+	    ret = s->dataw;
         break;
-    case 1:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
-            ret = s->status; 
-        } else {
-            ret = s->status;
-            s->irq_pending = 0;
-            if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
-                /* XXX Fixme: wait 5 microseconds */
-                if (s->status & PARA_STS_ACK)
-                    s->status &= ~PARA_STS_ACK;
-                else {
-                    /* XXX Fixme: wait 5 microseconds */
-                    s->status |= PARA_STS_ACK;
-                    s->status |= PARA_STS_BUSY;
-                }
-            }
-            parallel_update_irq(s);
-        }
+    case PARA_REG_STS:
+	ret = s->status;
+	s->irq_pending = 0;
+	if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
+	    /* XXX Fixme: wait 5 microseconds */
+	    if (s->status & PARA_STS_ACK)
+		s->status &= ~PARA_STS_ACK;
+	    else {
+		/* XXX Fixme: wait 5 microseconds */
+		s->status |= PARA_STS_ACK;
+		s->status |= PARA_STS_BUSY;
+	    }
+	}
+	parallel_update_irq(s);
         break;
-    case 2:
-        if (s->hw_driver) {
-            qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
-        }
+    case PARA_REG_CTR:
         ret = s->control;
         break;
     }
-#ifdef DEBUG_PARALLEL
-    printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
-#endif
+    pdebug("read addr=0x%02x val=0x%02x\n", addr, ret);
     return ret;
 }
 
+static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint8_t ret = 0xff;
+    addr &= 7;
+    switch(addr) {
+    case PARA_REG_DATA:
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
+	if (s->last_read_offset != addr || s->datar != ret)
+	    pdebug("rd%02x\n", ret);
+        s->datar = ret;
+        break;
+    case PARA_REG_STS:
+	qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
+	ret &= ~PARA_STS_TMOUT;
+	if (s->epp_timeout)
+	    ret |= PARA_STS_TMOUT;
+	if (s->last_read_offset != addr || s->status != ret)
+	    pdebug("rs%02x\n", ret);
+	s->status = ret;
+        break;
+    case PARA_REG_CTR:
+        /* s->control has some bits fixed to 1. It is zero only when
+	   it has not been yet written to.  */
+	if (s->control == 0) {
+	    qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
+	    if (s->last_read_offset != addr)
+		pdebug("rc%02x\n", ret);
+	    s->control = ret;
+	}
+	else {
+	    ret = s->control;
+	    if (s->last_read_offset != addr)
+		pdebug("rc%02x\n", ret);
+	}
+        break;
+    case PARA_REG_EPP_ADDR:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
+	    /* Controls not correct for EPP addr cycle, so do nothing */
+	    pdebug("ra%02x s\n", ret);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("ra%02x t\n", ret);
+	    }
+	    else
+		pdebug("ra%02x\n", ret);
+	}
+	break;
+    case PARA_REG_EPP_DATA:
+	if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
+	    /* Controls not correct for EPP data cycle, so do nothing */
+	    pdebug("re%02x s\n", ret);
+	else {
+	    struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
+	    if (qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
+		s->epp_timeout = 1;
+		pdebug("re%02x t\n", ret);
+	    }
+	    else
+		pdebug("re%02x\n", ret);
+	}
+	break;
+    }
+    s->last_read_offset = addr;
+    return ret;
+}
+
+static uint32_t
+parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint32_t ret;
+    uint16_t eppdata = ~0;
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("re%04x s\n", eppdata);
+	return eppdata;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
+    ret = le16_to_cpu(eppdata);
+
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("re%04x t\n", ret);
+    }
+    else
+	pdebug("re%04x\n", ret);
+    return ret;
+}
+
+static uint32_t
+parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
+{
+    ParallelState *s = opaque;
+    uint32_t ret;
+    uint32_t eppdata = ~0U;
+    int err;
+    struct ParallelIOArg ioarg = {
+	.buffer = &eppdata, .count = sizeof(eppdata)
+    };
+    if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT)) {
+	/* Controls not correct for EPP data cycle, so do nothing */
+	pdebug("re%08x s\n", eppdata);
+	return eppdata;
+    }
+    err = qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
+    ret = le32_to_cpu(eppdata);
+
+    if (err) {
+	s->epp_timeout = 1;
+	pdebug("re%08x t\n", ret);
+    }
+    else
+	pdebug("re%08x\n", ret);
+    return ret;
+}
+
+static void parallel_ioport_ecp_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    addr &= 7;
+    pdebug("wecp%d=%02x\n", addr, val);
+}
+
+static uint32_t parallel_ioport_ecp_read(void *opaque, uint32_t addr)
+{
+    uint8_t ret = 0xff;
+    addr &= 7;
+    pdebug("recp%d:%02x\n", addr, ret);
+    return ret;
+}
+
 /* If fd is zero, it means that the parallel device uses the console */
-ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
+ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr)
 {
     ParallelState *s;
     uint8_t dummy;
@@ -163,21 +409,39 @@
     s = qemu_mallocz(sizeof(ParallelState));
     if (!s)
         return NULL;
-    s->chr = chr;
-    s->hw_driver = 0;
-    if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
-        s->hw_driver = 1;
-
-    s->irq = irq;
-    s->data = 0;
+    s->datar = ~0;
+    s->dataw = ~0;
     s->status = PARA_STS_BUSY;
     s->status |= PARA_STS_ACK;
     s->status |= PARA_STS_ONLINE;
     s->status |= PARA_STS_ERROR;
     s->control = PARA_CTR_SELECT;
     s->control |= PARA_CTR_INIT;
+    s->irq = irq;
+    s->irq_pending = 0;
+    s->chr = chr;
+    s->hw_driver = 0;
+    s->epp_timeout = 0;
+    s->last_read_offset = ~0U;
 
-    register_ioport_write(base, 8, 1, parallel_ioport_write, s);
-    register_ioport_read(base, 8, 1, parallel_ioport_read, s);
+    if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
+        s->hw_driver = 1;
+	s->status = dummy;
+    }
+
+    if (s->hw_driver) {
+	register_ioport_write(base, 8, 1, parallel_ioport_write_hw, s);
+	register_ioport_read(base, 8, 1, parallel_ioport_read_hw, s);
+	register_ioport_write(base+4, 1, 2, parallel_ioport_eppdata_write_hw2, s);
+	register_ioport_read(base+4, 1, 2, parallel_ioport_eppdata_read_hw2, s);
+	register_ioport_write(base+4, 1, 4, parallel_ioport_eppdata_write_hw4, s);
+	register_ioport_read(base+4, 1, 4, parallel_ioport_eppdata_read_hw4, s);
+	register_ioport_write(base+0x400, 8, 1, parallel_ioport_ecp_write, s);
+	register_ioport_read(base+0x400, 8, 1, parallel_ioport_ecp_read, s);
+    }
+    else {
+	register_ioport_write(base, 8, 1, parallel_ioport_write_sw, s);
+	register_ioport_read(base, 8, 1, parallel_ioport_read_sw, s);
+    }
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -32,9 +32,11 @@
 #define LINUX_BOOT_FILENAME "linux_boot.bin"
 
 #define KERNEL_LOAD_ADDR     0x00100000
-#define INITRD_LOAD_ADDR     0x00600000
+#define MAX_INITRD_LOAD_ADDR 0x38000000
 #define KERNEL_PARAMS_ADDR   0x00090000
 #define KERNEL_CMDLINE_ADDR  0x00099000
+/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
+#define ACPI_DATA_SIZE       0x10000
 
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
@@ -47,15 +49,16 @@
 }
 
 /* MSDOS compatibility mode FPU exception support */
+static qemu_irq ferr_irq;
 /* XXX: add IGNNE support */
 void cpu_set_ferr(CPUX86State *s)
 {
-    pic_set_irq(13, 1);
+    qemu_irq_raise(ferr_irq);
 }
 
 static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
 {
-    pic_set_irq(13, 0);
+    qemu_irq_lower(ferr_irq);
 }
 
 /* TSC handling */
@@ -99,7 +102,7 @@
     return intno;
 }
 
-static void pic_irq_request(void *opaque, int level)
+static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *env = opaque;
     if (level)
@@ -401,7 +404,7 @@
 static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 #ifdef HAS_AUDIO
-static void audio_init (PCIBus *pci_bus)
+static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
 {
     struct soundhw *c;
     int audio_enabled = 0;
@@ -418,7 +421,7 @@
             for (c = soundhw; c->name; ++c) {
                 if (c->enabled) {
                     if (c->isa) {
-                        c->init.init_isa (s);
+                        c->init.init_isa (s, pic);
                     }
                     else {
                         if (pci_bus) {
@@ -432,13 +435,13 @@
 }
 #endif
 
-static void pc_init_ne2k_isa(NICInfo *nd)
+static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 {
     static int nb_ne2k = 0;
 
     if (nb_ne2k == NE2000_NB_MAX)
         return;
-    isa_ne2000_init(ne2000_io[nb_ne2k], ne2000_irq[nb_ne2k], nd);
+    isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
     nb_ne2k++;
 }
 
@@ -451,12 +454,15 @@
 {
     char buf[1024];
     int ret, linux_boot, initrd_size, i;
-    unsigned long bios_offset, vga_bios_offset, option_rom_offset;
-    int bios_size, isa_bios_size;
+    ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset;
+    ram_addr_t initrd_offset;
+    int bios_size, isa_bios_size, vga_bios_size;
     PCIBus *pci_bus;
     int piix3_devfn = -1;
     CPUState *env;
     NICInfo *nd;
+    qemu_irq *cpu_irq;
+    qemu_irq *i8259;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -477,23 +483,24 @@
     }
 
     /* allocate RAM */
-    cpu_register_physical_memory(0, ram_size, 0);
+    ram_addr = qemu_ram_alloc(ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_addr);
 
+    /* allocate VGA RAM */
+    vga_ram_addr = qemu_ram_alloc(vga_ram_size);
+
     /* BIOS load */
-    bios_offset = ram_size + vga_ram_size;
-    vga_bios_offset = bios_offset + 256 * 1024;
-
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = get_image_size(buf);
     if (bios_size <= 0 || 
-        (bios_size % 65536) != 0 ||
-        bios_size > (256 * 1024)) {
+        (bios_size % 65536) != 0) {
         goto bios_error;
     }
+    bios_offset = qemu_ram_alloc(bios_size);
     ret = load_image(buf, phys_ram_base + bios_offset);
     if (ret != bios_size) {
     bios_error:
-        fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
+        fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", buf);
         exit(1);
     }
 
@@ -503,8 +510,18 @@
     } else {
         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
     }
+    vga_bios_size = get_image_size(buf);
+    if (vga_bios_size <= 0 || vga_bios_size > 65536) 
+        goto vga_bios_error;
+    vga_bios_offset = qemu_ram_alloc(65536);
+
     ret = load_image(buf, phys_ram_base + vga_bios_offset);
-    
+    if (ret != vga_bios_size) {
+    vga_bios_error:
+        fprintf(stderr, "qemu: could not load VGA BIOS '%s'\n", buf);
+        exit(1);
+    }
+
     /* setup basic memory access */
     cpu_register_physical_memory(0xc0000, 0x10000, 
                                  vga_bios_offset | IO_MEM_ROM);
@@ -519,20 +536,32 @@
                                  isa_bios_size, 
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-    option_rom_offset = 0;
-    for (i = 0; i < nb_option_roms; i++) {
-	int offset = bios_offset + bios_size + option_rom_offset;
-	int size;
+    {
+        ram_addr_t option_rom_offset;
+        int size, offset;
 
-	size = load_image(option_rom[i], phys_ram_base + offset);
-	if ((size + option_rom_offset) > 0x10000) {
-	    fprintf(stderr, "Too many option ROMS\n");
-	    exit(1);
-	}
-	cpu_register_physical_memory(0xd0000 + option_rom_offset,
-				     size, offset | IO_MEM_ROM);
-	option_rom_offset += size + 2047;
-	option_rom_offset -= (option_rom_offset % 2048);
+        offset = 0;
+        for (i = 0; i < nb_option_roms; i++) {
+            size = get_image_size(option_rom[i]);
+            if (size < 0) {
+                fprintf(stderr, "Could not load option rom '%s'\n", 
+                        option_rom[i]);
+                exit(1);
+            }
+            if (size > (0x10000 - offset))
+                goto option_rom_error;
+            option_rom_offset = qemu_ram_alloc(size);
+            ret = load_image(option_rom[i], phys_ram_base + option_rom_offset);
+            if (ret != size) {
+            option_rom_error:
+                fprintf(stderr, "Too many option ROMS\n");
+                exit(1);
+            }
+            size = (size + 4095) & ~4095;
+            cpu_register_physical_memory(0xd0000 + offset,
+                                         size, option_rom_offset | IO_MEM_ROM);
+            offset += size;
+        }
     }
 
     /* map all the bios at the top of memory */
@@ -576,8 +605,28 @@
         
         /* load initrd */
         initrd_size = 0;
+        initrd_offset = 0;
         if (initrd_filename) {
-            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
+            initrd_size = get_image_size (initrd_filename);
+            if (initrd_size > 0) {
+                initrd_offset = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+                /* Leave space for BIOS ACPI tables.  */
+                initrd_offset -= ACPI_DATA_SIZE;
+                /* Avoid the last 64k to avoid 2.2.x kernel bugs.  */
+                initrd_offset -= 0x10000;
+                if (initrd_offset > MAX_INITRD_LOAD_ADDR)
+                    initrd_offset = MAX_INITRD_LOAD_ADDR;
+
+                if (initrd_size > ram_size
+                    || initrd_offset < KERNEL_LOAD_ADDR + ret) {
+                    fprintf(stderr,
+                            "qemu: memory too small for initial ram disk '%s'\n",
+                            initrd_filename);
+                    exit(1);
+                }
+                initrd_size = load_image(initrd_filename,
+                                         phys_ram_base + initrd_offset);
+            }
             if (initrd_size < 0) {
                 fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
                         initrd_filename);
@@ -585,7 +634,7 @@
             }
         }
         if (initrd_size > 0) {
-            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
+            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, initrd_offset);
             stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
         }
         pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
@@ -597,9 +646,13 @@
         stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
     }
 
+    cpu_irq = qemu_allocate_irqs(pic_irq_request, first_cpu, 1);
+    i8259 = i8259_init(cpu_irq[0]);
+    ferr_irq = i8259[13];
+
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state);
-        piix3_devfn = piix3_init(pci_bus);
+        pci_bus = i440fx_init(&i440fx_state, i8259);
+        piix3_devfn = piix3_init(pci_bus, -1);
     } else {
         pci_bus = NULL;
     }
@@ -612,23 +665,29 @@
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
             pci_cirrus_vga_init(pci_bus, 
-                                ds, phys_ram_base + ram_size, ram_size, 
-                                vga_ram_size);
+                                ds, phys_ram_base + vga_ram_addr, 
+                                vga_ram_addr, vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size, 
-                                vga_ram_size);
+            isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr, 
+                                vga_ram_addr, vga_ram_size);
         }
+    } else if (vmsvga_enabled) {
+        if (pci_enabled)
+            pci_vmsvga_init(pci_bus, ds, phys_ram_base + ram_size,
+                            ram_size, vga_ram_size);
+        else
+            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
     } else {
         if (pci_enabled) {
-            pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
-                         vga_ram_size, 0, 0);
+            pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, 
+                         vga_ram_addr, vga_ram_size, 0, 0);
         } else {
-            isa_vga_init(ds, phys_ram_base + ram_size, ram_size, 
-                         vga_ram_size);
+            isa_vga_init(ds, phys_ram_base + vga_ram_addr, 
+                         vga_ram_addr, vga_ram_size);
         }
     }
 
-    rtc_state = rtc_init(0x70, 8);
+    rtc_state = rtc_init(0x70, i8259[8]);
 
     register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
@@ -636,8 +695,7 @@
     if (pci_enabled) {
         ioapic = ioapic_init();
     }
-    isa_pic = pic_init(pic_irq_request, first_cpu);
-    pit = pit_init(0x40, 0);
+    pit = pit_init(0x40, i8259[0]);
     pcspk_init(pit);
     if (pci_enabled) {
         pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
@@ -645,14 +703,14 @@
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(&pic_set_irq_new, isa_pic,
-                        serial_io[i], serial_irq[i], serial_hds[i]);
+            serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
+            parallel_init(parallel_io[i], i8259[parallel_irq[i]],
+                          parallel_hds[i]);
         }
     }
 
@@ -666,11 +724,9 @@
             }
         }
         if (strcmp(nd->model, "ne2k_isa") == 0) {
-            pc_init_ne2k_isa(nd);
-        } else if (strcmp(nd->model, "usb") == 0) {
-            /* ignore */
+            pc_init_ne2k_isa(nd, i8259);
         } else if (pci_enabled) {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
             exit(1);
@@ -678,21 +734,21 @@
     }
 
     if (pci_enabled) {
-        pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1);
+        pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1, i8259);
     } else {
         for(i = 0; i < 2; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+            isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                          bs_table[2 * i], bs_table[2 * i + 1]);
         }
     }
 
-    kbd_init();
+    i8042_init(i8259[1], i8259[12], 0x60);
     DMA_init(0);
 #ifdef HAS_AUDIO
-    audio_init(pci_enabled ? pci_bus : NULL);
+    audio_init(pci_enabled ? pci_bus : NULL, i8259);
 #endif
 
-    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table);
 
     cmos_init(ram_size, boot_device, bs_table);
 
@@ -701,7 +757,13 @@
     }
 
     if (pci_enabled && acpi_enabled) {
-        piix4_pm_init(pci_bus, piix3_devfn + 3);
+        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
+        i2c_bus *smbus;
+
+        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3);
+        for (i = 0; i < 8; i++) {
+            smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
+        }
     }
     
     if (i440fx_state) {
@@ -731,7 +793,8 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        const char *cpu_model)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
@@ -744,7 +807,8 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        const char *cpu_model)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,

Modified: trunk/src/host/qemu-neo1973/hw/pcf5060x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcf5060x.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcf5060x.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -12,10 +12,8 @@
 #define VERBOSE 1
 
 struct pcf_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
-    void *pic;
-    int irq;
+    i2c_slave i2c;
+    qemu_irq irq;
 
     int firstbyte;
     int charging;
@@ -59,17 +57,14 @@
         uint8_t alm_mon;
         uint8_t alm_year;
     } rtc;
-    struct {
-        gpio_handler_t fn;
-        void *opaque;
-    } gpo_handler[6];
+    qemu_irq gpo_handler[6];
     uint8_t gpo;
     QEMUTimer *onkeylow;
 };
 
-void pcf_reset(struct i2c_slave_s *i2c)
+void pcf_reset(i2c_slave *i2c)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     time_t ti;
     s->charging = 1;
     s->reg = 0x00;
@@ -132,7 +127,7 @@
 
 static inline void pcf_update(struct pcf_s *s)
 {
-    pic_set_irq_new(s->pic, s->irq,
+    qemu_set_irq(s->irq,
                     (s->intr[0] & ~s->intm[0]) ||
                     (s->intr[1] & ~s->intm[1]) ||
                     (s->intr[2] & ~s->intm[2]));
@@ -267,8 +262,8 @@
 static void pcf_gpo_set(struct pcf_s *s, int line, int state, int inv)
 {
     state = (!!state) ^ inv;
-    if (s->gpo_handler[line].fn && ((s->gpo & 1) ^ state))
-        s->gpo_handler[line].fn(line, state, s->gpo_handler[line].opaque);
+    if (s->gpo_handler[line] && ((s->gpo & 1) ^ state))
+        qemu_set_irq(s->gpo_handler[line], state);
     s->gpo &= ~(1 << line);
     s->gpo |= state << line;
 }
@@ -755,33 +750,33 @@
     }
 }
 
-static void pcf_start(void *opaque, int dir)
+static void pcf_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct pcf_s *s = (struct pcf_s *) opaque;
-    s->i2c_dir = dir;
-    s->firstbyte = 1;
+    struct pcf_s *s = (struct pcf_s *) i2c;
+
+    if (event == I2C_START_SEND)
+        s->firstbyte = 1;
 }
 
-static int pcf_tx(void *opaque, uint8_t *data, int len)
+static int pcf_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct pcf_s *s = (struct pcf_s *) opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     /* Interpret register address byte */
-    if (s->firstbyte && len && !s->i2c_dir) {
-        s->reg = *(data ++);
-        len --;
+    if (s->firstbyte) {
+        s->reg = data;
         s->firstbyte = 0;
-    }
+    } else
+        pcf_write(s, s->reg ++, data);
 
-    while (len --) {
-        if (s->i2c_dir)
-            *(data ++) = pcf_read(opaque, s->reg ++);
-        else
-            pcf_write(opaque, s->reg ++, *(data ++));
-    }
-
     return 0;
 }
 
+static int pcf_rx(i2c_slave *i2c)
+{
+    struct pcf_s *s = (struct pcf_s *) i2c;
+    return pcf_read(s, s->reg ++);
+}
+
 static void pcf_onkey1s(void *opaque)
 {
     struct pcf_s *s = (struct pcf_s *) opaque;
@@ -790,14 +785,14 @@
     pcf_update(s);
 }
 
-struct i2c_slave_s *pcf5060x_init(void *pic, int irq, int tsc)
+i2c_slave *pcf5060x_init(i2c_bus *bus, qemu_irq irq, int tsc)
 {
-    struct pcf_s *s = qemu_mallocz(sizeof(struct pcf_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = pcf_tx;
-    s->i2c.start = pcf_start;
+    struct pcf_s *s = (struct pcf_s *)
+            i2c_slave_init(bus, 0, sizeof(struct pcf_s));
+    s->i2c.event = pcf_event;
+    s->i2c.recv = pcf_rx;
+    s->i2c.send = pcf_tx;
 
-    s->pic = pic;
     s->irq = irq;
     s->rtc.hz = qemu_new_timer(rt_clock, pcf_rtc_hz, s);
     s->onkeylow = qemu_new_timer(vm_clock, pcf_onkey1s, s);
@@ -815,19 +810,17 @@
     return &s->i2c;
 }
 
-void pcf_gpo_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque)
+void pcf_gpo_handler_set(i2c_slave *i2c, int line, qemu_irq handler)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (line >= 6 || line < 0)
         cpu_abort(cpu_single_env, "%s: No GPO line %i\n", __FUNCTION__, line);
-    s->gpo_handler[line].fn = handler;
-    s->gpo_handler[line].opaque = opaque;
+    s->gpo_handler[line] = handler;
 }
 
-void pcf_onkey_set(struct i2c_slave_s *i2c, int level)
+void pcf_onkey_set(i2c_slave *i2c, int level)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (level) {
         s->oocs |= 1 << 0;		/* set ONKEY */
         s->intr[0] |= 1 << 0;		/* set ONKEYR */
@@ -840,9 +833,9 @@
     pcf_update(s);
 }
 
-void pcf_exton_set(struct i2c_slave_s *i2c, int level)
+void pcf_exton_set(i2c_slave *i2c, int level)
 {
-    struct pcf_s *s = (struct pcf_s *) i2c->opaque;
+    struct pcf_s *s = (struct pcf_s *) i2c;
     if (level) {
         s->oocs |= 1 << 1;		/* set EXTON */
         s->intr[0] |= 1 << 3;		/* set EXTONR */

Modified: trunk/src/host/qemu-neo1973/hw/pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -33,7 +33,7 @@
     uint32_t config_reg; /* XXX: suppress */
     /* low level pic */
     SetIRQFunc *low_set_irq;
-    void *irq_opaque;
+    qemu_irq *irq_opaque;
     PCIDevice *devices[256];
     PCIDevice *parent_dev;
     PCIBus *next;
@@ -43,13 +43,14 @@
 };
 
 static void pci_update_mappings(PCIDevice *d);
+static void pci_set_irq(void *opaque, int irq_num, int level);
 
 target_phys_addr_t pci_mem_base;
 static int pci_irq_index;
 static PCIBus *first_bus;
 
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *pic, int devfn_min, int nirq)
+                         qemu_irq *pic, int devfn_min, int nirq)
 {
     PCIBus *bus;
     bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
@@ -129,6 +130,7 @@
     pci_dev->config_write = config_write;
     pci_dev->irq_index = pci_irq_index++;
     bus->devices[devfn] = pci_dev;
+    pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4);
     return pci_dev;
 }
 
@@ -433,8 +435,9 @@
 /* generic PCI irq support */
 
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
-void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
+static void pci_set_irq(void *opaque, int irq_num, int level)
 {
+    PCIDevice *pci_dev = (PCIDevice *)opaque;
     PCIBus *bus;
     int change;
     
@@ -466,11 +469,38 @@
 {
     { 0x0100, "SCSI controller"},
     { 0x0101, "IDE controller"},
+    { 0x0102, "Floppy controller"},
+    { 0x0103, "IPI controller"},
+    { 0x0104, "RAID controller"},
+    { 0x0106, "SATA controller"},
+    { 0x0107, "SAS controller"},
+    { 0x0180, "Storage controller"},
     { 0x0200, "Ethernet controller"},
+    { 0x0201, "Token Ring controller"},
+    { 0x0202, "FDDI controller"},
+    { 0x0203, "ATM controller"},
+    { 0x0280, "Network controller"},
     { 0x0300, "VGA controller"},
+    { 0x0301, "XGA controller"},
+    { 0x0302, "3D controller"},
+    { 0x0380, "Display controller"},
+    { 0x0400, "Video controller"},
+    { 0x0401, "Audio controller"},
+    { 0x0402, "Phone"},
+    { 0x0480, "Multimedia controller"},
+    { 0x0500, "RAM controller"},
+    { 0x0501, "Flash controller"},
+    { 0x0580, "Memory controller"},
     { 0x0600, "Host bridge"},
     { 0x0601, "ISA bridge"},
+    { 0x0602, "EISA bridge"},
+    { 0x0603, "MC bridge"},
     { 0x0604, "PCI bridge"},
+    { 0x0605, "PCMCIA bridge"},
+    { 0x0606, "NUBUS bridge"},
+    { 0x0607, "CARDBUS bridge"},
+    { 0x0608, "RACEWAY bridge"},
+    { 0x0680, "Bridge"},
     { 0x0c03, "USB controller"},
     { 0, NULL}
 };
@@ -544,14 +574,20 @@
 }
 
 /* Initialize a PCI NIC.  */
-void pci_nic_init(PCIBus *bus, NICInfo *nd)
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     if (strcmp(nd->model, "ne2k_pci") == 0) {
-        pci_ne2000_init(bus, nd);
+        pci_ne2000_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82551") == 0) {
+        pci_i82551_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82557b") == 0) {
+        pci_i82557b_init(bus, nd, devfn);
+    } else if (strcmp(nd->model, "i82559er") == 0) {
+        pci_i82559er_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "rtl8139") == 0) {
-        pci_rtl8139_init(bus, nd);
+        pci_rtl8139_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "pcnet") == 0) {
-        pci_pcnet_init(bus, nd);
+        pci_pcnet_init(bus, nd, devfn);
     } else {
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);
@@ -587,7 +623,7 @@
     s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
                                          devfn, NULL, pci_bridge_write_config);
     s->dev.config[0x00] = id >> 16;
-    s->dev.config[0x01] = id > 24;
+    s->dev.config[0x01] = id >> 24;
     s->dev.config[0x02] = id; // device_id
     s->dev.config[0x03] = id >> 8;
     s->dev.config[0x04] = 0x06; // command = bus master, pci mem

Modified: trunk/src/host/qemu-neo1973/hw/pckbd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pckbd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -121,6 +121,11 @@
     uint8_t pending;
     void *kbd;
     void *mouse;
+
+    qemu_irq irq_kbd;
+    qemu_irq irq_mouse;
+    target_phys_addr_t base;
+    int it_shift;
 } KBDState;
 
 KBDState kbd_state;
@@ -130,26 +135,26 @@
    incorrect, but it avoids having to simulate exact delays */
 static void kbd_update_irq(KBDState *s)
 {
-    int irq12_level, irq1_level;
+    int irq_kbd_level, irq_mouse_level;
 
-    irq1_level = 0;    
-    irq12_level = 0;    
+    irq_kbd_level = 0;
+    irq_mouse_level = 0;
     s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
     if (s->pending) {
         s->status |= KBD_STAT_OBF;
-        /* kdb data takes priority over aux data.  */
+        /* kbd data takes priority over aux data.  */
         if (s->pending == KBD_PENDING_AUX) {
             s->status |= KBD_STAT_MOUSE_OBF;
             if (s->mode & KBD_MODE_MOUSE_INT)
-                irq12_level = 1;
+                irq_mouse_level = 1;
         } else {
             if ((s->mode & KBD_MODE_KBD_INT) && 
                 !(s->mode & KBD_MODE_DISABLE_KBD))
-                irq1_level = 1;
+                irq_kbd_level = 1;
         }
     }
-    pic_set_irq(1, irq1_level);
-    pic_set_irq(12, irq12_level);
+    qemu_set_irq(s->irq_kbd, irq_kbd_level);
+    qemu_set_irq(s->irq_mouse, irq_mouse_level);
 }
 
 static void kbd_update_kbd_irq(void *opaque, int level)
@@ -353,18 +358,89 @@
     return 0;
 }
 
-void kbd_init(void)
+void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base)
 {
     KBDState *s = &kbd_state;
-    
+
+    s->irq_kbd = kbd_irq;
+    s->irq_mouse = mouse_irq;
+
     kbd_reset(s);
     register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s);
-    register_ioport_read(0x60, 1, 1, kbd_read_data, s);
-    register_ioport_write(0x60, 1, 1, kbd_write_data, s);
-    register_ioport_read(0x64, 1, 1, kbd_read_status, s);
-    register_ioport_write(0x64, 1, 1, kbd_write_command, s);
+    register_ioport_read(io_base, 1, 1, kbd_read_data, s);
+    register_ioport_write(io_base, 1, 1, kbd_write_data, s);
+    register_ioport_read(io_base + 4, 1, 1, kbd_read_status, s);
+    register_ioport_write(io_base + 4, 1, 1, kbd_write_command, s);
 
     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
+#ifdef TARGET_I386
+    vmmouse_init(s->mouse);
+#endif
     qemu_register_reset(kbd_reset, s);
 }
+
+/* Memory mapped interface */
+uint32_t kbd_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    KBDState *s = opaque;
+
+    switch ((addr - s->base) >> s->it_shift) {
+    case 0:
+        return kbd_read_data(s, 0) & 0xff;
+    case 1:
+        return kbd_read_status(s, 0) & 0xff;
+    default:
+        return 0xff;
+    }
+}
+
+void kbd_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    KBDState *s = opaque;
+
+    switch ((addr - s->base) >> s->it_shift) {
+    case 0:
+        kbd_write_data(s, 0, value & 0xff);
+        break;
+    case 1:
+        kbd_write_command(s, 0, value & 0xff);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *kbd_mm_read[] = {
+    &kbd_mm_readb,
+    &kbd_mm_readb,
+    &kbd_mm_readb,
+};
+
+static CPUWriteMemoryFunc *kbd_mm_write[] = {
+    &kbd_mm_writeb,
+    &kbd_mm_writeb,
+    &kbd_mm_writeb,
+};
+
+void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, target_ulong base,
+                   int it_shift)
+{
+    KBDState *s = &kbd_state;
+    int s_io_memory;
+
+    s->irq_kbd = kbd_irq;
+    s->irq_mouse = mouse_irq;
+    s->base = base;
+    s->it_shift = it_shift;
+
+    kbd_reset(s);
+    register_savevm("pckbd", 0, 3, kbd_save, kbd_load, s);
+    s_io_memory = cpu_register_io_memory(0, kbd_mm_read, kbd_mm_write, s);
+    cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
+
+    s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
+    s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
+#ifdef TARGET_I386
+    vmmouse_init(s->mouse);
+#endif
+    qemu_register_reset(kbd_reset, s);
+}

Modified: trunk/src/host/qemu-neo1973/hw/pcnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -69,7 +69,7 @@
     int xmit_pos, recv_pos;
     uint8_t buffer[4096];
     int tx_busy;
-    void (*set_irq_cb)(void *s, int isr);
+    qemu_irq irq;
     void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
                          uint8_t *buf, int len, int do_bswap);
     void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
@@ -77,14 +77,6 @@
     void *dma_opaque;
 };
 
-/* XXX: using bitfields for target memory structures is almost surely
-   not portable, so it should be suppressed ASAP */
-#ifdef __GNUC__
-#define PACKED_FIELD(A) A __attribute__ ((packed))
-#else
-#error FixMe
-#endif
-
 struct qemu_ether_header {
     uint8_t ether_dhost[6];
     uint8_t ether_shost[6];
@@ -183,223 +175,291 @@
 };
 
 struct pcnet_TMD {
-    struct {
-        unsigned tbadr:32;
-    } tmd0;
-    struct {
-        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:7), PACKED_FIELD(bpe:1);
-        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(def:1), PACKED_FIELD(one:1);
-        unsigned PACKED_FIELD(ltint:1), PACKED_FIELD(nofcs:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
-    } tmd1;
-    struct {
-        unsigned PACKED_FIELD(trc:4), PACKED_FIELD(res:12);
-        unsigned PACKED_FIELD(tdr:10), PACKED_FIELD(rtry:1), PACKED_FIELD(lcar:1);
-        unsigned PACKED_FIELD(lcol:1), PACKED_FIELD(exdef:1), PACKED_FIELD(uflo:1), PACKED_FIELD(buff:1);
-    } tmd2;
-    struct {
-        unsigned res:32;
-    } tmd3;    
+    uint32_t tbadr;
+    int16_t length;
+    int16_t status;
+    uint32_t misc;
+    uint32_t res;
 };
 
+#define TMDL_BCNT_MASK  0x0fff
+#define TMDL_BCNT_SH    0
+#define TMDL_ONES_MASK  0xf000
+#define TMDL_ONES_SH    12
+
+#define TMDS_BPE_MASK   0x0080
+#define TMDS_BPE_SH     7
+#define TMDS_ENP_MASK   0x0100
+#define TMDS_ENP_SH     8
+#define TMDS_STP_MASK   0x0200
+#define TMDS_STP_SH     9
+#define TMDS_DEF_MASK   0x0400
+#define TMDS_DEF_SH     10
+#define TMDS_ONE_MASK   0x0800
+#define TMDS_ONE_SH     11
+#define TMDS_LTINT_MASK 0x1000
+#define TMDS_LTINT_SH   12
+#define TMDS_NOFCS_MASK 0x2000
+#define TMDS_NOFCS_SH   13
+#define TMDS_ERR_MASK   0x4000
+#define TMDS_ERR_SH     14
+#define TMDS_OWN_MASK   0x8000
+#define TMDS_OWN_SH     15
+
+#define TMDM_TRC_MASK   0x0000000f
+#define TMDM_TRC_SH     0
+#define TMDM_TDR_MASK   0x03ff0000
+#define TMDM_TDR_SH     16
+#define TMDM_RTRY_MASK  0x04000000
+#define TMDM_RTRY_SH    26
+#define TMDM_LCAR_MASK  0x08000000
+#define TMDM_LCAR_SH    27
+#define TMDM_LCOL_MASK  0x10000000
+#define TMDM_LCOL_SH    28
+#define TMDM_EXDEF_MASK 0x20000000
+#define TMDM_EXDEF_SH   29
+#define TMDM_UFLO_MASK  0x40000000
+#define TMDM_UFLO_SH    30
+#define TMDM_BUFF_MASK  0x80000000
+#define TMDM_BUFF_SH    31
+
 struct pcnet_RMD {
-    struct {
-        unsigned rbadr:32;
-    } rmd0;
-    struct {
-        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:4);
-        unsigned PACKED_FIELD(bam:1), PACKED_FIELD(lafm:1), PACKED_FIELD(pam:1), PACKED_FIELD(bpe:1);
-        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(buff:1), PACKED_FIELD(crc:1);
-        unsigned PACKED_FIELD(oflo:1), PACKED_FIELD(fram:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
-    } rmd1;
-    struct {
-        unsigned PACKED_FIELD(mcnt:12), PACKED_FIELD(zeros:4);
-        unsigned PACKED_FIELD(rpc:8), PACKED_FIELD(rcc:8);
-    } rmd2;    
-    struct {
-        unsigned res:32;
-    } rmd3;    
+    uint32_t rbadr;
+    int16_t buf_length;
+    int16_t status;
+    uint32_t msg_length;
+    uint32_t res;
 };
 
+#define RMDL_BCNT_MASK  0x0fff
+#define RMDL_BCNT_SH    0
+#define RMDL_ONES_MASK  0xf000
+#define RMDL_ONES_SH    12
 
-#define PRINT_TMD(T) printf(    \
-        "TMD0 : TBADR=0x%08x\n" \
+#define RMDS_BAM_MASK   0x0010
+#define RMDS_BAM_SH     4
+#define RMDS_LFAM_MASK  0x0020
+#define RMDS_LFAM_SH    5
+#define RMDS_PAM_MASK   0x0040
+#define RMDS_PAM_SH     6
+#define RMDS_BPE_MASK   0x0080
+#define RMDS_BPE_SH     7
+#define RMDS_ENP_MASK   0x0100
+#define RMDS_ENP_SH     8
+#define RMDS_STP_MASK   0x0200
+#define RMDS_STP_SH     9
+#define RMDS_BUFF_MASK  0x0400
+#define RMDS_BUFF_SH    10
+#define RMDS_CRC_MASK   0x0800
+#define RMDS_CRC_SH     11
+#define RMDS_OFLO_MASK  0x1000
+#define RMDS_OFLO_SH    12
+#define RMDS_FRAM_MASK  0x2000
+#define RMDS_FRAM_SH    13
+#define RMDS_ERR_MASK   0x4000
+#define RMDS_ERR_SH     14
+#define RMDS_OWN_MASK   0x8000
+#define RMDS_OWN_SH     15
+
+#define RMDM_MCNT_MASK  0x00000fff
+#define RMDM_MCNT_SH    0
+#define RMDM_ZEROS_MASK 0x0000f000
+#define RMDM_ZEROS_SH   12
+#define RMDM_RPC_MASK   0x00ff0000
+#define RMDM_RPC_SH     16
+#define RMDM_RCC_MASK   0xff000000
+#define RMDM_RCC_SH     24
+
+#define SET_FIELD(regp, name, field, value)             \
+  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
+             | ((value) << name ## _ ## field ## _SH))
+
+#define GET_FIELD(reg, name, field)                     \
+  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
+
+#define PRINT_TMD(T) printf(                            \
+        "TMD0 : TBADR=0x%08x\n"                         \
         "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
         "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
         "       BPE=%d, BCNT=%d\n"                      \
         "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
         "LCA=%d, RTR=%d,\n"                             \
         "       TDR=%d, TRC=%d\n",                      \
-        (T)->tmd0.tbadr,                                \
-        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
-        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
-        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
-        4096-(T)->tmd1.bcnt,                            \
-        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
-        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
-        (T)->tmd2.tdr, (T)->tmd2.trc)
+        (T)->tbadr,                                     \
+        GET_FIELD((T)->status, TMDS, OWN),              \
+        GET_FIELD((T)->status, TMDS, ERR),              \
+        GET_FIELD((T)->status, TMDS, NOFCS),            \
+        GET_FIELD((T)->status, TMDS, LTINT),            \
+        GET_FIELD((T)->status, TMDS, ONE),              \
+        GET_FIELD((T)->status, TMDS, DEF),              \
+        GET_FIELD((T)->status, TMDS, STP),              \
+        GET_FIELD((T)->status, TMDS, ENP),              \
+        GET_FIELD((T)->status, TMDS, BPE),              \
+        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
+        GET_FIELD((T)->misc, TMDM, BUFF),               \
+        GET_FIELD((T)->misc, TMDM, UFLO),               \
+        GET_FIELD((T)->misc, TMDM, EXDEF),              \
+        GET_FIELD((T)->misc, TMDM, LCOL),               \
+        GET_FIELD((T)->misc, TMDM, LCAR),               \
+        GET_FIELD((T)->misc, TMDM, RTRY),               \
+        GET_FIELD((T)->misc, TMDM, TDR),                \
+        GET_FIELD((T)->misc, TMDM, TRC))
 
-#define PRINT_RMD(R) printf(    \
-        "RMD0 : RBADR=0x%08x\n" \
+#define PRINT_RMD(R) printf(                            \
+        "RMD0 : RBADR=0x%08x\n"                         \
         "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
         "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
-        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
+        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
         "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
-        (R)->rmd0.rbadr,                                \
-        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
-        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
-        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
-        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
-        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
-        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
-        (R)->rmd2.zeros)
+        (R)->rbadr,                                     \
+        GET_FIELD((R)->status, RMDS, OWN),              \
+        GET_FIELD((R)->status, RMDS, ERR),              \
+        GET_FIELD((R)->status, RMDS, FRAM),             \
+        GET_FIELD((R)->status, RMDS, OFLO),             \
+        GET_FIELD((R)->status, RMDS, CRC),              \
+        GET_FIELD((R)->status, RMDS, BUFF),             \
+        GET_FIELD((R)->status, RMDS, STP),              \
+        GET_FIELD((R)->status, RMDS, ENP),              \
+        GET_FIELD((R)->status, RMDS, BPE),              \
+        GET_FIELD((R)->status, RMDS, PAM),              \
+        GET_FIELD((R)->status, RMDS, LFAM),             \
+        GET_FIELD((R)->status, RMDS, BAM),              \
+        GET_FIELD((R)->buf_length, RMDL, ONES),         \
+        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
+        GET_FIELD((R)->msg_length, RMDM, RCC),          \
+        GET_FIELD((R)->msg_length, RMDM, RPC),          \
+        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
+        GET_FIELD((R)->msg_length, RMDM, ZEROS))
 
-static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd1, 
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
                                   target_phys_addr_t addr)
 {
-    uint32_t *tmd = (uint32_t *)tmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t xda[4];
-        s->phys_mem_read(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
-        le16_to_cpus(&xda[0]);
-        le16_to_cpus(&xda[1]);
-        le16_to_cpus(&xda[2]);
-        le16_to_cpus(&xda[3]);
-        tmd[0] = (xda[0]&0xffff) |
-            ((xda[1]&0x00ff) << 16);
-        tmd[1] = (xda[2]&0xffff)|
-            ((xda[1] & 0xff00) << 16);
-        tmd[2] =
-            (xda[3] & 0xffff) << 16;
-        tmd[3] = 0;
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+	} xda;
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
+        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
+        tmd->length = le16_to_cpu(xda.length);
+        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
+        tmd->misc = le16_to_cpu(xda.status) << 16;
+        tmd->res = 0;
     } else {
-        uint32_t xda[4];
-        s->phys_mem_read(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
-        le32_to_cpus(&xda[0]);
-        le32_to_cpus(&xda[1]);
-        le32_to_cpus(&xda[2]);
-        le32_to_cpus(&xda[3]);
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(tmd, xda, sizeof(xda));
-        } else {
-            tmd[0] = xda[2];
-            tmd[1] = xda[1];
-            tmd[2] = xda[0];
-            tmd[3] = xda[3];
+        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
+        le32_to_cpus(&tmd->tbadr);
+        le16_to_cpus(&tmd->length);
+        le16_to_cpus(&tmd->status);
+        le32_to_cpus(&tmd->misc);
+        le32_to_cpus(&tmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = tmd->tbadr;
+            tmd->tbadr = tmd->misc;
+            tmd->misc = tmp;
         }
     }
 }
 
-static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd1,
+static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
                                    target_phys_addr_t addr)
 {
-    const uint32_t *tmd = (const uint32_t *)tmd1;
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t xda[4];
-        xda[0] = tmd[0] & 0xffff;
-        xda[1] = ((tmd[0]>>16)&0x00ff) |
-            ((tmd[1]>>16)&0xff00);
-        xda[2] = tmd[1] & 0xffff;
-        xda[3] = tmd[2] >> 16;
-        cpu_to_le16s(&xda[0]);
-        cpu_to_le16s(&xda[1]);
-        cpu_to_le16s(&xda[2]);
-        cpu_to_le16s(&xda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                (void *)&xda[0], sizeof(xda), 0);
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+        } xda;
+        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
+                                ((tmd->status & 0xff00) << 16));
+        xda.length = cpu_to_le16(tmd->length);
+        xda.status = cpu_to_le16(tmd->misc >> 16);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
     } else {
-        uint32_t xda[4];
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(xda, tmd, sizeof(xda));
-        } else {
-            xda[0] = tmd[2];
-            xda[1] = tmd[1];
-            xda[2] = tmd[0];
-            xda[3] = tmd[3];
+        struct {
+            uint32_t tbadr;
+            int16_t length;
+            int16_t status;
+            uint32_t misc;
+            uint32_t res;
+        } xda;
+        xda.tbadr = cpu_to_le32(tmd->tbadr);
+        xda.length = cpu_to_le16(tmd->length);
+        xda.status = cpu_to_le16(tmd->status);
+        xda.misc = cpu_to_le32(tmd->misc);
+        xda.res = cpu_to_le32(tmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = xda.tbadr;
+            xda.tbadr = xda.misc;
+            xda.misc = tmp;
         }
-        cpu_to_le32s(&xda[0]);
-        cpu_to_le32s(&xda[1]);
-        cpu_to_le32s(&xda[2]);
-        cpu_to_le32s(&xda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                          (void *)&xda[0], sizeof(xda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
     }
 }
 
-static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd1,
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
                                   target_phys_addr_t addr)
 {
-    uint32_t *rmd = (uint32_t *)rmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t rda[4];
-        s->phys_mem_read(s->dma_opaque, addr, 
-                         (void *)&rda[0], sizeof(rda), 0);
-        le16_to_cpus(&rda[0]);
-        le16_to_cpus(&rda[1]);
-        le16_to_cpus(&rda[2]);
-        le16_to_cpus(&rda[3]);
-        rmd[0] = (rda[0]&0xffff)|
-            ((rda[1] & 0x00ff) << 16);
-        rmd[1] = (rda[2]&0xffff)|
-            ((rda[1] & 0xff00) << 16);
-        rmd[2] = rda[3] & 0xffff;
-        rmd[3] = 0;
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t msg_length;
+	} rda;
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
+        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
+        rmd->buf_length = le16_to_cpu(rda.buf_length);
+        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
+        rmd->msg_length = le16_to_cpu(rda.msg_length);
+        rmd->res = 0;
     } else {
-        uint32_t rda[4];
-        s->phys_mem_read(s->dma_opaque, addr, 
-                         (void *)&rda[0], sizeof(rda), 0);
-        le32_to_cpus(&rda[0]);
-        le32_to_cpus(&rda[1]);
-        le32_to_cpus(&rda[2]);
-        le32_to_cpus(&rda[3]);
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(rmd, rda, sizeof(rda));
-        } else {
-            rmd[0] = rda[2];
-            rmd[1] = rda[1];
-            rmd[2] = rda[0];
-            rmd[3] = rda[3];
+        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
+        le32_to_cpus(&rmd->rbadr);
+        le16_to_cpus(&rmd->buf_length);
+        le16_to_cpus(&rmd->status);
+        le32_to_cpus(&rmd->msg_length);
+        le32_to_cpus(&rmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = rmd->rbadr;
+            rmd->rbadr = rmd->msg_length;
+            rmd->msg_length = tmp;
         }
     }
 }
 
-static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd1, 
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
                                    target_phys_addr_t addr)
 {
-    const uint32_t *rmd = (const uint32_t *)rmd1;
-
-    if (!BCR_SWSTYLE(s)) {
-        uint16_t rda[4];
-        rda[0] = rmd[0] & 0xffff;
-        rda[1] = ((rmd[0]>>16)&0xff)|
-            ((rmd[1]>>16)&0xff00);
-        rda[2] = rmd[1] & 0xffff;
-        rda[3] = rmd[2] & 0xffff;
-        cpu_to_le16s(&rda[0]);
-        cpu_to_le16s(&rda[1]);
-        cpu_to_le16s(&rda[2]);
-        cpu_to_le16s(&rda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                (void *)&rda[0], sizeof(rda), 0);
+    if (!BCR_SSIZE32(s)) {
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t msg_length;
+        } rda;
+        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
+                                ((rmd->status & 0xff00) << 16));
+        rda.buf_length = cpu_to_le16(rmd->buf_length);
+        rda.msg_length = cpu_to_le16(rmd->msg_length);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
     } else {
-        uint32_t rda[4];
-        if (BCR_SWSTYLE(s) != 3) {
-            memcpy(rda, rmd, sizeof(rda));
-        } else {
-            rda[0] = rmd[2];
-            rda[1] = rmd[1];
-            rda[2] = rmd[0];
-            rda[3] = rmd[3];
+        struct {
+            uint32_t rbadr;
+            int16_t buf_length;
+            int16_t status;
+            uint32_t msg_length;
+            uint32_t res;
+        } rda;
+        rda.rbadr = cpu_to_le32(rmd->rbadr);
+        rda.buf_length = cpu_to_le16(rmd->buf_length);
+        rda.status = cpu_to_le16(rmd->status);
+        rda.msg_length = cpu_to_le32(rmd->msg_length);
+        rda.res = cpu_to_le32(rmd->res);
+        if (BCR_SWSTYLE(s) == 3) {
+            uint32_t tmp = rda.rbadr;
+            rda.rbadr = rda.msg_length;
+            rda.msg_length = tmp;
         }
-        cpu_to_le32s(&rda[0]);
-        cpu_to_le32s(&rda[1]);
-        cpu_to_le32s(&rda[2]);
-        cpu_to_le32s(&rda[3]);
-        s->phys_mem_write(s->dma_opaque, addr,
-                          (void *)&rda[0], sizeof(rda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
     }
 }
 
@@ -417,14 +477,14 @@
 #define CHECK_RMD(ADDR,RES) do {                \
     struct pcnet_RMD rmd;                       \
     RMDLOAD(&rmd,(ADDR));                       \
-    (RES) |= (rmd.rmd1.ones != 15)              \
-          || (rmd.rmd2.zeros != 0);             \
+    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
+          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
 } while (0)
 
 #define CHECK_TMD(ADDR,RES) do {                \
     struct pcnet_TMD tmd;                       \
     TMDLOAD(&tmd,(ADDR));                       \
-    (RES) |= (tmd.tmd1.ones != 15);             \
+    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
 } while (0)
 
 #else
@@ -434,8 +494,8 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&rda[0], sizeof(rda), 0);  \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[2] & 0xf000)!=0xf000; \
             (RES) |= (rda[3] & 0xf000)!=0x0000; \
         } while (0);                            \
@@ -444,7 +504,7 @@
     case 0x02:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
                 (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
             (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
@@ -453,7 +513,7 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
                 (void *)&rda[0], sizeof(rda), 0); \
             (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
@@ -467,9 +527,9 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t xda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&xda[0], sizeof(xda), 0);  \
-            (RES) |= (xda[2] & 0xf000)!=0xf000;\
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&xda[0], sizeof(xda), 0); \
+            (RES) |= (xda[2] & 0xf000)!=0xf000; \
         } while (0);                            \
         break;                                  \
     case 0x01:                                  \
@@ -477,8 +537,8 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t xda[4];                    \
-            s->phys_mem_read(s->dma_opaque, (ADDR),    \
-                (void *)&xda[0], sizeof(xda), 0);  \
+            s->phys_mem_read(s->dma_opaque, (ADDR), \
+                (void *)&xda[0], sizeof(xda), 0); \
             (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
         } while (0);                            \
         break;                                  \
@@ -488,15 +548,15 @@
 #endif
 
 #define PRINT_PKTHDR(BUF) do {                  \
-    struct qemu_ether_header *hdr = (void *)(BUF);   \
-    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
-           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
-           "type=0x%04x\n",                          \
+    struct qemu_ether_header *hdr = (void *)(BUF); \
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
+           "type=0x%04x\n",                     \
            hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
            hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
            hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
            hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
-           be16_to_cpu(hdr->ether_type));                     \
+           be16_to_cpu(hdr->ether_type));       \
 } while (0)
 
 #define MULTICAST_FILTER_LEN 8
@@ -763,14 +823,14 @@
         printf("pcnet: INTA=%d\n", isr);
 #endif
     }
-    s->set_irq_cb(s, isr);
+    qemu_set_irq(s->irq, isr);
     s->isr = isr;
 }
 
 static void pcnet_init(PCNetState *s)
 {
     int rlen, tlen;
-    uint16_t *padr, *ladrf, mode;
+    uint16_t padr[3], ladrf[4], mode;
     uint32_t rdra, tdra;
 
 #ifdef PCNET_DEBUG
@@ -781,22 +841,30 @@
         struct pcnet_initblk32 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
                 (uint8_t *)&initblk, sizeof(initblk), 0);
-        mode = initblk.mode;
+        mode = le16_to_cpu(initblk.mode);
         rlen = initblk.rlen >> 4;
         tlen = initblk.tlen >> 4;
-        ladrf = initblk.ladrf;
-        padr = initblk.padr;
+	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
+	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
+	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
+	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
+	padr[0] = le16_to_cpu(initblk.padr[0]);
+	padr[1] = le16_to_cpu(initblk.padr[1]);
+	padr[2] = le16_to_cpu(initblk.padr[2]);
         rdra = le32_to_cpu(initblk.rdra);
         tdra = le32_to_cpu(initblk.tdra);
-        s->rdra = PHYSADDR(s,initblk.rdra);
-        s->tdra = PHYSADDR(s,initblk.tdra);
     } else {
         struct pcnet_initblk16 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
                 (uint8_t *)&initblk, sizeof(initblk), 0);
-        mode = initblk.mode;
-        ladrf = initblk.ladrf;
-        padr = initblk.padr;
+        mode = le16_to_cpu(initblk.mode);
+	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
+	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
+	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
+	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
+	padr[0] = le16_to_cpu(initblk.padr[0]);
+	padr[1] = le16_to_cpu(initblk.padr[1]);
+	padr[2] = le16_to_cpu(initblk.padr[2]);
         rdra = le32_to_cpu(initblk.rdra);
         tdra = le32_to_cpu(initblk.tdra);
         rlen = rdra >> 29;
@@ -804,22 +872,22 @@
         rdra &= 0x00ffffff;
         tdra &= 0x00ffffff;
     }
-    
+
 #if defined(PCNET_DEBUG)
-    printf("rlen=%d tlen=%d\n",
-           rlen, tlen);
+    printf("rlen=%d tlen=%d\n", rlen, tlen);
 #endif
+
     CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
     CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
     s->csr[ 6] = (tlen << 12) | (rlen << 8);
-    s->csr[15] = le16_to_cpu(mode);
-    s->csr[ 8] = le16_to_cpu(ladrf[0]);
-    s->csr[ 9] = le16_to_cpu(ladrf[1]);
-    s->csr[10] = le16_to_cpu(ladrf[2]);
-    s->csr[11] = le16_to_cpu(ladrf[3]);
-    s->csr[12] = le16_to_cpu(padr[0]);
-    s->csr[13] = le16_to_cpu(padr[1]);
-    s->csr[14] = le16_to_cpu(padr[2]);
+    s->csr[15] = mode;
+    s->csr[ 8] = ladrf[0];
+    s->csr[ 9] = ladrf[1];
+    s->csr[10] = ladrf[2];
+    s->csr[11] = ladrf[3];
+    s->csr[12] = padr[0];
+    s->csr[13] = padr[1];
+    s->csr[14] = padr[2];
     s->rdra = PHYSADDR(s, rdra);
     s->tdra = PHYSADDR(s, tdra);
 
@@ -914,12 +982,12 @@
     if (CSR_CRDA(s)) {
         struct pcnet_RMD rmd;
         RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
-        CSR_CRBC(s) = rmd.rmd1.bcnt;
-        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
+        CSR_CRST(s) = rmd.status;
 #ifdef PCNET_DEBUG_RMD_X
-        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
+        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
                 PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
-                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
+                rmd.buf_length, rmd.status, rmd.msg_length);
         PRINT_RMD(&rmd);
 #endif
     } else {
@@ -929,8 +997,8 @@
     if (CSR_NRDA(s)) {
         struct pcnet_RMD rmd;
         RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
-        CSR_NRBC(s) = rmd.rmd1.bcnt;
-        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
+        CSR_NRST(s) = rmd.status;
     } else {
         CSR_NRBC(s) = CSR_NRST(s) = 0;
     }
@@ -943,7 +1011,7 @@
     if (s->tdra) {
         target_phys_addr_t cxda = s->tdra + 
             (CSR_XMTRL(s) - CSR_XMTRC(s)) *
-            (BCR_SWSTYLE(s) ? 16 : 8 );
+            (BCR_SWSTYLE(s) ? 16 : 8);
         int bad = 0;
         CHECK_TMD(PHYSADDR(s, cxda),bad);
         if (!bad) {
@@ -955,8 +1023,7 @@
             }
             s->csr[34] = cxda & 0xffff;
             s->csr[35] = cxda >> 16;
-#ifdef PCNET_DEBUG
-        } else {
+#ifdef PCNET_DEBUG_X
             printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
 #endif
         }
@@ -967,8 +1034,8 @@
 
         TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
 
-        CSR_CXBC(s) = tmd.tmd1.bcnt;
-        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
+        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
+        CSR_CXST(s) = tmd.status;
     } else {
         CSR_CXBC(s) = CSR_CXST(s) = 0;
     }
@@ -1029,7 +1096,7 @@
                     (CSR_RCVRL(s) - rcvrc) *
                     (BCR_SWSTYLE(s) ? 16 : 8 );
                 RMDLOAD(&rmd, PHYSADDR(s,nrda));                  
-                if (rmd.rmd1.own) {                
+                if (GET_FIELD(rmd.status, RMDS, OWN)) {
 #ifdef PCNET_DEBUG_RMD
                     printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
                                 rcvrc, CSR_RCVRC(s));
@@ -1086,14 +1153,15 @@
 
             RMDLOAD(&rmd, PHYSADDR(s,crda));
             /*if (!CSR_LAPPEN(s))*/
-                rmd.rmd1.stp = 1;
+                SET_FIELD(&rmd.status, RMDS, STP, 1);
 
 #define PCNET_RECV_STORE() do {                                 \
-    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
-    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
-    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s));  \
+    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),size); \
+    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr);          \
+    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
     src += count; size -= count;                                \
-    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
+    SET_FIELD(&rmd.msg_length, RMDM, MCNT, count);              \
+    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
     RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
     pktcount++;                                                 \
 } while (0)
@@ -1102,12 +1170,12 @@
             if ((size > 0) && CSR_NRDA(s)) {
                 target_phys_addr_t nrda = CSR_NRDA(s);
                 RMDLOAD(&rmd, PHYSADDR(s,nrda));
-                if (rmd.rmd1.own) {
+                if (GET_FIELD(rmd.status, RMDS, OWN)) {
                     crda = nrda;
                     PCNET_RECV_STORE();
                     if ((size > 0) && (nrda=CSR_NNRD(s))) {
                         RMDLOAD(&rmd, PHYSADDR(s,nrda));
-                        if (rmd.rmd1.own) {
+                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
                             crda = nrda;
                             PCNET_RECV_STORE();
                         }
@@ -1119,14 +1187,14 @@
 
             RMDLOAD(&rmd, PHYSADDR(s,crda));
             if (size == 0) {
-                rmd.rmd1.enp = 1;
-                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
-                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
-                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
+                SET_FIELD(&rmd.status, RMDS, ENP, 1);
+                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
+                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
+                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
             } else {
-                rmd.rmd1.oflo = 1;
-                rmd.rmd1.buff = 1;
-                rmd.rmd1.err = 1;
+                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
+                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
+                SET_FIELD(&rmd.status, RMDS, ERR, 1);
             }
             RMDSTORE(&rmd, PHYSADDR(s,crda));
             s->csr[0] |= 0x0400;
@@ -1172,30 +1240,30 @@
     if (pcnet_tdte_poll(s)) {
         struct pcnet_TMD tmd;
 
-        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
 
 #ifdef PCNET_DEBUG_TMD
         printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
         PRINT_TMD(&tmd);
 #endif
-        if (tmd.tmd1.stp) {
-            s->xmit_pos = 0;                
-            if (!tmd.tmd1.enp) {
-                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
-                                 s->buffer, 4096 - tmd.tmd1.bcnt, 
-                                 CSR_BSWP(s));
-                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
-            } 
+        if (GET_FIELD(tmd.status, TMDS, STP)) {
+            s->xmit_pos = 0;
+            if (!GET_FIELD(tmd.status, TMDS, ENP)) {
+                int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+                                 s->buffer, bcnt, CSR_BSWP(s));
+                s->xmit_pos += bcnt;
+            }
             xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
         }
-        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
-            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
-                             s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt, 
-                             CSR_BSWP(s));
-            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+        if (GET_FIELD(tmd.status, TMDS, ENP) && (s->xmit_pos >= 0)) {
+            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
+            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
+                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+            s->xmit_pos += bcnt;
 #ifdef PCNET_DEBUG
             printf("pcnet_transmit size=%d\n", s->xmit_pos);
-#endif            
+#endif
             if (CSR_LOOP(s))
                 pcnet_receive(s, s->buffer, s->xmit_pos);
             else
@@ -1206,9 +1274,9 @@
             s->xmit_pos = -1;
         }
 
-        tmd.tmd1.own = 0;
+        SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
-        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
+        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
             s->csr[0] |= 0x0200;    /* set TINT */
 
         if (CSR_XMTRC(s)<=1)
@@ -1221,9 +1289,11 @@
     } else 
     if (s->xmit_pos >= 0) {
         struct pcnet_TMD tmd;
-        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));                
-        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
-        tmd.tmd1.own = 0;
+        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
+        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
+        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
+        SET_FIELD(&tmd.status, TMDS, ERR, 1);
+        SET_FIELD(&tmd.status, TMDS, OWN, 0);
         TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
         s->csr[0] |= 0x0200;    /* set TINT */
         if (!CSR_DXSUFLO(s)) {
@@ -1870,13 +1940,6 @@
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
 }
 
-static void pcnet_pci_set_irq_cb(void *opaque, int isr)
-{
-    PCNetState *s = opaque;
-
-    pci_set_irq(&s->dev, 0, isr);
-}
-
 static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
                                       uint8_t *buf, int len, int do_bswap)
 {
@@ -1889,7 +1952,7 @@
     cpu_physical_memory_read(addr, buf, len);
 }
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
+void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCNetState *d;
     uint8_t *pci_conf;
@@ -1900,7 +1963,7 @@
 #endif
 
     d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
-                                          -1, NULL, NULL);
+                                          devfn, NULL, NULL);
                                           
     pci_conf = d->dev.config;
     
@@ -1931,7 +1994,7 @@
     pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
                            PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
                            
-    d->set_irq_cb = pcnet_pci_set_irq_cb;
+    d->irq = d->dev.irq[0];
     d->phys_mem_read = pci_physical_memory_read;
     d->phys_mem_write = pci_physical_memory_write;
     d->pci_dev = &d->dev;
@@ -1955,15 +2018,8 @@
     (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
 };
 
-static void pcnet_sparc_set_irq_cb(void *opaque, int isr)
+void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque, qemu_irq irq)
 {
-    PCNetState *s = opaque;
-
-    ledma_set_irq(s->dma_opaque, isr);
-}
-
-void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque)
-{
     PCNetState *d;
     int lance_io_memory;
 
@@ -1977,7 +2033,7 @@
     d->dma_opaque = dma_opaque;
     cpu_register_physical_memory(leaddr, 4, lance_io_memory);
 
-    d->set_irq_cb = pcnet_sparc_set_irq_cb;
+    d->irq = irq;
     d->phys_mem_read = ledma_memory_read;
     d->phys_mem_write = ledma_memory_write;
 

Modified: trunk/src/host/qemu-neo1973/hw/pcspk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcspk.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pcspk.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -92,7 +92,7 @@
     }
 }
 
-int pcspk_audio_init(AudioState *audio)
+int pcspk_audio_init(AudioState *audio, qemu_irq *pic)
 {
     PCSpkState *s = &pcspk_state;
     audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};

Modified: trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pflash_cfi02.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -91,7 +91,7 @@
     uint32_t ret;
     uint8_t *p;
 
-    DPRINTF("%s: offset %08x\n", __func__, offset);
+    DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset);
     ret = -1;
     offset -= pfl->base;
     boff = offset & 0xFF;
@@ -161,7 +161,7 @@
         default:
             goto flash_read;
         }
-        DPRINTF("%s: ID %d %x\n", __func__, boff, ret);
+        DPRINTF("%s: ID " TARGET_FMT_ld " %x\n", __func__, boff, ret);
         break;
     case 0xA0:
     case 0x10:
@@ -208,18 +208,23 @@
 
     /* WARNING: when the memory area is in ROMD mode, the offset is a
        ram offset, not a physical address */
-    if (pfl->wcycle == 0)
-        offset -= (target_ulong)(long)pfl->storage;
-    else
-        offset -= pfl->base;
-        
     cmd = value;
-    DPRINTF("%s: offset %08x %08x %d\n", __func__, offset, value, width);
     if (pfl->cmd != 0xA0 && cmd == 0xF0) {
+#if 0
         DPRINTF("%s: flash reset asked (%02x %02x)\n",
                 __func__, pfl->cmd, cmd);
+#endif
         goto reset_flash;
     }
+    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d %d\n", __func__,
+            offset, value, width, pfl->wcycle);
+    if (pfl->wcycle == 0)
+        offset -= (target_ulong)(long)pfl->storage;
+    else
+        offset -= pfl->base;
+        
+    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
+            offset, value, width);
     /* Set the device in I/O access mode */
     cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
     boff = offset & (pfl->sector_len - 1);
@@ -239,7 +244,7 @@
             return;
         }
         if (boff != 0x555 || cmd != 0xAA) {
-            DPRINTF("%s: unlock0 failed %04x %02x %04x\n",
+            DPRINTF("%s: unlock0 failed " TARGET_FMT_lx " %02x %04x\n",
                     __func__, boff, cmd, 0x555);
             goto reset_flash;
         }
@@ -249,7 +254,8 @@
         /* We started an unlock sequence */
     check_unlock1:
         if (boff != 0x2AA || cmd != 0x55) {
-            DPRINTF("%s: unlock1 failed %04x %02x\n", __func__, boff, cmd);
+            DPRINTF("%s: unlock1 failed " TARGET_FMT_lx " %02x\n", __func__,
+                    boff, cmd);
             goto reset_flash;
         }
         DPRINTF("%s: unlock sequence done\n", __func__);
@@ -257,7 +263,8 @@
     case 2:
         /* We finished an unlock sequence */
         if (!pfl->bypass && boff != 0x555) {
-            DPRINTF("%s: command failed %04x %02x\n", __func__, boff, cmd);
+            DPRINTF("%s: command failed " TARGET_FMT_lx " %02x\n", __func__,
+                    boff, cmd);
             goto reset_flash;
         }
         switch (cmd) {
@@ -281,7 +288,7 @@
             /* We need another unlock sequence */
             goto check_unlock0;
         case 0xA0:
-            DPRINTF("%s: write data offset %08x %08x %d\n",
+            DPRINTF("%s: write data offset " TARGET_FMT_lx " %08x %d\n",
                     __func__, offset, value, width);
             p = pfl->storage;
             switch (width) {
@@ -352,7 +359,7 @@
         switch (cmd) {
         case 0x10:
             if (boff != 0x555) {
-                DPRINTF("%s: chip erase: invalid address %04x\n",
+                DPRINTF("%s: chip erase: invalid address " TARGET_FMT_lx "\n",
                         __func__, offset);
                 goto reset_flash;
             }
@@ -369,7 +376,8 @@
             /* Sector erase */
             p = pfl->storage;
             offset &= ~(pfl->sector_len - 1);
-            DPRINTF("%s: start sector erase at %08x\n", __func__, offset);
+            DPRINTF("%s: start sector erase at " TARGET_FMT_lx "\n", __func__,
+                    offset);
             memset(p + offset, 0xFF, pfl->sector_len);
             pflash_update(pfl, offset, pfl->sector_len);
             pfl->status = 0x00;
@@ -412,10 +420,8 @@
 
     /* Reset flash */
  reset_flash:
-    if (pfl->wcycle != 0) {
-        cpu_register_physical_memory(pfl->base, pfl->total_len,
-                                     pfl->off | IO_MEM_ROMD | pfl->fl_mem);
-    }
+    cpu_register_physical_memory(pfl->base, pfl->total_len,
+                                 pfl->off | IO_MEM_ROMD | pfl->fl_mem);
     pfl->bypass = 0;
     pfl->wcycle = 0;
     pfl->cmd = 0;
@@ -526,14 +532,17 @@
 
     total_len = sector_len * nb_blocs;
     /* XXX: to be fixed */
+#if 0
     if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
         total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
         return NULL;
+#endif
     pfl = qemu_mallocz(sizeof(pflash_t));
     if (pfl == NULL)
         return NULL;
     pfl->storage = phys_ram_base + off;
-    pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, pfl);
+    pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops,
+                                         pfl);
     pfl->off = off;
     cpu_register_physical_memory(base, total_len,
                                  off | pfl->fl_mem | IO_MEM_ROMD);
@@ -609,7 +618,9 @@
     pfl->cfi_table[0x28] = 0x02;
     pfl->cfi_table[0x29] = 0x00;
     /* Max number of bytes in multi-bytes write */
-    pfl->cfi_table[0x2A] = 0x05;
+    /* XXX: disable buffered write as it's not supported */
+    //    pfl->cfi_table[0x2A] = 0x05;
+    pfl->cfi_table[0x2A] = 0x00;
     pfl->cfi_table[0x2B] = 0x00;
     /* Number of erase block regions (uniform) */
     pfl->cfi_table[0x2C] = 0x01;

Modified: trunk/src/host/qemu-neo1973/hw/piix_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/piix_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -40,7 +40,7 @@
     return s->config_reg;
 }
 
-static void piix3_set_irq(void *pic, int irq_num, int level);
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level);
 
 /* return the global irq number corresponding to a given device irq
    pin. We could also use the bus number to have a more precise
@@ -155,14 +155,14 @@
     return 0;
 }
 
-PCIBus *i440fx_init(PCIDevice **pi440fx_state)
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
 {
     PCIBus *b;
     PCIDevice *d;
     I440FXState *s;
 
     s = qemu_mallocz(sizeof(I440FXState));
-    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, NULL, 0, 4);
+    b = pci_register_bus(piix3_set_irq, pci_slot_get_pirq, pic, 0, 4);
     s->bus = b;
 
     register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
@@ -196,14 +196,15 @@
 
 /* PIIX3 PCI to ISA bridge */
 
-static PCIDevice *piix3_dev;
+PCIDevice *piix3_dev;
+PCIDevice *piix4_dev;
 
 /* just used for simpler irq handling. */
 #define PCI_IRQ_WORDS   ((PCI_DEVICES_MAX + 31) / 32)
 
 static int pci_irq_levels[4];
 
-static void piix3_set_irq(void *pic, int irq_num, int level)
+static void piix3_set_irq(qemu_irq *pic, int irq_num, int level)
 {
     int i, pic_irq, pic_level;
 
@@ -220,7 +221,7 @@
             if (pic_irq == piix3_dev->config[0x60 + i])
                 pic_level |= pci_irq_levels[i];
         }
-        pic_set_irq(pic_irq, pic_level);
+        qemu_set_irq(pic[pic_irq], pic_level);
     }
 }
 
@@ -245,6 +246,42 @@
     pci_conf[0x80] = 0x00;
     pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
+    pci_conf[0xa2] = 0x00;
+    pci_conf[0xa3] = 0x00;
+    pci_conf[0xa4] = 0x00;
+    pci_conf[0xa5] = 0x00;
+    pci_conf[0xa6] = 0x00;
+    pci_conf[0xa7] = 0x00;
+    pci_conf[0xa8] = 0x0f;
+    pci_conf[0xaa] = 0x00;
+    pci_conf[0xab] = 0x00;
+    pci_conf[0xac] = 0x00;
+    pci_conf[0xae] = 0x00;
+}
+
+static void piix4_reset(PCIDevice *d)
+{
+    uint8_t *pci_conf = d->config;
+
+    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x05] = 0x00;
+    pci_conf[0x06] = 0x00;
+    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x4c] = 0x4d;
+    pci_conf[0x4e] = 0x03;
+    pci_conf[0x4f] = 0x00;
+    pci_conf[0x60] = 0x0a; // PCI A -> IRQ 10
+    pci_conf[0x61] = 0x0a; // PCI B -> IRQ 10
+    pci_conf[0x62] = 0x0b; // PCI C -> IRQ 11
+    pci_conf[0x63] = 0x0b; // PCI D -> IRQ 11
+    pci_conf[0x69] = 0x02;
+    pci_conf[0x70] = 0x80;
+    pci_conf[0x76] = 0x0c;
+    pci_conf[0x77] = 0x0c;
+    pci_conf[0x78] = 0x02;
+    pci_conf[0x79] = 0x00;
+    pci_conf[0x80] = 0x00;
+    pci_conf[0x82] = 0x00;
     pci_conf[0xa0] = 0x08;
     pci_conf[0xa2] = 0x00;
     pci_conf[0xa3] = 0x00;
@@ -273,13 +310,38 @@
     return pci_device_load(d, f);
 }
 
-int piix3_init(PCIBus *bus)
+int piix_init(PCIBus *bus, int devfn)
 {
     PCIDevice *d;
     uint8_t *pci_conf;
 
+    d = pci_register_device(bus, "PIIX", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX", 0, 2, piix_save, piix_load, d);
+
+    piix3_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x2E; // 82371FB PIIX PCI-to-ISA bridge
+    pci_conf[0x03] = 0x12;
+    pci_conf[0x08] = 0x02; // Step A1
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix3_reset(d);
+    return d->devfn;
+}
+
+int piix3_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
     d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-                                    -1, NULL, NULL);
+                                    devfn, NULL, NULL);
     register_savevm("PIIX3", 0, 2, piix_save, piix_load, d);
 
     piix3_dev = d;
@@ -296,3 +358,27 @@
     piix3_reset(d);
     return d->devfn;
 }
+
+int piix4_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *d;
+    uint8_t *pci_conf;
+
+    d = pci_register_device(bus, "PIIX4", sizeof(PCIDevice),
+                                    devfn, NULL, NULL);
+    register_savevm("PIIX4", 0, 2, piix_save, piix_load, d);
+
+    piix4_dev = d;
+    pci_conf = d->config;
+
+    pci_conf[0x00] = 0x86; // Intel
+    pci_conf[0x01] = 0x80;
+    pci_conf[0x02] = 0x10; // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
+    pci_conf[0x03] = 0x71;
+    pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+    pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+    pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+    piix4_reset(d);
+    return d->devfn;
+}

Modified: trunk/src/host/qemu-neo1973/hw/pl011.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl011.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl011.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -27,8 +27,7 @@
     int read_count;
     int read_trigger;
     CharDriverState *chr;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } pl011_state;
 
 #define PL011_INT_TX 0x20
@@ -47,7 +46,7 @@
     uint32_t flags;
     
     flags = s->int_level & s->int_enabled;
-    pic_set_irq_new(s->pic, s->irq, flags != 0);
+    qemu_set_irq(s->irq, flags != 0);
 }
 
 static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
@@ -224,7 +223,7 @@
    pl011_write
 };
 
-void pl011_init(uint32_t base, void *pic, int irq,
+void pl011_init(uint32_t base, qemu_irq irq,
                 CharDriverState *chr)
 {
     int iomemtype;
@@ -235,7 +234,6 @@
                                        pl011_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->chr = chr;
     s->read_trigger = 1;
@@ -243,8 +241,8 @@
     s->cr = 0x300;
     s->flags = 0x90;
     if (chr){ 
-        qemu_chr_add_read_handler(chr, pl011_can_recieve, pl011_recieve, s);
-        qemu_chr_add_event_handler(chr, pl011_event);
+        qemu_chr_add_handlers(chr, pl011_can_recieve, pl011_recieve,
+                              pl011_event, s);
     }
     /* ??? Save/restore.  */
 }

Modified: trunk/src/host/qemu-neo1973/hw/pl050.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl050.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl050.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * Arm PrimeCell PL050 Keyboard / Mouse Interface
  *
- * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL.
@@ -15,12 +15,19 @@
     uint32_t cr;
     uint32_t clk;
     uint32_t last;
-    void *pic;
     int pending;
-    int irq;
+    qemu_irq irq;
     int is_mouse;
 } pl050_state;
 
+#define PL050_TXEMPTY         (1 << 6)
+#define PL050_TXBUSY          (1 << 5)
+#define PL050_RXFULL          (1 << 4)
+#define PL050_RXBUSY          (1 << 3)
+#define PL050_RXPARITY        (1 << 2)
+#define PL050_KMIC            (1 << 1)
+#define PL050_KMID            (1 << 0)
+
 static const unsigned char pl050_id[] =
 { 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
 
@@ -32,7 +39,7 @@
     s->pending = level;
     raise = (s->pending && (s->cr & 0x10) != 0)
             || (s->cr & 0x08) != 0;
-    pic_set_irq_new(s->pic, s->irq, raise);
+    qemu_set_irq(s->irq, raise);
 }
 
 static uint32_t pl050_read(void *opaque, target_phys_addr_t offset)
@@ -46,11 +53,22 @@
     case 0: /* KMICR */
         return s->cr;
     case 1: /* KMISTAT */
-        /* KMIC and KMID bits not implemented.  */
-        if (s->pending) {
-            return 0x10;
-        } else {
-            return 0;
+        {
+            uint8_t val;
+            uint32_t stat;
+
+            val = s->last;
+            val = val ^ (val >> 4);
+            val = val ^ (val >> 2);
+            val = (val ^ (val >> 1)) & 1;
+
+            stat = PL050_TXEMPTY;
+            if (val)
+                stat |= PL050_RXPARITY;
+            if (s->pending)
+                stat |= PL050_RXFULL;
+
+            return stat;
         }
     case 2: /* KMIDATA */
         if (s->pending)
@@ -105,7 +123,7 @@
    pl050_write
 };
 
-void pl050_init(uint32_t base, void *pic, int irq, int is_mouse)
+void pl050_init(uint32_t base, qemu_irq irq, int is_mouse)
 {
     int iomemtype;
     pl050_state *s;
@@ -115,7 +133,6 @@
                                        pl050_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->is_mouse = is_mouse;
     if (is_mouse)

Modified: trunk/src/host/qemu-neo1973/hw/pl080.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl080.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl080.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -49,8 +49,7 @@
     int nchannels;
     /* Flag to avoid recursive DMA invocations.  */
     int running;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 } pl080_state;
 
 static const unsigned char pl080_id[] =
@@ -63,9 +62,9 @@
 {
     if ((s->tc_int & s->tc_mask)
             || (s->err_int & s->err_mask))
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_raise(s->irq);
     else
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_lower(s->irq);
 }
 
 static void pl080_run(pl080_state *s)
@@ -325,7 +324,7 @@
 
 /* The PL080 and PL081 are the same except for the number of channels
    they implement (8 and 2 respectively).  */
-void *pl080_init(uint32_t base, void *pic, int irq, int nchannels)
+void *pl080_init(uint32_t base, qemu_irq irq, int nchannels)
 {
     int iomemtype;
     pl080_state *s;
@@ -335,7 +334,6 @@
                                        pl080_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->nchannels = nchannels;
     /* ??? Save/restore.  */

Modified: trunk/src/host/qemu-neo1973/hw/pl110.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl110.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl110.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -29,7 +29,6 @@
     DisplayState *ds;
     /* The Versatile/PB uses a slightly modified PL110 controller.  */
     int versatile;
-    void *pic;
     uint32_t timing[4];
     uint32_t cr;
     uint32_t upbase;
@@ -42,7 +41,7 @@
     int invalidate;
     uint32_t pallette[256];
     uint32_t raw_pallette[128];
-    int irq;
+    qemu_irq irq;
 } pl110_state;
 
 static const unsigned char pl110_id[] =
@@ -399,7 +398,7 @@
    pl110_write
 };
 
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq,
+void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq,
                  int versatile)
 {
     pl110_state *s;
@@ -412,7 +411,6 @@
     s->base = base;
     s->ds = ds;
     s->versatile = versatile;
-    s->pic = pic;
     s->irq = irq;
     graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
                          NULL, s);

Added: trunk/src/host/qemu-neo1973/hw/pl181.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl181.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl181.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,443 @@
+/* 
+ * Arm PrimeCell PL181 MultiMedia Card Interface
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "vl.h"
+#include "sd.h"
+
+//#define DEBUG_PL181 1
+
+#ifdef DEBUG_PL181
+#define DPRINTF(fmt, args...) \
+do { printf("pl181: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define PL181_FIFO_LEN 16
+
+typedef struct {
+    SDState *card;
+    uint32_t base;
+    uint32_t clock;
+    uint32_t power;
+    uint32_t cmdarg;
+    uint32_t cmd;
+    uint32_t datatimer;
+    uint32_t datalength;
+    uint32_t respcmd;
+    uint32_t response[4];
+    uint32_t datactrl;
+    uint32_t datacnt;
+    uint32_t status;
+    uint32_t mask[2];
+    uint32_t fifocnt;
+    int fifo_pos;
+    int fifo_len;
+    uint32_t fifo[PL181_FIFO_LEN];
+    qemu_irq irq[2];
+} pl181_state;
+
+#define PL181_CMD_INDEX     0x3f
+#define PL181_CMD_RESPONSE  (1 << 6)
+#define PL181_CMD_LONGRESP  (1 << 7)
+#define PL181_CMD_INTERRUPT (1 << 8)
+#define PL181_CMD_PENDING   (1 << 9)
+#define PL181_CMD_ENABLE    (1 << 10)
+
+#define PL181_DATA_ENABLE             (1 << 0)
+#define PL181_DATA_DIRECTION          (1 << 1)
+#define PL181_DATA_MODE               (1 << 2)
+#define PL181_DATA_DMAENABLE          (1 << 3)
+
+#define PL181_STATUS_CMDCRCFAIL       (1 << 0)
+#define PL181_STATUS_DATACRCFAIL      (1 << 1)
+#define PL181_STATUS_CMDTIMEOUT       (1 << 2)
+#define PL181_STATUS_DATATIMEOUT      (1 << 3)
+#define PL181_STATUS_TXUNDERRUN       (1 << 4)
+#define PL181_STATUS_RXOVERRUN        (1 << 5)
+#define PL181_STATUS_CMDRESPEND       (1 << 6)
+#define PL181_STATUS_CMDSENT          (1 << 7)
+#define PL181_STATUS_DATAEND          (1 << 8)
+#define PL181_STATUS_DATABLOCKEND     (1 << 10)
+#define PL181_STATUS_CMDACTIVE        (1 << 11)
+#define PL181_STATUS_TXACTIVE         (1 << 12)
+#define PL181_STATUS_RXACTIVE         (1 << 13)
+#define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
+#define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
+#define PL181_STATUS_TXFIFOFULL       (1 << 16)
+#define PL181_STATUS_RXFIFOFULL       (1 << 17)
+#define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
+#define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
+#define PL181_STATUS_TXDATAAVLBL      (1 << 20)
+#define PL181_STATUS_RXDATAAVLBL      (1 << 21)
+
+#define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
+                             |PL181_STATUS_TXFIFOHALFEMPTY \
+                             |PL181_STATUS_TXFIFOFULL \
+                             |PL181_STATUS_TXFIFOEMPTY \
+                             |PL181_STATUS_TXDATAAVLBL)
+#define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
+                             |PL181_STATUS_RXFIFOHALFFULL \
+                             |PL181_STATUS_RXFIFOFULL \
+                             |PL181_STATUS_RXFIFOEMPTY \
+                             |PL181_STATUS_RXDATAAVLBL)
+
+static const unsigned char pl181_id[] =
+{ 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
+
+static void pl181_update(pl181_state *s)
+{
+    int i;
+    for (i = 0; i < 2; i++) {
+        qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
+    }
+}
+
+static void pl181_fifo_push(pl181_state *s, uint32_t value)
+{
+    int n;
+
+    if (s->fifo_len == PL181_FIFO_LEN) {
+        fprintf(stderr, "pl181: FIFO overflow\n");
+        return;
+    }
+    n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
+    s->fifo_len++;
+    s->fifo[n] = value;
+    DPRINTF("FIFO push %08x\n", (int)value);
+}
+
+static uint32_t pl181_fifo_pop(pl181_state *s)
+{
+    uint32_t value;
+
+    if (s->fifo_len == 0) {
+        fprintf(stderr, "pl181: FIFO underflow\n");
+        return 0;
+    }
+    value = s->fifo[s->fifo_pos];
+    s->fifo_len--;
+    s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
+    DPRINTF("FIFO pop %08x\n", (int)value);
+    return value;
+}
+
+static void pl181_send_command(pl181_state *s)
+{
+    struct sd_request_s request;
+    uint8_t response[16];
+    int rlen;
+
+    request.cmd = s->cmd & PL181_CMD_INDEX;
+    request.arg = s->cmdarg;
+    DPRINTF("Command %d %08x\n", request.cmd, request.arg);
+    rlen = sd_do_command(s->card, &request, response);
+    if (rlen < 0)
+        goto error;
+    if (s->cmd & PL181_CMD_RESPONSE) {
+#define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \
+                  | (response[n + 2] << 8) | response[n + 3])
+        if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
+            goto error;
+        if (rlen != 4 && rlen != 16)
+            goto error;
+        s->response[0] = RWORD(0);
+        if (rlen == 4) {
+            s->response[1] = s->response[2] = s->response[3] = 0;
+        } else {
+            s->response[1] = RWORD(4);
+            s->response[2] = RWORD(8);
+            s->response[3] = RWORD(12) & ~1;
+        }
+        DPRINTF("Response recieved\n");
+        s->status |= PL181_STATUS_CMDRESPEND;
+#undef RWORD
+    } else {
+        DPRINTF("Command sent\n");
+        s->status |= PL181_STATUS_CMDSENT;
+    }
+    return;
+
+error:
+    DPRINTF("Timeout\n");
+    s->status |= PL181_STATUS_CMDTIMEOUT;
+}
+
+/* Transfer data between teh card and the FIFO.  This is complicated by
+   the FIFO holding 32-bit words and the card taking data in single byte
+   chunks.  FIFO bytes are transferred in little-endian order.  */
+   
+static void pl181_fifo_run(pl181_state *s)
+{
+    uint32_t bits;
+    uint32_t value;
+    int n;
+    int limit;
+    int is_read;
+
+    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
+    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))) {
+        limit = is_read ? PL181_FIFO_LEN : 0;
+        n = 0;
+        value = 0;
+        while (s->datacnt && s->fifo_len != limit) {
+            if (is_read) {
+                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
+                n++;
+                if (n == 4) {
+                    pl181_fifo_push(s, value);
+                    value = 0;
+                    n = 0;
+                }
+            } else {
+                if (n == 0) {
+                    value = pl181_fifo_pop(s);
+                    n = 4;
+                }
+                sd_write_data(s->card, value & 0xff);
+                value >>= 8;
+                n--;
+            }
+            s->datacnt--;
+        }
+        if (n && is_read) {
+            pl181_fifo_push(s, value);
+        }
+    }
+    s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
+    if (s->datacnt == 0) {
+        s->status |= PL181_STATUS_DATAEND;
+        /* HACK: */
+        s->status |= PL181_STATUS_DATABLOCKEND;
+        DPRINTF("Transfer Complete\n");
+    }
+    if (s->datacnt == 0 && s->fifocnt == 0) {
+        s->datactrl &= ~PL181_DATA_ENABLE;
+        DPRINTF("Data engine idle\n");
+    } else {
+        /* Update FIFO bits.  */
+        bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
+        if (s->fifo_len == 0) {
+            bits |= PL181_STATUS_TXFIFOEMPTY;
+            bits |= PL181_STATUS_RXFIFOEMPTY;
+        } else {
+            bits |= PL181_STATUS_TXDATAAVLBL;
+            bits |= PL181_STATUS_RXDATAAVLBL;
+        }
+        if (s->fifo_len == 16) {
+            bits |= PL181_STATUS_TXFIFOFULL;
+            bits |= PL181_STATUS_RXFIFOFULL;
+        }
+        if (s->fifo_len <= 8) {
+            bits |= PL181_STATUS_TXFIFOHALFEMPTY;
+        }
+        if (s->fifo_len >= 8) {
+            bits |= PL181_STATUS_RXFIFOHALFFULL;
+        }
+        if (s->datactrl & PL181_DATA_DIRECTION) {
+            bits &= PL181_STATUS_RX_FIFO;
+        } else {
+            bits &= PL181_STATUS_TX_FIFO;
+        }
+        s->status |= bits;
+    }
+}
+
+static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    offset -= s->base;
+    if (offset >= 0xfe0 && offset < 0x1000) {
+        return pl181_id[(offset - 0xfe0) >> 2];
+    }
+    switch (offset) {
+    case 0x00: /* Power */
+        return s->power;
+    case 0x04: /* Clock */
+        return s->clock;
+    case 0x08: /* Argument */
+        return s->cmdarg;
+    case 0x0c: /* Command */
+        return s->cmd;
+    case 0x10: /* RespCmd */
+        return s->respcmd;
+    case 0x14: /* Response0 */
+        return s->response[0];
+    case 0x18: /* Response1 */
+        return s->response[1];
+    case 0x1c: /* Response2 */
+        return s->response[2];
+    case 0x20: /* Response3 */
+        return s->response[3];
+    case 0x24: /* DataTimer */
+        return s->datatimer;
+    case 0x28: /* DataLength */
+        return s->datalength;
+    case 0x2c: /* DataCtrl */
+        return s->datactrl;
+    case 0x30: /* DataCnt */
+        return s->datacnt;
+    case 0x34: /* Status */
+        return s->status;
+    case 0x3c: /* Mask0 */
+        return s->mask[0];
+    case 0x40: /* Mask1 */
+        return s->mask[1];
+    case 0x48: /* FifoCnt */
+        return s->fifocnt;
+    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
+    case 0x90: case 0x94: case 0x98: case 0x9c:
+    case 0xa0: case 0xa4: case 0xa8: case 0xac:
+    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
+        if (s->fifocnt == 0) {
+            fprintf(stderr, "pl181: Unexpected FIFO read\n");
+            return 0;
+        } else {
+            uint32_t value;
+            s->fifocnt--;
+            value = pl181_fifo_pop(s);
+            pl181_fifo_run(s);
+            pl181_update(s);
+            return value;
+        }
+    default:
+        cpu_abort (cpu_single_env, "pl181_read: Bad offset %x\n", offset);
+        return 0;
+    }
+}
+
+static void pl181_write(void *opaque, target_phys_addr_t offset,
+                          uint32_t value)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    offset -= s->base;
+    switch (offset) {
+    case 0x00: /* Power */
+        s->power = value & 0xff;
+        break;
+    case 0x04: /* Clock */
+        s->clock = value & 0xff;
+        break;
+    case 0x08: /* Argument */
+        s->cmdarg = value;
+        break;
+    case 0x0c: /* Command */
+        s->cmd = value;
+        if (s->cmd & PL181_CMD_ENABLE) {
+            if (s->cmd & PL181_CMD_INTERRUPT) {
+                fprintf(stderr, "pl181: Interrupt mode not implemented\n");
+                abort();
+            } if (s->cmd & PL181_CMD_PENDING) {
+                fprintf(stderr, "pl181: Pending commands not implemented\n");
+                abort();
+            } else {
+                pl181_send_command(s);
+                pl181_fifo_run(s);
+            }
+            /* The command has completed one way or the other.  */
+            s->cmd &= ~PL181_CMD_ENABLE;
+        }
+        break;
+    case 0x24: /* DataTimer */
+        s->datatimer = value;
+        break;
+    case 0x28: /* DataLength */
+        s->datalength = value & 0xffff;
+        break;
+    case 0x2c: /* DataCtrl */
+        s->datactrl = value & 0xff;
+        if (value & PL181_DATA_ENABLE) {
+            s->datacnt = s->datalength;
+            s->fifocnt = (s->datalength + 3) >> 2;
+            pl181_fifo_run(s);
+        }
+        break;
+    case 0x38: /* Clear */
+        s->status &= ~(value & 0x7ff);
+        break;
+    case 0x3c: /* Mask0 */
+        s->mask[0] = value;
+        break;
+    case 0x40: /* Mask1 */
+        s->mask[1] = value;
+        break;
+    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
+    case 0x90: case 0x94: case 0x98: case 0x9c:
+    case 0xa0: case 0xa4: case 0xa8: case 0xac:
+    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
+        if (s->fifocnt == 0) {
+            fprintf(stderr, "pl181: Unexpected FIFO write\n");
+        } else {
+            s->fifocnt--;
+            pl181_fifo_push(s, value);
+            pl181_fifo_run(s);
+        }
+        break;
+    default:
+        cpu_abort (cpu_single_env, "pl181_write: Bad offset %x\n", offset);
+    }
+    pl181_update(s);
+}
+
+static CPUReadMemoryFunc *pl181_readfn[] = {
+   pl181_read,
+   pl181_read,
+   pl181_read
+};
+
+static CPUWriteMemoryFunc *pl181_writefn[] = {
+   pl181_write,
+   pl181_write,
+   pl181_write
+};
+
+static void pl181_reset(void *opaque)
+{
+    pl181_state *s = (pl181_state *)opaque;
+
+    s->power = 0;
+    s->cmdarg = 0;
+    s->cmd = 0;
+    s->datatimer = 0;
+    s->datalength = 0;
+    s->respcmd = 0;
+    s->response[0] = 0;
+    s->response[1] = 0;
+    s->response[2] = 0;
+    s->response[3] = 0;
+    s->datatimer = 0;
+    s->datalength = 0;
+    s->datactrl = 0;
+    s->datacnt = 0;
+    s->status = 0;
+    s->mask[0] = 0;
+    s->mask[1] = 0;
+    s->fifocnt = 0;
+}
+
+void pl181_init(uint32_t base, BlockDriverState *bd,
+                qemu_irq irq0, qemu_irq irq1)
+{
+    int iomemtype;
+    pl181_state *s;
+
+    s = (pl181_state *)qemu_mallocz(sizeof(pl181_state));
+    iomemtype = cpu_register_io_memory(0, pl181_readfn,
+                                       pl181_writefn, s);
+    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+    s->base = base;
+    s->card = sd_init(bd);
+    s->irq[0] = irq0;
+    s->irq[1] = irq1;
+    qemu_register_reset(pl181_reset, s);
+    pl181_reset(s);
+    /* ??? Save/restore.  */
+}

Modified: trunk/src/host/qemu-neo1973/hw/pl190.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pl190.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pl190.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -17,7 +17,6 @@
 #define PL190_NUM_PRIO 17
 
 typedef struct {
-    arm_pic_handler handler;
     uint32_t base;
     DisplayState *ds;
     uint32_t level;
@@ -33,9 +32,8 @@
     /* Current priority level.  */
     int priority;
     int prev_prio[PL190_NUM_PRIO];
-    void *parent;
-    int irq;
-    int fiq;
+    qemu_irq irq;
+    qemu_irq fiq;
 } pl190_state;
 
 static const unsigned char pl190_id[] =
@@ -53,9 +51,9 @@
     int set;
 
     set = (level & s->prio_mask[s->priority]) != 0;
-    pic_set_irq_new(s->parent, s->irq, set);
+    qemu_set_irq(s->irq, set);
     set = ((s->level | s->soft_level) & s->fiq_select) != 0;
-    pic_set_irq_new(s->parent, s->fiq, set);
+    qemu_set_irq(s->fiq, set);
 }
 
 static void pl190_set_irq(void *opaque, int irq, int level)
@@ -232,21 +230,21 @@
   pl190_update_vectors(s);
 }
 
-void *pl190_init(uint32_t base, void *parent, int irq, int fiq)
+qemu_irq *pl190_init(uint32_t base, qemu_irq irq, qemu_irq fiq)
 {
     pl190_state *s;
+    qemu_irq *qi;
     int iomemtype;
 
     s = (pl190_state *)qemu_mallocz(sizeof(pl190_state));
     iomemtype = cpu_register_io_memory(0, pl190_readfn,
                                        pl190_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
-    s->handler = pl190_set_irq;
+    qi = qemu_allocate_irqs(pl190_set_irq, s, 32);
     s->base = base;
-    s->parent = parent;
     s->irq = irq;
     s->fiq = fiq;
     pl190_reset(s);
     /* ??? Save/restore.  */
-    return s;
+    return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/ppc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
- * QEMU generic PPC hardware System Emulator
+ * QEMU generic PowerPC hardware System Emulator
  * 
- * Copyright (c) 2003-2004 Jocelyn Mayer
+ * Copyright (c) 2003-2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -24,10 +24,387 @@
 #include "vl.h"
 #include "m48t59.h"
 
+//#define PPC_DEBUG_IRQ
+//#define PPC_DEBUG_TB
+
+extern FILE *logfile;
+extern int loglevel;
+
+void ppc_set_irq (CPUState *env, int n_IRQ, int level)
+{
+    if (level) {
+        env->pending_interrupts |= 1 << n_IRQ;
+        cpu_interrupt(env, CPU_INTERRUPT_HARD);
+    } else {
+        env->pending_interrupts &= ~(1 << n_IRQ);
+        if (env->pending_interrupts == 0)
+            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
+                __func__, env, n_IRQ, level,
+                env->pending_interrupts, env->interrupt_request);
+    }
+#endif
+}
+
+/* PowerPC 6xx / 7xx internal IRQ controller */
+static void ppc6xx_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC6xx_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC6xx_INPUT_SMI:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
+            break;
+        case PPC6xx_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: raise machine check state\n",
+                            __func__);
+                }
+#endif
+                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC6xx_INPUT_CKSTP_IN:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC6xx_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the CPU\n", __func__);
+                }
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC6xx_INPUT_SRESET:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc6xx_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
+}
+
+/* PowerPC 970 internal IRQ controller */
+static void ppc970_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC970_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC970_INPUT_THINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
+                        level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
+            break;
+        case PPC970_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: raise machine check state\n",
+                            __func__);
+                }
+#endif
+                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC970_INPUT_CKSTP:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC970_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the CPU\n", __func__);
+                }
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC970_INPUT_SRESET:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC970_INPUT_TBEN:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
+                        level);
+            }
+#endif
+            /* XXX: TODO */
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc970_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
+}
+
+/* PowerPC 405 internal IRQ controller */
+static void ppc405_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC405_INPUT_RESET_SYS:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC system\n",
+                            __func__);
+                }
+#endif
+                ppc40x_system_reset(env);
+            }
+            break;
+        case PPC405_INPUT_RESET_CHIP:
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
+                }
+#endif
+                ppc40x_chip_reset(env);
+            }
+            break;
+            /* No break here */
+        case PPC405_INPUT_RESET_CORE:
+            /* XXX: TODO: update DBSR[MRR] */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
+                }
+#endif
+                ppc40x_core_reset(env);
+            }
+            break;
+        case PPC405_INPUT_CINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            /* XXX: TOFIX */
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC405_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC405_INPUT_HALT:
+            /* Level sensitive - active low */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC405_INPUT_DEBUG:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, EXCP_40x_DEBUG, level);
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc405_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc405_set_irq, env, 7);
+}
+
 /*****************************************************************************/
-/* PPC time base and decrementer emulation */
-//#define DEBUG_TB
-
+/* PowerPC time base and decrementer emulation */
 struct ppc_tb_t {
     /* Time base management */
     int64_t  tb_offset;    /* Compensation               */
@@ -35,13 +412,14 @@
     /* Decrementer management */
     uint64_t decr_next;    /* Tick for next decr interrupt  */
     struct QEMUTimer *decr_timer;
+    void *opaque;
 };
 
 static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
 {
     /* TB time in tb periods */
     return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
-		    tb_env->tb_freq, ticks_per_sec);
+                    tb_env->tb_freq, ticks_per_sec);
 }
 
 uint32_t cpu_ppc_load_tbl (CPUState *env)
@@ -50,16 +428,18 @@
     uint64_t tb;
 
     tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
+#ifdef PPC_DEBUG_TB
     {
-         static int last_time;
-	 int now;
-	 now = time(NULL);
-	 if (last_time != now) {
-	     last_time = now;
-	     printf("%s: tb=0x%016lx %d %08lx\n",
-                    __func__, tb, now, tb_env->tb_offset);
-	 }
+        static int last_time;
+        int now;
+        now = time(NULL);
+        if (last_time != now) {
+            last_time = now;
+            if (loglevel != 0) {
+                fprintf(logfile, "%s: tb=0x%016lx %d %08lx\n",
+                        __func__, tb, now, tb_env->tb_offset);
+            }
+        }
     }
 #endif
 
@@ -72,9 +452,12 @@
     uint64_t tb;
 
     tb = cpu_ppc_get_tb(tb_env);
-#ifdef DEBUG_TB
-    printf("%s: tb=0x%016lx\n", __func__, tb);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
+    }
 #endif
+
     return tb >> 32;
 }
 
@@ -82,8 +465,11 @@
 {
     tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
         - qemu_get_clock(vm_clock);
-#ifdef DEBUG_TB
-    printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
+                tb_env->tb_offset);
+    }
 #endif
 }
 
@@ -114,9 +500,12 @@
         decr = muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
     else
         decr = -muldiv64(-diff, tb_env->tb_freq, ticks_per_sec);
-#if defined(DEBUG_TB)
-    printf("%s: 0x%08x\n", __func__, decr);
+#if defined(PPC_DEBUG_TB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
+    }
 #endif
+
     return decr;
 }
 
@@ -126,10 +515,12 @@
 static inline void cpu_ppc_decr_excp (CPUState *env)
 {
     /* Raise it */
-#ifdef DEBUG_TB
-    printf("raise decrementer exception\n");
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "raise decrementer exception\n");
+    }
 #endif
-    cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
 }
 
 static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
@@ -138,15 +529,17 @@
     ppc_tb_t *tb_env = env->tb_env;
     uint64_t now, next;
 
-#ifdef DEBUG_TB
-    printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
+    }
 #endif
     now = qemu_get_clock(vm_clock);
     next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
     if (is_excp)
         next += tb_env->decr_next - now;
     if (next == now)
-	next++;
+        next++;
     tb_env->decr_next = next;
     /* Adjust timer */
     qemu_mod_timer(tb_env->decr_timer, next);
@@ -154,7 +547,7 @@
      * raise an exception.
      */
     if ((value & 0x80000000) && !(decr & 0x80000000))
-	cpu_ppc_decr_excp(env);
+        cpu_ppc_decr_excp(env);
 }
 
 void cpu_ppc_store_decr (CPUState *env, uint32_t value)
@@ -167,8 +560,21 @@
     _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
 }
 
+static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+    tb_env->tb_freq = freq;
+    /* There is a bug in Linux 2.4 kernels:
+     * if a decrementer exception is pending when it enables msr_ee at startup,
+     * it's not ready to handle it...
+     */
+    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+}
+
 /* Set up (once) timebase frequency (in Hz) */
-ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
+clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
 {
     ppc_tb_t *tb_env;
 
@@ -176,21 +582,414 @@
     if (tb_env == NULL)
         return NULL;
     env->tb_env = tb_env;
-    if (tb_env->tb_freq == 0 || 1) {
-	tb_env->tb_freq = freq;
-	/* Create new timer */
-	tb_env->decr_timer =
-            qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
-	/* There is a bug in  2.4 kernels:
-	 * if a decrementer exception is pending when it enables msr_ee,
-	 * it's not ready to handle it...
-	 */
-	_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+    /* Create new timer */
+    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+    cpu_ppc_set_tb_clk(env, freq);
+
+    return &cpu_ppc_set_tb_clk;
+}
+
+/* Specific helpers for POWER & PowerPC 601 RTC */
+clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
+{
+    return cpu_ppc_tb_init(env, 7812500);
+}
+
+void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+
+void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
+}
+
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+{
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC timers */
+
+/* PIT, FIT & WDT */
+typedef struct ppcemb_timer_t ppcemb_timer_t;
+struct ppcemb_timer_t {
+    uint64_t pit_reload;  /* PIT auto-reload value        */
+    uint64_t fit_next;    /* Tick for next FIT interrupt  */
+    struct QEMUTimer *fit_timer;
+    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
+    struct QEMUTimer *wdt_timer;
+};
+   
+/* Fixed interval timer */
+static void cpu_4xx_fit_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    now = qemu_get_clock(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
+    case 0:
+        next = 1 << 9;
+        break;
+    case 1:
+        next = 1 << 13;
+        break;
+    case 2:
+        next = 1 << 17;
+        break;
+    case 3:
+        next = 1 << 21;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
     }
+    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+    if (next == now)
+        next++;
+    qemu_mod_timer(ppcemb_timer->fit_timer, next);
+    env->spr[SPR_40x_TSR] |= 1 << 26;
+    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
+        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
+                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    }
+#endif
+}
 
-    return tb_env;
+/* Programmable interval timer */
+static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
+{
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    ppcemb_timer = tb_env->opaque;
+    if (ppcemb_timer->pit_reload <= 1 ||
+        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
+        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
+        /* Stop PIT */
+#ifdef PPC_DEBUG_TB
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: stop PIT\n", __func__);
+        }
+#endif
+        qemu_del_timer(tb_env->decr_timer);
+    } else {
+#ifdef PPC_DEBUG_TB
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
+                    __func__, ppcemb_timer->pit_reload);
+        }
+#endif
+        now = qemu_get_clock(vm_clock);
+        next = now + muldiv64(ppcemb_timer->pit_reload,
+                              ticks_per_sec, tb_env->tb_freq);
+        if (is_excp)
+            next += tb_env->decr_next - now;
+        if (next == now)
+            next++;
+        qemu_mod_timer(tb_env->decr_timer, next);
+        tb_env->decr_next = next;
+    }
 }
 
+static void cpu_4xx_pit_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    env->spr[SPR_40x_TSR] |= 1 << 27;
+    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
+        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
+    start_stop_pit(env, tb_env, 1);
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
+                "%016" PRIx64 "\n", __func__,
+                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
+                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
+                ppcemb_timer->pit_reload);
+    }
+#endif
+}
+
+/* Watchdog timer */
+static void cpu_4xx_wdt_cb (void *opaque)
+{
+    CPUState *env;
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+    uint64_t now, next;
+
+    env = opaque;
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+    now = qemu_get_clock(vm_clock);
+    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
+    case 0:
+        next = 1 << 17;
+        break;
+    case 1:
+        next = 1 << 21;
+        break;
+    case 2:
+        next = 1 << 25;
+        break;
+    case 3:
+        next = 1 << 29;
+        break;
+    default:
+        /* Cannot occur, but makes gcc happy */
+        return;
+    }
+    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
+    if (next == now)
+        next++;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
+                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
+    }
+#endif
+    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
+    case 0x0:
+    case 0x1:
+        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
+        ppcemb_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 31;
+        break;
+    case 0x2:
+        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
+        ppcemb_timer->wdt_next = next;
+        env->spr[SPR_40x_TSR] |= 1 << 30;
+        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
+            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
+        break;
+    case 0x3:
+        env->spr[SPR_40x_TSR] &= ~0x30000000;
+        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
+        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
+        case 0x0:
+            /* No reset */
+            break;
+        case 0x1: /* Core reset */
+            ppc40x_core_reset(env);
+            break;
+        case 0x2: /* Chip reset */
+            ppc40x_chip_reset(env);
+            break;
+        case 0x3: /* System reset */
+            ppc40x_system_reset(env);
+            break;
+        }
+    }
+}
+
+void store_40x_pit (CPUState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    tb_env = env->tb_env;
+    ppcemb_timer = tb_env->opaque;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
+    }
+#endif
+    ppcemb_timer->pit_reload = val;
+    start_stop_pit(env, tb_env, 0);
+}
+
+target_ulong load_40x_pit (CPUState *env)
+{
+    return cpu_ppc_load_decr(env);
+}
+
+void store_booke_tsr (CPUState *env, target_ulong val)
+{
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
+    }
+#endif
+    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
+    if (val & 0x80000000)
+        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
+}
+
+void store_booke_tcr (CPUState *env, target_ulong val)
+{
+    ppc_tb_t *tb_env;
+
+    tb_env = env->tb_env;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
+    }
+#endif
+    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
+    start_stop_pit(env, tb_env, 1);
+    cpu_4xx_wdt_cb(env);
+}
+
+static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
+{
+    CPUState *env = opaque;
+    ppc_tb_t *tb_env = env->tb_env;
+
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
+    }
+#endif
+    tb_env->tb_freq = freq;
+    /* XXX: we should also update all timers */
+}
+
+clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
+{
+    ppc_tb_t *tb_env;
+    ppcemb_timer_t *ppcemb_timer;
+
+    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
+    if (tb_env == NULL) {
+        return NULL;
+    }
+    env->tb_env = tb_env;
+    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
+    tb_env->tb_freq = freq;
+    tb_env->opaque = ppcemb_timer;
+#ifdef PPC_DEBUG_TB
+    if (loglevel != 0) {
+        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
+                &ppc_emb_set_tb_clk);
+    }
+#endif
+    if (ppcemb_timer != NULL) {
+        /* We use decr timer for PIT */
+        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
+        ppcemb_timer->fit_timer =
+            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
+        ppcemb_timer->wdt_timer =
+            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
+    }
+
+    return &ppc_emb_set_tb_clk;
+}
+
+/*****************************************************************************/
+/* Embedded PowerPC Device Control Registers */
+typedef struct ppc_dcrn_t ppc_dcrn_t;
+struct ppc_dcrn_t {
+    dcr_read_cb dcr_read;
+    dcr_write_cb dcr_write;
+    void *opaque;
+};
+
+#define DCRN_NB 1024
+struct ppc_dcr_t {
+    ppc_dcrn_t dcrn[DCRN_NB];
+    int (*read_error)(int dcrn);
+    int (*write_error)(int dcrn);
+};
+
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_read == NULL)
+        goto error;
+    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+
+    return 0;
+
+ error:
+    if (dcr_env->read_error != NULL)
+        return (*dcr_env->read_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+    ppc_dcrn_t *dcr;
+
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        goto error;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->dcr_write == NULL)
+        goto error;
+    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
+
+    return 0;
+
+ error:
+    if (dcr_env->write_error != NULL)
+        return (*dcr_env->write_error)(dcrn);
+
+    return -1;
+}
+
+int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+    ppc_dcr_t *dcr_env;
+    ppc_dcrn_t *dcr;
+
+    dcr_env = env->dcr_env;
+    if (dcr_env == NULL)
+        return -1;
+    if (dcrn < 0 || dcrn >= DCRN_NB)
+        return -1;
+    dcr = &dcr_env->dcrn[dcrn];
+    if (dcr->opaque != NULL ||
+        dcr->dcr_read != NULL ||
+        dcr->dcr_write != NULL)
+        return -1;
+    dcr->opaque = opaque;
+    dcr->dcr_read = dcr_read;
+    dcr->dcr_write = dcr_write;
+
+    return 0;
+}
+
+int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
+                  int (*write_error)(int dcrn))
+{
+    ppc_dcr_t *dcr_env;
+
+    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
+    if (dcr_env == NULL)
+        return -1;
+    dcr_env->read_error = read_error;
+    dcr_env->write_error = write_error;
+    env->dcr_env = dcr_env;
+
+    return 0;
+}
+
+
 #if 0
 /*****************************************************************************/
 /* Handle system reset (for now, just stop emulation) */
@@ -264,6 +1063,7 @@
     tmp |= m48t59_read(nvram, addr + 1) << 16;
     tmp |= m48t59_read(nvram, addr + 2) << 8;
     tmp |= m48t59_read(nvram, addr + 3);
+
     return tmp;
 }
 
@@ -316,10 +1116,10 @@
     odd = count & 1;
     count &= ~1;
     for (i = 0; i != count; i++) {
-	crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
     }
     if (odd) {
-	crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
     }
 
     return crc;

Added: trunk/src/host/qemu-neo1973/hw/ppc405.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,122 @@
+/*
+ * QEMU PowerPC 405 shared definitions
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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.
+ */
+
+#if !defined(PPC_405_H)
+#define PPC_405_H
+
+/* Bootinfo as set-up by u-boot */
+typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
+struct ppc4xx_bd_info_t {
+    uint32_t bi_memstart;
+    uint32_t bi_memsize;
+    uint32_t bi_flashstart;
+    uint32_t bi_flashsize;
+    uint32_t bi_flashoffset; /* 0x10 */
+    uint32_t bi_sramstart;
+    uint32_t bi_sramsize;
+    uint32_t bi_bootflags;
+    uint32_t bi_ipaddr; /* 0x20 */
+    uint8_t  bi_enetaddr[6];
+    uint16_t bi_ethspeed;
+    uint32_t bi_intfreq;
+    uint32_t bi_busfreq; /* 0x30 */
+    uint32_t bi_baudrate;
+    uint8_t  bi_s_version[4];
+    uint8_t  bi_r_version[32];
+    uint32_t bi_procfreq;
+    uint32_t bi_plb_busfreq;
+    uint32_t bi_pci_busfreq;
+    uint8_t  bi_pci_enetaddr[6];
+    uint32_t bi_pci_enetaddr2[6];
+    uint32_t bi_opbfreq;
+    uint32_t bi_iic_fast[2];
+};
+
+/* PowerPC 405 core */
+CPUState *ppc405_init (const unsigned char *cpu_model,
+                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                       uint32_t sysclk);
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd);
+
+/* */
+typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+                          target_phys_addr_t offset, uint32_t len,
+                          CPUReadMemoryFunc **mem_read,
+                          CPUWriteMemoryFunc **mem_write, void *opaque);
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
+/* PowerPC 4xx peripheral local bus arbitrer */
+void ppc4xx_plb_init (CPUState *env);
+/* PLB to OPB bridge */
+void ppc4xx_pob_init (CPUState *env);
+/* OPB arbitrer */
+void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset);
+/* PowerPC 4xx universal interrupt controller */
+enum {
+    PPCUIC_OUTPUT_INT = 0,
+    PPCUIC_OUTPUT_CINT = 1,
+    PPCUIC_OUTPUT_NB,
+};
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr);
+/* SDRAM controller */
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_ulong *ram_bases, target_ulong *ram_sizes,
+                        int do_init);
+/* Peripheral controller */
+void ppc405_ebc_init (CPUState *env);
+/* DMA controller */
+void ppc405_dma_init (CPUState *env, qemu_irq irqs[4]);
+/* GPIO */
+void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset);
+/* Serial ports */
+void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                         target_phys_addr_t offset, qemu_irq irq,
+                         CharDriverState *chr);
+/* On Chip Memory */
+void ppc405_ocm_init (CPUState *env, unsigned long offset);
+/* I2C controller */
+void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq);
+/* General purpose timers */
+void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq[5]);
+/* Memory access layer */
+void ppc405_mal_init (CPUState *env, qemu_irq irqs[4]);
+/* PowerPC 405 microcontrollers */
+CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init);
+CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init);
+/* IBM STBxxx microcontrollers */
+CPUState *ppc_stb025_init (target_ulong ram_bases[2],
+                           target_ulong ram_sizes[2],
+                           uint32_t sysclk, qemu_irq **picp,
+                           ram_addr_t *offsetp);
+
+#endif /* !defined(PPC_405_H) */

Added: trunk/src/host/qemu-neo1973/hw/ppc405_boards.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_boards.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,630 @@
+/*
+ * QEMU PowerPC 405 evaluation boards emulation
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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 "vl.h"
+#include "ppc405.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+#define BIOS_FILENAME "ppc405_rom.bin"
+#undef BIOS_SIZE
+#define BIOS_SIZE (2048 * 1024)
+
+#define KERNEL_LOAD_ADDR 0x00000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+#define USE_FLASH_BIOS
+
+#define DEBUG_BOARD_INIT
+
+/*****************************************************************************/
+/* PPC405EP reference board (IBM) */
+/* Standalone board with:
+ * - PowerPC 405EP CPU
+ * - SDRAM (0x00000000)
+ * - Flash (0xFFF80000)
+ * - SRAM  (0xFFF00000)
+ * - NVRAM (0xF0000000)
+ * - FPGA  (0xF0300000)
+ */
+typedef struct ref405ep_fpga_t ref405ep_fpga_t;
+struct ref405ep_fpga_t {
+    uint32_t base;
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t ref405ep_fpga_readb (void *opaque, target_phys_addr_t addr)
+{
+    ref405ep_fpga_t *fpga;
+    uint32_t ret;
+
+    fpga = opaque;
+    addr -= fpga->base;
+    switch (addr) {
+    case 0x0:
+        ret = fpga->reg0;
+        break;
+    case 0x1:
+        ret = fpga->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void ref405ep_fpga_writeb (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    addr -= fpga->base;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        fpga->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t ref405ep_fpga_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writew (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_writeb(opaque, addr, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t ref405ep_fpga_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = ref405ep_fpga_readb(opaque, addr) << 24;
+    ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
+    ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
+    ret |= ref405ep_fpga_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ref405ep_fpga_writel (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    ref405ep_fpga_writel(opaque, addr, (value >> 24) & 0xFF);
+    ref405ep_fpga_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    ref405ep_fpga_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static CPUReadMemoryFunc *ref405ep_fpga_read[] = {
+    &ref405ep_fpga_readb,
+    &ref405ep_fpga_readw,
+    &ref405ep_fpga_readl,
+};
+
+static CPUWriteMemoryFunc *ref405ep_fpga_write[] = {
+    &ref405ep_fpga_writeb,
+    &ref405ep_fpga_writew,
+    &ref405ep_fpga_writel,
+};
+
+static void ref405ep_fpga_reset (void *opaque)
+{
+    ref405ep_fpga_t *fpga;
+
+    fpga = opaque;
+    fpga->reg0 = 0x00;
+    fpga->reg1 = 0x0F;
+}
+
+static void ref405ep_fpga_init (uint32_t base)
+{
+    ref405ep_fpga_t *fpga;
+    int fpga_memory;
+
+    fpga = qemu_mallocz(sizeof(ref405ep_fpga_t));
+    if (fpga != NULL) {
+        fpga->base = base;
+        fpga_memory = cpu_register_io_memory(0, ref405ep_fpga_read,
+                                             ref405ep_fpga_write, fpga);
+        cpu_register_physical_memory(base, 0x00000100, fpga_memory);
+        ref405ep_fpga_reset(fpga);
+        qemu_register_reset(&ref405ep_fpga_reset, fpga);
+    }
+}
+
+static void ref405ep_init (int ram_size, int vga_ram_size, int boot_device,
+                           DisplayState *ds, const char **fd_filename, 
+                           int snapshot,
+                           const char *kernel_filename, 
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           const char *cpu_model)
+{
+    char buf[1024];
+    ppc4xx_bd_info_t bd;
+    CPUPPCState *env;
+    qemu_irq *pic;
+    ram_addr_t sram_offset, bios_offset, bdloc;
+    target_ulong ram_bases[2], ram_sizes[2];
+    target_ulong sram_size, bios_size;
+    //int phy_addr = 0;
+    //static int phy_addr = 1;
+    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors, len;
+
+    /* XXX: fix this */
+    ram_bases[0] = 0x00000000;
+    ram_sizes[0] = 0x08000000;
+    ram_bases[1] = 0x00000000;
+    ram_sizes[1] = 0x00000000;
+    ram_size = 128 * 1024 * 1024;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, &sram_offset,
+                        kernel_filename == NULL ? 0 : 1);
+    /* allocate SRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register SRAM at offset %08lx\n", __func__, sram_offset);
+#endif
+    sram_size = 512 * 1024;
+    cpu_register_physical_memory(0xFFF00000, sram_size,
+                                 sram_offset | IO_MEM_RAM);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    bios_offset = sram_offset + sram_size;
+    fl_idx = 0;
+#ifdef USE_FLASH_BIOS
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s' %d\n",
+               fl_idx, bios_size, bios_offset, -bios_size,
+               bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
+#endif
+        pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 2,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        bios_size = load_image(buf, phys_ram_base + bios_offset);
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        cpu_register_physical_memory((uint32_t)(-bios_size), 
+                                     bios_size, bios_offset | IO_MEM_ROM);
+    }
+    bios_offset += bios_size;
+    /* Register FPGA */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register FPGA\n", __func__);
+#endif
+    ref405ep_fpga_init(0xF0300000);
+    /* Register NVRAM */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register NVRAM\n", __func__);
+#endif
+    m48t59_init(NULL, 0xF0000000, 0, 8192, 8);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        memset(&bd, 0, sizeof(bd));
+        bd.bi_memstart = 0x00000000;
+        bd.bi_memsize = ram_size;
+        bd.bi_flashstart = -(bios_size);
+        bd.bi_flashsize = -bios_size;
+        bd.bi_flashoffset = 0;
+        bd.bi_sramstart = 0xFFF00000;
+        bd.bi_sramsize = sram_size;
+        bd.bi_bootflags = 0;
+        bd.bi_intfreq = 133333333;
+        bd.bi_busfreq = 33333333;
+        bd.bi_baudrate = 115200;
+        bd.bi_s_version[0] = 'Q';
+        bd.bi_s_version[1] = 'M';
+        bd.bi_s_version[2] = 'U';
+        bd.bi_s_version[3] = '\0';
+        bd.bi_r_version[0] = 'Q';
+        bd.bi_r_version[1] = 'E';
+        bd.bi_r_version[2] = 'M';
+        bd.bi_r_version[3] = 'U';
+        bd.bi_r_version[4] = '\0';
+        bd.bi_procfreq = 133333333;
+        bd.bi_plb_busfreq = 33333333;
+        bd.bi_pci_busfreq = 33333333;
+        bd.bi_opbfreq = 33333333;
+        bdloc = ppc405_set_bootinfo(env, &bd);
+        env->gpr[3] = bdloc;
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
+                    kernel_filename);
+            exit(1);
+        }
+        printf("Load kernel size " TARGET_FMT_ld " at " TARGET_FMT_lx
+               " %02x %02x %02x %02x\n", kernel_size, kernel_base,
+               *(char *)(phys_ram_base + kernel_base),
+               *(char *)(phys_ram_base + kernel_base + 1),
+               *(char *)(phys_ram_base + kernel_base + 2),
+               *(char *)(phys_ram_base + kernel_base + 3));
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+        env->gpr[4] = initrd_base;
+        env->gpr[5] = initrd_size;
+        boot_device = 'm';
+        if (kernel_cmdline != NULL) {
+            len = strlen(kernel_cmdline);
+            bdloc -= ((len + 255) & ~255);
+            memcpy(phys_ram_base + bdloc, kernel_cmdline, len + 1);
+            env->gpr[6] = bdloc;
+            env->gpr[7] = bdloc + len;
+        } else {
+            env->gpr[6] = 0;
+            env->gpr[7] = 0;
+        }
+        env->nip = KERNEL_LOAD_ADDR;
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+        bdloc = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+    printf("bdloc %016lx %s\n",
+           (unsigned long)bdloc, (char *)(phys_ram_base + bdloc));
+}
+
+QEMUMachine ref405ep_machine = {
+    "ref405ep",
+    "ref405ep",
+    ref405ep_init,
+};
+
+/*****************************************************************************/
+/* AMCC Taihu evaluation board */
+/* - PowerPC 405EP processor
+ * - SDRAM               128 MB at 0x00000000
+ * - Boot flash          2 MB   at 0xFFE00000
+ * - Application flash   32 MB  at 0xFC000000
+ * - 2 serial ports
+ * - 2 ethernet PHY
+ * - 1 USB 1.1 device    0x50000000
+ * - 1 LCD display       0x50100000
+ * - 1 CPLD              0x50100000
+ * - 1 I2C EEPROM
+ * - 1 I2C thermal sensor
+ * - a set of LEDs
+ * - bit-bang SPI port using GPIOs
+ * - 1 EBC interface connector 0 0x50200000
+ * - 1 cardbus controller + expansion slot.
+ * - 1 PCI expansion slot.
+ */
+typedef struct taihu_cpld_t taihu_cpld_t;
+struct taihu_cpld_t {
+    uint32_t base;
+    uint8_t reg0;
+    uint8_t reg1;
+};
+
+static uint32_t taihu_cpld_readb (void *opaque, target_phys_addr_t addr)
+{
+    taihu_cpld_t *cpld;
+    uint32_t ret;
+
+    cpld = opaque;
+    addr -= cpld->base;
+    switch (addr) {
+    case 0x0:
+        ret = cpld->reg0;
+        break;
+    case 0x1:
+        ret = cpld->reg1;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void taihu_cpld_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    addr -= cpld->base;
+    switch (addr) {
+    case 0x0:
+        /* Read only */
+        break;
+    case 0x1:
+        cpld->reg1 = value;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t taihu_cpld_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void taihu_cpld_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_writeb(opaque, addr, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 1, value & 0xFF);
+}
+
+static uint32_t taihu_cpld_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = taihu_cpld_readb(opaque, addr) << 24;
+    ret |= taihu_cpld_readb(opaque, addr + 1) << 16;
+    ret |= taihu_cpld_readb(opaque, addr + 2) << 8;
+    ret |= taihu_cpld_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void taihu_cpld_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    taihu_cpld_writel(opaque, addr, (value >> 24) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 1, (value >> 16) & 0xFF);
+    taihu_cpld_writel(opaque, addr + 2, (value >> 8) & 0xFF);
+    taihu_cpld_writeb(opaque, addr + 3, value & 0xFF);
+}
+
+static CPUReadMemoryFunc *taihu_cpld_read[] = {
+    &taihu_cpld_readb,
+    &taihu_cpld_readw,
+    &taihu_cpld_readl,
+};
+
+static CPUWriteMemoryFunc *taihu_cpld_write[] = {
+    &taihu_cpld_writeb,
+    &taihu_cpld_writew,
+    &taihu_cpld_writel,
+};
+
+static void taihu_cpld_reset (void *opaque)
+{
+    taihu_cpld_t *cpld;
+
+    cpld = opaque;
+    cpld->reg0 = 0x01;
+    cpld->reg1 = 0x80;
+}
+
+static void taihu_cpld_init (uint32_t base)
+{
+    taihu_cpld_t *cpld;
+    int cpld_memory;
+
+    cpld = qemu_mallocz(sizeof(taihu_cpld_t));
+    if (cpld != NULL) {
+        cpld->base = base;
+        cpld_memory = cpu_register_io_memory(0, taihu_cpld_read,
+                                             taihu_cpld_write, cpld);
+        cpu_register_physical_memory(base, 0x00000100, cpld_memory);
+        taihu_cpld_reset(cpld);
+        qemu_register_reset(&taihu_cpld_reset, cpld);
+    }
+}
+
+static void taihu_405ep_init(int ram_size, int vga_ram_size, int boot_device,
+                             DisplayState *ds, const char **fd_filename, 
+                             int snapshot,
+                             const char *kernel_filename, 
+                             const char *kernel_cmdline,
+                             const char *initrd_filename,
+                             const char *cpu_model)
+{
+    char buf[1024];
+    CPUPPCState *env;
+    qemu_irq *pic;
+    ram_addr_t bios_offset;
+    target_ulong ram_bases[2], ram_sizes[2];
+    target_ulong bios_size;
+    target_ulong kernel_base, kernel_size, initrd_base, initrd_size;
+    int linux_boot;
+    int fl_idx, fl_sectors;
+    
+    /* RAM is soldered to the board so the size cannot be changed */
+    ram_bases[0] = 0x00000000;
+    ram_sizes[0] = 0x04000000;
+    ram_bases[1] = 0x04000000;
+    ram_sizes[1] = 0x04000000;
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register cpu\n", __func__);
+#endif
+    env = ppc405ep_init(ram_bases, ram_sizes, 33333333, &pic, &bios_offset,
+                        kernel_filename == NULL ? 0 : 1);
+    /* allocate and load BIOS */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register BIOS\n", __func__);
+#endif
+    fl_idx = 0;
+#if defined(USE_FLASH_BIOS)
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        /* XXX: should check that size is 2MB */
+        //        bios_size = 2 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s' %d\n",
+               fl_idx, bios_size, bios_offset, -bios_size,
+               bdrv_get_device_name(pflash_table[fl_idx]), fl_sectors);
+#endif
+        pflash_register(-(bios_size), bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 4,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    } else
+#endif
+    {
+#ifdef DEBUG_BOARD_INIT
+        printf("Load BIOS from file\n");
+#endif
+        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+        bios_size = load_image(buf, phys_ram_base + bios_offset);
+        if (bios_size < 0 || bios_size > BIOS_SIZE) {
+            fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
+            exit(1);
+        }
+        bios_size = (bios_size + 0xfff) & ~0xfff;
+        cpu_register_physical_memory((uint32_t)(-bios_size), 
+                                     bios_size, bios_offset | IO_MEM_ROM);
+    }
+    bios_offset += bios_size;
+    /* Register Linux flash */
+    if (pflash_table[fl_idx] != NULL) {
+        bios_size = bdrv_getlength(pflash_table[fl_idx]);
+        /* XXX: should check that size is 32MB */
+        bios_size = 32 * 1024 * 1024;
+        fl_sectors = (bios_size + 65535) >> 16;
+#ifdef DEBUG_BOARD_INIT
+        printf("Register parallel flash %d size " ADDRX " at offset %08lx "
+               " addr " ADDRX " '%s'\n",
+               fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
+               bdrv_get_device_name(pflash_table[fl_idx]));
+#endif
+        pflash_register(0xfc000000, bios_offset, pflash_table[fl_idx],
+                        65536, fl_sectors, 4,
+                        0x0001, 0x22DA, 0x0000, 0x0000);
+        fl_idx++;
+    }
+    /* Register CLPD & LCD display */
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: register CPLD\n", __func__);
+#endif
+    taihu_cpld_init(0x50100000);
+    /* Load kernel */
+    linux_boot = (kernel_filename != NULL);
+    if (linux_boot) {
+#ifdef DEBUG_BOARD_INIT
+        printf("%s: load kernel\n", __func__);
+#endif
+        kernel_base = KERNEL_LOAD_ADDR;
+        /* now we can load the kernel */
+        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
+                    kernel_filename);
+            exit(1);
+        }
+        /* load initrd */
+        if (initrd_filename) {
+            initrd_base = INITRD_LOAD_ADDR;
+            initrd_size = load_image(initrd_filename,
+                                     phys_ram_base + initrd_base);
+            if (initrd_size < 0) {
+                fprintf(stderr,
+                        "qemu: could not load initial ram disk '%s'\n", 
+                        initrd_filename);
+                exit(1);
+            }
+        } else {
+            initrd_base = 0;
+            initrd_size = 0;
+        }
+        boot_device = 'm';
+    } else {
+        kernel_base = 0;
+        kernel_size = 0;
+        initrd_base = 0;
+        initrd_size = 0;
+    }
+#ifdef DEBUG_BOARD_INIT
+    printf("%s: Done\n", __func__);
+#endif
+}
+
+QEMUMachine taihu_machine = {
+    "taihu",
+    "taihu",
+    taihu_405ep_init,
+};

Added: trunk/src/host/qemu-neo1973/hw/ppc405_uc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc405_uc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,3452 @@
+/*
+ * QEMU PowerPC 405 embedded processors emulation
+ * 
+ * Copyright (c) 2007 Jocelyn Mayer
+ * 
+ * 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 "vl.h"
+#include "ppc405.h"
+
+extern int loglevel;
+extern FILE *logfile;
+
+//#define DEBUG_MMIO
+#define DEBUG_OPBA
+#define DEBUG_SDRAM
+#define DEBUG_GPIO
+#define DEBUG_SERIAL
+#define DEBUG_OCM
+//#define DEBUG_I2C
+#define DEBUG_GPT
+#define DEBUG_MAL
+#define DEBUG_UIC
+#define DEBUG_CLOCKS
+//#define DEBUG_UNASSIGNED
+
+/*****************************************************************************/
+/* Generic PowerPC 405 processor instanciation */
+CPUState *ppc405_init (const unsigned char *cpu_model,
+                       clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
+                       uint32_t sysclk)
+{
+    CPUState *env;
+    ppc_def_t *def;
+
+    /* init CPUs */
+    env = cpu_init();
+    qemu_register_reset(&cpu_ppc_reset, env);
+    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
+    ppc_find_by_name(cpu_model, &def);
+    if (def == NULL) {
+        cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
+                  cpu_model);
+    }
+    cpu_ppc_register(env, def);
+    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
+    cpu_clk->opaque = env;
+    /* Set time-base frequency to sysclk */
+    tb_clk->cb = ppc_emb_timers_init(env, sysclk);
+    tb_clk->opaque = env;
+    ppc_dcr_init(env, NULL, NULL);
+
+    return env;
+}
+
+ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd)
+{
+    ram_addr_t bdloc;
+    int i, n;
+
+    /* We put the bd structure at the top of memory */
+    bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t);
+    stl_raw(phys_ram_base + bdloc + 0x00, bd->bi_memstart);
+    stl_raw(phys_ram_base + bdloc + 0x04, bd->bi_memsize);
+    stl_raw(phys_ram_base + bdloc + 0x08, bd->bi_flashstart);
+    stl_raw(phys_ram_base + bdloc + 0x0C, bd->bi_flashsize);
+    stl_raw(phys_ram_base + bdloc + 0x10, bd->bi_flashoffset);
+    stl_raw(phys_ram_base + bdloc + 0x14, bd->bi_sramstart);
+    stl_raw(phys_ram_base + bdloc + 0x18, bd->bi_sramsize);
+    stl_raw(phys_ram_base + bdloc + 0x1C, bd->bi_bootflags);
+    stl_raw(phys_ram_base + bdloc + 0x20, bd->bi_ipaddr);
+    for (i = 0; i < 6; i++)
+        stb_raw(phys_ram_base + bdloc + 0x24 + i, bd->bi_enetaddr[i]);
+    stw_raw(phys_ram_base + bdloc + 0x2A, bd->bi_ethspeed);
+    stl_raw(phys_ram_base + bdloc + 0x2C, bd->bi_intfreq);
+    stl_raw(phys_ram_base + bdloc + 0x30, bd->bi_busfreq);
+    stl_raw(phys_ram_base + bdloc + 0x34, bd->bi_baudrate);
+    for (i = 0; i < 4; i++)
+        stb_raw(phys_ram_base + bdloc + 0x38 + i, bd->bi_s_version[i]);
+    for (i = 0; i < 32; i++)
+        stb_raw(phys_ram_base + bdloc + 0x3C + i, bd->bi_s_version[i]);
+    stl_raw(phys_ram_base + bdloc + 0x5C, bd->bi_plb_busfreq);
+    stl_raw(phys_ram_base + bdloc + 0x60, bd->bi_pci_busfreq);
+    for (i = 0; i < 6; i++)
+        stb_raw(phys_ram_base + bdloc + 0x64 + i, bd->bi_pci_enetaddr[i]);
+    n = 0x6A;
+    if (env->spr[SPR_PVR] == CPU_PPC_405EP) {
+        for (i = 0; i < 6; i++)
+            stb_raw(phys_ram_base + bdloc + n++, bd->bi_pci_enetaddr2[i]);
+    }
+    stl_raw(phys_ram_base + bdloc + n, bd->bi_opbfreq);
+    n += 4;
+    for (i = 0; i < 2; i++) {
+        stl_raw(phys_ram_base + bdloc + n, bd->bi_iic_fast[i]);
+        n += 4;
+    }
+
+    return bdloc;
+}
+
+/*****************************************************************************/
+/* Shared peripherals */
+
+/*****************************************************************************/
+/* Fake device used to map multiple devices in a single memory page */
+#define MMIO_AREA_BITS 8
+#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
+#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
+#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
+struct ppc4xx_mmio_t {
+    target_phys_addr_t base;
+    CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
+    CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
+    void *opaque[MMIO_AREA_NB];
+};
+
+static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_UNASSIGNED
+    ppc4xx_mmio_t *mmio;
+
+    mmio = opaque;
+    printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
+           addr, mmio->base);
+#endif
+
+    return 0;
+}
+
+static void unassigned_mmio_writeb (void *opaque,
+                                   target_phys_addr_t addr, uint32_t val)
+{
+#ifdef DEBUG_UNASSIGNED
+    ppc4xx_mmio_t *mmio;
+
+    mmio = opaque;
+    printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
+           addr, val, mmio->base);
+#endif
+}
+
+static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
+    unassigned_mmio_readb,
+    unassigned_mmio_readb,
+    unassigned_mmio_readb,
+};
+
+static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
+    unassigned_mmio_writeb,
+    unassigned_mmio_writeb,
+    unassigned_mmio_writeb,
+};
+
+static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
+                              target_phys_addr_t addr, int len)
+{
+    CPUReadMemoryFunc **mem_read;
+    uint32_t ret;
+    int idx;
+
+    idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+    printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
+           mmio, len, addr, idx);
+#endif
+    mem_read = mmio->mem_read[idx];
+    ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
+
+    return ret;
+}
+
+static void mmio_writelen (ppc4xx_mmio_t *mmio,
+                           target_phys_addr_t addr, uint32_t value, int len)
+{
+    CPUWriteMemoryFunc **mem_write;
+    int idx;
+
+    idx = MMIO_IDX(addr - mmio->base);
+#if defined(DEBUG_MMIO)
+    printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
+           mmio, len, addr, idx, value);
+#endif
+    mem_write = mmio->mem_write[idx];
+    (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
+}
+
+static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 0);
+}
+
+static void mmio_writeb (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 0);
+}
+
+static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 1);
+}
+
+static void mmio_writew (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 1);
+}
+
+static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return mmio_readlen(opaque, addr, 2);
+}
+
+static void mmio_writel (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_MMIO)
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    mmio_writelen(opaque, addr, value, 2);
+}
+
+static CPUReadMemoryFunc *mmio_read[] = {
+    &mmio_readb,
+    &mmio_readw,
+    &mmio_readl,
+};
+
+static CPUWriteMemoryFunc *mmio_write[] = {
+    &mmio_writeb,
+    &mmio_writew,
+    &mmio_writel,
+};
+
+int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
+                          target_phys_addr_t offset, uint32_t len,
+                          CPUReadMemoryFunc **mem_read,
+                          CPUWriteMemoryFunc **mem_write, void *opaque)
+{
+    uint32_t end;
+    int idx, eidx;
+
+    if ((offset + len) > TARGET_PAGE_SIZE)
+        return -1;
+    idx = MMIO_IDX(offset);
+    end = offset + len - 1;
+    eidx = MMIO_IDX(end);
+#if defined(DEBUG_MMIO)
+    printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
+           end, idx, eidx);
+#endif
+    for (; idx <= eidx; idx++) {
+        mmio->mem_read[idx] = mem_read;
+        mmio->mem_write[idx] = mem_write;
+        mmio->opaque[idx] = opaque;
+    }
+
+    return 0;
+}
+
+ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
+{
+    ppc4xx_mmio_t *mmio;
+    int mmio_memory;
+
+    mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
+    if (mmio != NULL) {
+        mmio->base = base;
+        mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
+#if defined(DEBUG_MMIO)
+        printf("%s: %p base %08x len %08x %d\n", __func__,
+               mmio, base, TARGET_PAGE_SIZE, mmio_memory);
+#endif
+        cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
+        ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
+                             unassigned_mmio_read, unassigned_mmio_write,
+                             mmio);
+    }
+
+    return mmio;
+}
+
+/*****************************************************************************/
+/* Peripheral local bus arbitrer */
+enum {
+    PLB0_BESR = 0x084,
+    PLB0_BEAR = 0x086,
+    PLB0_ACR  = 0x087,
+};
+
+typedef struct ppc4xx_plb_t ppc4xx_plb_t;
+struct ppc4xx_plb_t {
+    uint32_t acr;
+    uint32_t bear;
+    uint32_t besr;
+};
+
+static target_ulong dcr_read_plb (void *opaque, int dcrn)
+{
+    ppc4xx_plb_t *plb;
+    target_ulong ret;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        ret = plb->acr;
+        break;
+    case PLB0_BEAR:
+        ret = plb->bear;
+        break;
+    case PLB0_BESR:
+        ret = plb->besr;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_plb (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    switch (dcrn) {
+    case PLB0_ACR:
+        /* We don't care about the actual parameters written as
+         * we don't manage any priorities on the bus
+         */
+        plb->acr = val & 0xF8000000;
+        break;
+    case PLB0_BEAR:
+        /* Read only */
+        break;
+    case PLB0_BESR:
+        /* Write-clear */
+        plb->besr &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_plb_reset (void *opaque)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = opaque;
+    plb->acr = 0x00000000;
+    plb->bear = 0x00000000;
+    plb->besr = 0x00000000;
+}
+
+void ppc4xx_plb_init (CPUState *env)
+{
+    ppc4xx_plb_t *plb;
+
+    plb = qemu_mallocz(sizeof(ppc4xx_plb_t));
+    if (plb != NULL) {
+        ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
+        ppc4xx_plb_reset(plb);
+        qemu_register_reset(ppc4xx_plb_reset, plb);
+    }
+}
+
+/*****************************************************************************/
+/* PLB to OPB bridge */
+enum {
+    POB0_BESR0 = 0x0A0,
+    POB0_BESR1 = 0x0A2,
+    POB0_BEAR  = 0x0A4,
+};
+
+typedef struct ppc4xx_pob_t ppc4xx_pob_t;
+struct ppc4xx_pob_t {
+    uint32_t bear;
+    uint32_t besr[2];
+};
+
+static target_ulong dcr_read_pob (void *opaque, int dcrn)
+{
+    ppc4xx_pob_t *pob;
+    target_ulong ret;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        ret = pob->bear;
+        break;
+    case POB0_BESR0:
+    case POB0_BESR1:
+        ret = pob->besr[dcrn - POB0_BESR0];
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_pob (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    switch (dcrn) {
+    case POB0_BEAR:
+        /* Read only */
+        break;
+    case POB0_BESR0:
+    case POB0_BESR1:
+        /* Write-clear */
+        pob->besr[dcrn - POB0_BESR0] &= ~val;
+        break;
+    }
+}
+
+static void ppc4xx_pob_reset (void *opaque)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = opaque;
+    /* No error */
+    pob->bear = 0x00000000;
+    pob->besr[0] = 0x0000000;
+    pob->besr[1] = 0x0000000;
+}
+
+void ppc4xx_pob_init (CPUState *env)
+{
+    ppc4xx_pob_t *pob;
+
+    pob = qemu_mallocz(sizeof(ppc4xx_pob_t));
+    if (pob != NULL) {
+        ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob);
+        ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob);
+        ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob);
+        qemu_register_reset(ppc4xx_pob_reset, pob);
+        ppc4xx_pob_reset(env);
+    }
+}
+
+/*****************************************************************************/
+/* OPB arbitrer */
+typedef struct ppc4xx_opba_t ppc4xx_opba_t;
+struct ppc4xx_opba_t {
+    target_phys_addr_t base;
+    uint8_t cr;
+    uint8_t pr;
+};
+
+static uint32_t opba_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_opba_t *opba;
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    opba = opaque;
+    switch (addr - opba->base) {
+    case 0x00:
+        ret = opba->cr;
+        break;
+    case 0x01:
+        ret = opba->pr;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+
+    return ret;
+}
+
+static void opba_writeb (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_opba_t *opba;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba = opaque;
+    switch (addr - opba->base) {
+    case 0x00:
+        opba->cr = value & 0xF8;
+        break;
+    case 0x01:
+        opba->pr = value & 0xFF;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t opba_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 8;
+    ret |= opba_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void opba_writew (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba_writeb(opaque, addr, value >> 8);
+    opba_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t opba_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = opba_readb(opaque, addr) << 24;
+    ret |= opba_readb(opaque, addr + 1) << 16;
+
+    return ret;
+}
+
+static void opba_writel (void *opaque,
+                         target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_OPBA
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    opba_writeb(opaque, addr, value >> 24);
+    opba_writeb(opaque, addr + 1, value >> 16);
+}
+
+static CPUReadMemoryFunc *opba_read[] = {
+    &opba_readb,
+    &opba_readw,
+    &opba_readl,
+};
+
+static CPUWriteMemoryFunc *opba_write[] = {
+    &opba_writeb,
+    &opba_writew,
+    &opba_writel,
+};
+
+static void ppc4xx_opba_reset (void *opaque)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = opaque;
+    opba->cr = 0x00; /* No dynamic priorities - park disabled */
+    opba->pr = 0x11;
+}
+
+void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset)
+{
+    ppc4xx_opba_t *opba;
+
+    opba = qemu_mallocz(sizeof(ppc4xx_opba_t));
+    if (opba != NULL) {
+        opba->base = offset;
+#ifdef DEBUG_OPBA
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x002,
+                             opba_read, opba_write, opba);
+        qemu_register_reset(ppc4xx_opba_reset, opba);
+        ppc4xx_opba_reset(opba);
+    }
+}
+
+/*****************************************************************************/
+/* "Universal" Interrupt controller */
+enum {
+    DCR_UICSR  = 0x000,
+    DCR_UICSRS = 0x001,
+    DCR_UICER  = 0x002,
+    DCR_UICCR  = 0x003,
+    DCR_UICPR  = 0x004,
+    DCR_UICTR  = 0x005,
+    DCR_UICMSR = 0x006,
+    DCR_UICVR  = 0x007,
+    DCR_UICVCR = 0x008,
+    DCR_UICMAX = 0x009,
+};
+
+#define UIC_MAX_IRQ 32
+typedef struct ppcuic_t ppcuic_t;
+struct ppcuic_t {
+    uint32_t dcr_base;
+    int use_vectors;
+    uint32_t uicsr;  /* Status register */
+    uint32_t uicer;  /* Enable register */
+    uint32_t uiccr;  /* Critical register */
+    uint32_t uicpr;  /* Polarity register */
+    uint32_t uictr;  /* Triggering register */
+    uint32_t uicvcr; /* Vector configuration register */
+    uint32_t uicvr;
+    qemu_irq *irqs;
+};
+
+static void ppcuic_trigger_irq (ppcuic_t *uic)
+{
+    uint32_t ir, cr;
+    int start, end, inc, i;
+
+    /* Trigger interrupt if any is pending */
+    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
+    cr = uic->uicsr & uic->uicer & uic->uiccr;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
+                "   %08x ir %08x cr %08x\n", __func__,
+                uic->uicsr, uic->uicer, uic->uiccr,
+                uic->uicsr & uic->uicer, ir, cr);
+    }
+#endif
+    if (ir != 0x0000000) {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Raise UIC interrupt\n");
+        }
+#endif
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
+    } else {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Lower UIC interrupt\n");
+        }
+#endif
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
+    }
+    /* Trigger critical interrupt if any is pending and update vector */
+    if (cr != 0x0000000) {
+        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        if (uic->use_vectors) {
+            /* Compute critical IRQ vector */
+            if (uic->uicvcr & 1) {
+                start = 31;
+                end = 0;
+                inc = -1;
+            } else {
+                start = 0;
+                end = 31;
+                inc = 1;
+            }
+            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
+            for (i = start; i <= end; i += inc) {
+                if (cr & (1 << i)) {
+                    uic->uicvr += (i - start) * 512 * inc;
+                    break;
+                }
+            }
+        }
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
+                    uic->uicvr);
+        }
+#endif
+    } else {
+#ifdef DEBUG_UIC
+        if (loglevel & CPU_LOG_INT) {
+            fprintf(logfile, "Lower UIC critical interrupt\n");
+        }
+#endif
+        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
+        uic->uicvr = 0x00000000;
+    }
+}
+
+static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+{
+    ppcuic_t *uic;
+    uint32_t mask, sr;
+
+    uic = opaque;
+    mask = 1 << irq_num;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
+                "%08x\n", __func__, irq_num, level,
+                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
+    }
+#endif
+    if (irq_num < 0 || irq_num > 31)
+        return;
+    sr = uic->uicsr;
+    if (!(uic->uicpr & mask)) {
+        /* Negatively asserted IRQ */
+        level = level == 0 ? 1 : 0;
+    }
+    /* Update status register */
+    if (uic->uictr & mask) {
+        /* Edge sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+    } else {
+        /* Level sensitive interrupt */
+        if (level == 1)
+            uic->uicsr |= mask;
+        else
+            uic->uicsr &= ~mask;
+    }
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
+                irq_num, level, uic->uicsr, sr);
+    }
+#endif
+    if (sr != uic->uicsr)
+        ppcuic_trigger_irq(uic);
+}
+
+static target_ulong dcr_read_uic (void *opaque, int dcrn)
+{
+    ppcuic_t *uic;
+    target_ulong ret;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+    switch (dcrn) {
+    case DCR_UICSR:
+    case DCR_UICSRS:
+        ret = uic->uicsr;
+        break;
+    case DCR_UICER:
+        ret = uic->uicer;
+        break;
+    case DCR_UICCR:
+        ret = uic->uiccr;
+        break;
+    case DCR_UICPR:
+        ret = uic->uicpr;
+        break;
+    case DCR_UICTR:
+        ret = uic->uictr;
+        break;
+    case DCR_UICMSR:
+        ret = uic->uicsr & uic->uicer;
+        break;
+    case DCR_UICVR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvr;
+        break;
+    case DCR_UICVCR:
+        if (!uic->use_vectors)
+            goto no_read;
+        ret = uic->uicvcr;
+        break;
+    default:
+    no_read:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    dcrn -= uic->dcr_base;
+#ifdef DEBUG_UIC
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
+    }
+#endif
+    switch (dcrn) {
+    case DCR_UICSR:
+        uic->uicsr &= ~val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICSRS:
+        uic->uicsr |= val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICER:
+        uic->uicer = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICCR:
+        uic->uiccr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICPR:
+        uic->uicpr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICTR:
+        uic->uictr = val;
+        ppcuic_trigger_irq(uic);
+        break;
+    case DCR_UICMSR:
+        break;
+    case DCR_UICVR:
+        break;
+    case DCR_UICVCR:
+        uic->uicvcr = val & 0xFFFFFFFD;
+        ppcuic_trigger_irq(uic);
+        break;
+    }
+}
+
+static void ppcuic_reset (void *opaque)
+{
+    ppcuic_t *uic;
+
+    uic = opaque;
+    uic->uiccr = 0x00000000;
+    uic->uicer = 0x00000000;
+    uic->uicpr = 0x00000000;
+    uic->uicsr = 0x00000000;
+    uic->uictr = 0x00000000;
+    if (uic->use_vectors) {
+        uic->uicvcr = 0x00000000;
+        uic->uicvr = 0x0000000;
+    }
+}
+
+qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
+                       uint32_t dcr_base, int has_ssr, int has_vr)
+{
+    ppcuic_t *uic;
+    int i;
+
+    uic = qemu_mallocz(sizeof(ppcuic_t));
+    if (uic != NULL) {
+        uic->dcr_base = dcr_base;
+        uic->irqs = irqs;
+        if (has_vr)
+            uic->use_vectors = 1;
+        for (i = 0; i < DCR_UICMAX; i++) {
+            ppc_dcr_register(env, dcr_base + i, uic,
+                             &dcr_read_uic, &dcr_write_uic);
+        }
+        qemu_register_reset(ppcuic_reset, uic);
+        ppcuic_reset(uic);
+    }
+
+    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
+}
+
+/*****************************************************************************/
+/* Code decompression controller */
+/* XXX: TODO */
+
+/*****************************************************************************/
+/* SDRAM controller */
+typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
+struct ppc4xx_sdram_t {
+    uint32_t addr;
+    int nbanks;
+    target_ulong ram_bases[4];
+    target_ulong ram_sizes[4];
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t bear;
+    uint32_t cfg;
+    uint32_t status;
+    uint32_t rtr;
+    uint32_t pmit;
+    uint32_t bcr[4];
+    uint32_t tr;
+    uint32_t ecccfg;
+    uint32_t eccesr;
+    qemu_irq irq;
+};
+
+enum {
+    SDRAM0_CFGADDR = 0x010,
+    SDRAM0_CFGDATA = 0x011,
+};
+
+static uint32_t sdram_bcr (target_ulong ram_base, target_ulong ram_size)
+{
+    uint32_t bcr;
+
+    switch (ram_size) {
+    case (4 * 1024 * 1024):
+        bcr = 0x00000000;
+        break;
+    case (8 * 1024 * 1024):
+        bcr = 0x00020000;
+        break;
+    case (16 * 1024 * 1024):
+        bcr = 0x00040000;
+        break;
+    case (32 * 1024 * 1024):
+        bcr = 0x00060000;
+        break;
+    case (64 * 1024 * 1024):
+        bcr = 0x00080000;
+        break;
+    case (128 * 1024 * 1024):
+        bcr = 0x000A0000;
+        break;
+    case (256 * 1024 * 1024):
+        bcr = 0x000C0000;
+        break;
+    default:
+        printf("%s: invalid RAM size " TARGET_FMT_ld "\n", __func__, ram_size);
+        return 0x00000000;
+    }
+    bcr |= ram_base & 0xFF800000;
+    bcr |= 1;
+
+    return bcr;
+}
+
+static inline target_ulong sdram_base (uint32_t bcr)
+{
+    return bcr & 0xFF800000;
+}
+
+static target_ulong sdram_size (uint32_t bcr)
+{
+    target_ulong size;
+    int sh;
+
+    sh = (bcr >> 17) & 0x7;
+    if (sh == 7)
+        size = -1;
+    else
+        size = (4 * 1024 * 1024) << sh;
+
+    return size;
+}
+
+static void sdram_set_bcr (uint32_t *bcrp, uint32_t bcr, int enabled)
+{
+    if (*bcrp & 0x00000001) {
+        /* Unmap RAM */
+#ifdef DEBUG_SDRAM
+        printf("%s: unmap RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(*bcrp), sdram_size(*bcrp));
+#endif
+        cpu_register_physical_memory(sdram_base(*bcrp), sdram_size(*bcrp),
+                                     IO_MEM_UNASSIGNED);
+    }
+    *bcrp = bcr & 0xFFDEE001;
+    if (enabled && (bcr & 0x00000001)) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Map RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(bcr), sdram_size(bcr));
+#endif
+        cpu_register_physical_memory(sdram_base(bcr), sdram_size(bcr),
+                                     sdram_base(bcr) | IO_MEM_RAM);
+    }
+}
+
+static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+        if (sdram->ram_sizes[i] != 0) {
+            sdram_set_bcr(&sdram->bcr[i],
+                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
+                          1);
+        } else {
+            sdram_set_bcr(&sdram->bcr[i], 0x00000000, 0);
+        }
+    }
+}
+
+static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
+{
+    int i;
+
+    for (i = 0; i < sdram->nbanks; i++) {
+#ifdef DEBUG_SDRAM
+        printf("%s: Unmap RAM area " ADDRX " " ADDRX "\n", __func__,
+               sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
+#endif
+        cpu_register_physical_memory(sdram_base(sdram->bcr[i]),
+                                     sdram_size(sdram->bcr[i]),
+                                     IO_MEM_UNASSIGNED);
+    }
+}
+
+static target_ulong dcr_read_sdram (void *opaque, int dcrn)
+{
+    ppc4xx_sdram_t *sdram;
+    target_ulong ret;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        ret = sdram->addr;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            ret = sdram->besr0;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            ret = sdram->besr1;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            ret = sdram->bear;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            ret = sdram->cfg;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            ret = sdram->status;
+            break;
+        case 0x30: /* SDRAM_RTR */
+            ret = sdram->rtr;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            ret = sdram->pmit;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            ret = sdram->bcr[0];
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            ret = sdram->bcr[1];
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            ret = sdram->bcr[2];
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            ret = sdram->bcr[3];
+            break;
+        case 0x80: /* SDRAM_TR */
+            ret = -1; /* ? */
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            ret = sdram->ecccfg;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            ret = sdram->eccesr;
+            break;
+        default: /* Error */
+            ret = -1;
+            break;
+        }
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_sdram (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    switch (dcrn) {
+    case SDRAM0_CFGADDR:
+        sdram->addr = val;
+        break;
+    case SDRAM0_CFGDATA:
+        switch (sdram->addr) {
+        case 0x00: /* SDRAM_BESR0 */
+            sdram->besr0 &= ~val;
+            break;
+        case 0x08: /* SDRAM_BESR1 */
+            sdram->besr1 &= ~val;
+            break;
+        case 0x10: /* SDRAM_BEAR */
+            sdram->bear = val;
+            break;
+        case 0x20: /* SDRAM_CFG */
+            val &= 0xFFE00000;
+            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: enable SDRAM controller\n", __func__);
+#endif
+                /* validate all RAM mappings */
+                sdram_map_bcr(sdram);
+                sdram->status &= ~0x80000000;
+            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
+#ifdef DEBUG_SDRAM
+                printf("%s: disable SDRAM controller\n", __func__);
+#endif
+                /* invalidate all RAM mappings */
+                sdram_unmap_bcr(sdram);
+                sdram->status |= 0x80000000;
+            }
+            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
+                sdram->status |= 0x40000000;
+            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
+                sdram->status &= ~0x40000000;
+            sdram->cfg = val;
+            break;
+        case 0x24: /* SDRAM_STATUS */
+            /* Read-only register */
+            break;
+        case 0x30: /* SDRAM_RTR */
+            sdram->rtr = val & 0x3FF80000;
+            break;
+        case 0x34: /* SDRAM_PMIT */
+            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
+            break;
+        case 0x40: /* SDRAM_B0CR */
+            sdram_set_bcr(&sdram->bcr[0], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x44: /* SDRAM_B1CR */
+            sdram_set_bcr(&sdram->bcr[1], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x48: /* SDRAM_B2CR */
+            sdram_set_bcr(&sdram->bcr[2], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x4C: /* SDRAM_B3CR */
+            sdram_set_bcr(&sdram->bcr[3], val, sdram->cfg & 0x80000000);
+            break;
+        case 0x80: /* SDRAM_TR */
+            sdram->tr = val & 0x018FC01F;
+            break;
+        case 0x94: /* SDRAM_ECCCFG */
+            sdram->ecccfg = val & 0x00F00000;
+            break;
+        case 0x98: /* SDRAM_ECCESR */
+            val &= 0xFFF0F000;
+            if (sdram->eccesr == 0 && val != 0)
+                qemu_irq_raise(sdram->irq);
+            else if (sdram->eccesr != 0 && val == 0)
+                qemu_irq_lower(sdram->irq);
+            sdram->eccesr = val;
+            break;
+        default: /* Error */
+            break;
+        }
+        break;
+    }
+}
+
+static void sdram_reset (void *opaque)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = opaque;
+    sdram->addr = 0x00000000;
+    sdram->bear = 0x00000000;
+    sdram->besr0 = 0x00000000; /* No error */
+    sdram->besr1 = 0x00000000; /* No error */
+    sdram->cfg = 0x00000000;
+    sdram->ecccfg = 0x00000000; /* No ECC */
+    sdram->eccesr = 0x00000000; /* No error */
+    sdram->pmit = 0x07C00000;
+    sdram->rtr = 0x05F00000;
+    sdram->tr = 0x00854009;
+    /* We pre-initialize RAM banks */
+    sdram->status = 0x00000000;
+    sdram->cfg = 0x00800000;
+    sdram_unmap_bcr(sdram);
+}
+
+void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
+                        target_ulong *ram_bases, target_ulong *ram_sizes,
+                        int do_init)
+{
+    ppc4xx_sdram_t *sdram;
+
+    sdram = qemu_mallocz(sizeof(ppc4xx_sdram_t));
+    if (sdram != NULL) {
+        sdram->irq = irq;
+        sdram->nbanks = nbanks;
+        memset(sdram->ram_bases, 0, 4 * sizeof(target_ulong));
+        memcpy(sdram->ram_bases, ram_bases, nbanks * sizeof(target_ulong));
+        memset(sdram->ram_sizes, 0, 4 * sizeof(target_ulong));
+        memcpy(sdram->ram_sizes, ram_sizes, nbanks * sizeof(target_ulong));
+        sdram_reset(sdram);
+        qemu_register_reset(&sdram_reset, sdram);
+        ppc_dcr_register(env, SDRAM0_CFGADDR,
+                         sdram, &dcr_read_sdram, &dcr_write_sdram);
+        ppc_dcr_register(env, SDRAM0_CFGDATA,
+                         sdram, &dcr_read_sdram, &dcr_write_sdram);
+        if (do_init)
+            sdram_map_bcr(sdram);
+    }
+}
+
+/*****************************************************************************/
+/* Peripheral controller */
+typedef struct ppc4xx_ebc_t ppc4xx_ebc_t;
+struct ppc4xx_ebc_t {
+    uint32_t addr;
+    uint32_t bcr[8];
+    uint32_t bap[8];
+    uint32_t bear;
+    uint32_t besr0;
+    uint32_t besr1;
+    uint32_t cfg;
+};
+
+enum {
+    EBC0_CFGADDR = 0x012,
+    EBC0_CFGDATA = 0x013,
+};
+
+static target_ulong dcr_read_ebc (void *opaque, int dcrn)
+{
+    ppc4xx_ebc_t *ebc;
+    target_ulong ret;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ret = ebc->addr;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            ret = ebc->bcr[0];
+            break;
+        case 0x01: /* B1CR */
+            ret = ebc->bcr[1];
+            break;
+        case 0x02: /* B2CR */
+            ret = ebc->bcr[2];
+            break;
+        case 0x03: /* B3CR */
+            ret = ebc->bcr[3];
+            break;
+        case 0x04: /* B4CR */
+            ret = ebc->bcr[4];
+            break;
+        case 0x05: /* B5CR */
+            ret = ebc->bcr[5];
+            break;
+        case 0x06: /* B6CR */
+            ret = ebc->bcr[6];
+            break;
+        case 0x07: /* B7CR */
+            ret = ebc->bcr[7];
+            break;
+        case 0x10: /* B0AP */
+            ret = ebc->bap[0];
+            break;
+        case 0x11: /* B1AP */
+            ret = ebc->bap[1];
+            break;
+        case 0x12: /* B2AP */
+            ret = ebc->bap[2];
+            break;
+        case 0x13: /* B3AP */
+            ret = ebc->bap[3];
+            break;
+        case 0x14: /* B4AP */
+            ret = ebc->bap[4];
+            break;
+        case 0x15: /* B5AP */
+            ret = ebc->bap[5];
+            break;
+        case 0x16: /* B6AP */
+            ret = ebc->bap[6];
+            break;
+        case 0x17: /* B7AP */
+            ret = ebc->bap[7];
+            break;
+        case 0x20: /* BEAR */
+            ret = ebc->bear;
+            break;
+        case 0x21: /* BESR0 */
+            ret = ebc->besr0;
+            break;
+        case 0x22: /* BESR1 */
+            ret = ebc->besr1;
+            break;
+        case 0x23: /* CFG */
+            ret = ebc->cfg;
+            break;
+        default:
+            ret = 0x00000000;
+            break;
+        }
+    default:
+        ret = 0x00000000;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ebc (void *opaque, int dcrn, target_ulong val)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = opaque;
+    switch (dcrn) {
+    case EBC0_CFGADDR:
+        ebc->addr = val;
+        break;
+    case EBC0_CFGDATA:
+        switch (ebc->addr) {
+        case 0x00: /* B0CR */
+            break;
+        case 0x01: /* B1CR */
+            break;
+        case 0x02: /* B2CR */
+            break;
+        case 0x03: /* B3CR */
+            break;
+        case 0x04: /* B4CR */
+            break;
+        case 0x05: /* B5CR */
+            break;
+        case 0x06: /* B6CR */
+            break;
+        case 0x07: /* B7CR */
+            break;
+        case 0x10: /* B0AP */
+            break;
+        case 0x11: /* B1AP */
+            break;
+        case 0x12: /* B2AP */
+            break;
+        case 0x13: /* B3AP */
+            break;
+        case 0x14: /* B4AP */
+            break;
+        case 0x15: /* B5AP */
+            break;
+        case 0x16: /* B6AP */
+            break;
+        case 0x17: /* B7AP */
+            break;
+        case 0x20: /* BEAR */
+            break;
+        case 0x21: /* BESR0 */
+            break;
+        case 0x22: /* BESR1 */
+            break;
+        case 0x23: /* CFG */
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ebc_reset (void *opaque)
+{
+    ppc4xx_ebc_t *ebc;
+    int i;
+
+    ebc = opaque;
+    ebc->addr = 0x00000000;
+    ebc->bap[0] = 0x7F8FFE80;
+    ebc->bcr[0] = 0xFFE28000;
+    for (i = 0; i < 8; i++) {
+        ebc->bap[i] = 0x00000000;
+        ebc->bcr[i] = 0x00000000;
+    }
+    ebc->besr0 = 0x00000000;
+    ebc->besr1 = 0x00000000;
+    ebc->cfg = 0x80400000;
+}
+
+void ppc405_ebc_init (CPUState *env)
+{
+    ppc4xx_ebc_t *ebc;
+
+    ebc = qemu_mallocz(sizeof(ppc4xx_ebc_t));
+    if (ebc != NULL) {
+        ebc_reset(ebc);
+        qemu_register_reset(&ebc_reset, ebc);
+        ppc_dcr_register(env, EBC0_CFGADDR,
+                         ebc, &dcr_read_ebc, &dcr_write_ebc);
+        ppc_dcr_register(env, EBC0_CFGDATA,
+                         ebc, &dcr_read_ebc, &dcr_write_ebc);
+    }
+}
+
+/*****************************************************************************/
+/* DMA controller */
+enum {
+    DMA0_CR0 = 0x100,
+    DMA0_CT0 = 0x101,
+    DMA0_DA0 = 0x102,
+    DMA0_SA0 = 0x103,
+    DMA0_SG0 = 0x104,
+    DMA0_CR1 = 0x108,
+    DMA0_CT1 = 0x109,
+    DMA0_DA1 = 0x10A,
+    DMA0_SA1 = 0x10B,
+    DMA0_SG1 = 0x10C,
+    DMA0_CR2 = 0x110,
+    DMA0_CT2 = 0x111,
+    DMA0_DA2 = 0x112,
+    DMA0_SA2 = 0x113,
+    DMA0_SG2 = 0x114,
+    DMA0_CR3 = 0x118,
+    DMA0_CT3 = 0x119,
+    DMA0_DA3 = 0x11A,
+    DMA0_SA3 = 0x11B,
+    DMA0_SG3 = 0x11C,
+    DMA0_SR  = 0x120,
+    DMA0_SGC = 0x123,
+    DMA0_SLP = 0x125,
+    DMA0_POL = 0x126,
+};
+
+typedef struct ppc405_dma_t ppc405_dma_t;
+struct ppc405_dma_t {
+    qemu_irq irqs[4];
+    uint32_t cr[4];
+    uint32_t ct[4];
+    uint32_t da[4];
+    uint32_t sa[4];
+    uint32_t sg[4];
+    uint32_t sr;
+    uint32_t sgc;
+    uint32_t slp;
+    uint32_t pol;
+};
+
+static target_ulong dcr_read_dma (void *opaque, int dcrn)
+{
+    ppc405_dma_t *dma;
+
+    dma = opaque;
+
+    return 0;
+}
+
+static void dcr_write_dma (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405_dma_t *dma;
+
+    dma = opaque;
+}
+
+static void ppc405_dma_reset (void *opaque)
+{
+    ppc405_dma_t *dma;
+    int i;
+
+    dma = opaque;
+    for (i = 0; i < 4; i++) {
+        dma->cr[i] = 0x00000000;
+        dma->ct[i] = 0x00000000;
+        dma->da[i] = 0x00000000;
+        dma->sa[i] = 0x00000000;
+        dma->sg[i] = 0x00000000;
+    }
+    dma->sr = 0x00000000;
+    dma->sgc = 0x00000000;
+    dma->slp = 0x7C000000;
+    dma->pol = 0x00000000;
+}
+
+void ppc405_dma_init (CPUState *env, qemu_irq irqs[4])
+{
+    ppc405_dma_t *dma;
+
+    dma = qemu_mallocz(sizeof(ppc405_dma_t));
+    if (dma != NULL) {
+        memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq));
+        ppc405_dma_reset(dma);
+        qemu_register_reset(&ppc405_dma_reset, dma);
+        ppc_dcr_register(env, DMA0_CR0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG0,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG1,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG2,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CR3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_CT3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_DA3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SA3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SG3,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SR,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SGC,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_SLP,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+        ppc_dcr_register(env, DMA0_POL,
+                         dma, &dcr_read_dma, &dcr_write_dma);
+    }
+}
+
+/*****************************************************************************/
+/* GPIO */
+typedef struct ppc405_gpio_t ppc405_gpio_t;
+struct ppc405_gpio_t {
+    target_phys_addr_t base;
+    uint32_t or;
+    uint32_t tcr;
+    uint32_t osrh;
+    uint32_t osrl;
+    uint32_t tsrh;
+    uint32_t tsrl;
+    uint32_t odr;
+    uint32_t ir;
+    uint32_t rr1;
+    uint32_t isr1h;
+    uint32_t isr1l;
+};
+
+static uint32_t ppc405_gpio_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writeb (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readw (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writew (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static uint32_t ppc405_gpio_readl (void *opaque, target_phys_addr_t addr)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+
+    return 0;
+}
+
+static void ppc405_gpio_writel (void *opaque,
+                                target_phys_addr_t addr, uint32_t value)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+#ifdef DEBUG_GPIO
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+}
+
+static CPUReadMemoryFunc *ppc405_gpio_read[] = {
+    &ppc405_gpio_readb,
+    &ppc405_gpio_readw,
+    &ppc405_gpio_readl,
+};
+
+static CPUWriteMemoryFunc *ppc405_gpio_write[] = {
+    &ppc405_gpio_writeb,
+    &ppc405_gpio_writew,
+    &ppc405_gpio_writel,
+};
+
+static void ppc405_gpio_reset (void *opaque)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = opaque;
+}
+
+void ppc405_gpio_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                       target_phys_addr_t offset)
+{
+    ppc405_gpio_t *gpio;
+
+    gpio = qemu_mallocz(sizeof(ppc405_gpio_t));
+    if (gpio != NULL) {
+        gpio->base = offset;
+        ppc405_gpio_reset(gpio);
+        qemu_register_reset(&ppc405_gpio_reset, gpio);
+#ifdef DEBUG_GPIO
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x038,
+                             ppc405_gpio_read, ppc405_gpio_write, gpio);
+    }
+}
+
+/*****************************************************************************/
+/* Serial ports */
+static CPUReadMemoryFunc *serial_mm_read[] = {
+    &serial_mm_readb,
+    &serial_mm_readw,
+    &serial_mm_readl,
+};
+
+static CPUWriteMemoryFunc *serial_mm_write[] = {
+    &serial_mm_writeb,
+    &serial_mm_writew,
+    &serial_mm_writel,
+};
+
+void ppc405_serial_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                         target_phys_addr_t offset, qemu_irq irq,
+                         CharDriverState *chr)
+{
+    void *serial;
+
+#ifdef DEBUG_SERIAL
+    printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+    serial = serial_mm_init(offset, 0, irq, chr, 0);
+    ppc4xx_mmio_register(env, mmio, offset, 0x008,
+                         serial_mm_read, serial_mm_write, serial);
+}
+
+/*****************************************************************************/
+/* On Chip Memory */
+enum {
+    OCM0_ISARC   = 0x018,
+    OCM0_ISACNTL = 0x019,
+    OCM0_DSARC   = 0x01A,
+    OCM0_DSACNTL = 0x01B,
+};
+
+typedef struct ppc405_ocm_t ppc405_ocm_t;
+struct ppc405_ocm_t {
+    target_ulong offset;
+    uint32_t isarc;
+    uint32_t isacntl;
+    uint32_t dsarc;
+    uint32_t dsacntl;
+};
+
+static void ocm_update_mappings (ppc405_ocm_t *ocm,
+                                 uint32_t isarc, uint32_t isacntl,
+                                 uint32_t dsarc, uint32_t dsacntl)
+{
+#ifdef DEBUG_OCM
+    printf("OCM update ISA %08x %08x (%08x %08x) DSA %08x %08x (%08x %08x)\n",
+           isarc, isacntl, dsarc, dsacntl,
+           ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl);
+#endif
+    if (ocm->isarc != isarc ||
+        (ocm->isacntl & 0x80000000) != (isacntl & 0x80000000)) {
+        if (ocm->isacntl & 0x80000000) {
+            /* Unmap previously assigned memory region */
+            printf("OCM unmap ISA %08x\n", ocm->isarc);
+            cpu_register_physical_memory(ocm->isarc, 0x04000000,
+                                         IO_MEM_UNASSIGNED);
+        }
+        if (isacntl & 0x80000000) {
+            /* Map new instruction memory region */
+#ifdef DEBUG_OCM
+            printf("OCM map ISA %08x\n", isarc);
+#endif
+            cpu_register_physical_memory(isarc, 0x04000000,
+                                         ocm->offset | IO_MEM_RAM);
+        }
+    }
+    if (ocm->dsarc != dsarc ||
+        (ocm->dsacntl & 0x80000000) != (dsacntl & 0x80000000)) {
+        if (ocm->dsacntl & 0x80000000) {
+            /* Beware not to unmap the region we just mapped */
+            if (!(isacntl & 0x80000000) || ocm->dsarc != isarc) {
+                /* Unmap previously assigned memory region */
+#ifdef DEBUG_OCM
+                printf("OCM unmap DSA %08x\n", ocm->dsarc);
+#endif
+                cpu_register_physical_memory(ocm->dsarc, 0x04000000,
+                                             IO_MEM_UNASSIGNED);
+            }
+        }
+        if (dsacntl & 0x80000000) {
+            /* Beware not to remap the region we just mapped */
+            if (!(isacntl & 0x80000000) || dsarc != isarc) {
+                /* Map new data memory region */
+#ifdef DEBUG_OCM
+                printf("OCM map DSA %08x\n", dsarc);
+#endif
+                cpu_register_physical_memory(dsarc, 0x04000000,
+                                             ocm->offset | IO_MEM_RAM);
+            }
+        }
+    }
+}
+
+static target_ulong dcr_read_ocm (void *opaque, int dcrn)
+{
+    ppc405_ocm_t *ocm;
+    target_ulong ret;
+
+    ocm = opaque;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        ret = ocm->isarc;
+        break;
+    case OCM0_ISACNTL:
+        ret = ocm->isacntl;
+        break;
+    case OCM0_DSARC:
+        ret = ocm->dsarc;
+        break;
+    case OCM0_DSACNTL:
+        ret = ocm->dsacntl;
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_ocm (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = ocm->isarc;
+    dsarc = ocm->dsarc;
+    isacntl = ocm->isacntl;
+    dsacntl = ocm->dsacntl;
+    switch (dcrn) {
+    case OCM0_ISARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_ISACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    case OCM0_DSARC:
+        isarc = val & 0xFC000000;
+        break;
+    case OCM0_DSACNTL:
+        isacntl = val & 0xC0000000;
+        break;
+    }
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+static void ocm_reset (void *opaque)
+{
+    ppc405_ocm_t *ocm;
+    uint32_t isarc, dsarc, isacntl, dsacntl;
+
+    ocm = opaque;
+    isarc = 0x00000000;
+    isacntl = 0x00000000;
+    dsarc = 0x00000000;
+    dsacntl = 0x00000000;
+    ocm_update_mappings(ocm, isarc, isacntl, dsarc, dsacntl);
+    ocm->isarc = isarc;
+    ocm->dsarc = dsarc;
+    ocm->isacntl = isacntl;
+    ocm->dsacntl = dsacntl;
+}
+
+void ppc405_ocm_init (CPUState *env, unsigned long offset)
+{
+    ppc405_ocm_t *ocm;
+
+    ocm = qemu_mallocz(sizeof(ppc405_ocm_t));
+    if (ocm != NULL) {
+        ocm->offset = offset;
+        ocm_reset(ocm);
+        qemu_register_reset(&ocm_reset, ocm);
+        ppc_dcr_register(env, OCM0_ISARC,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_ISACNTL,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_DSARC,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+        ppc_dcr_register(env, OCM0_DSACNTL,
+                         ocm, &dcr_read_ocm, &dcr_write_ocm);
+    }
+}
+
+/*****************************************************************************/
+/* I2C controller */
+typedef struct ppc4xx_i2c_t ppc4xx_i2c_t;
+struct ppc4xx_i2c_t {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    uint8_t mdata;
+    uint8_t lmadr;
+    uint8_t hmadr;
+    uint8_t cntl;
+    uint8_t mdcntl;
+    uint8_t sts;
+    uint8_t extsts;
+    uint8_t sdata;
+    uint8_t lsadr;
+    uint8_t hsadr;
+    uint8_t clkdiv;
+    uint8_t intrmsk;
+    uint8_t xfrcnt;
+    uint8_t xtcntlss;
+    uint8_t directcntl;
+};
+
+static uint32_t ppc4xx_i2c_readb (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_i2c_t *i2c;
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    i2c = opaque;
+    switch (addr - i2c->base) {
+    case 0x00:
+        //        i2c_readbyte(&i2c->mdata);
+        ret = i2c->mdata;
+        break;
+    case 0x02:
+        ret = i2c->sdata;
+        break;
+    case 0x04:
+        ret = i2c->lmadr;
+        break;
+    case 0x05:
+        ret = i2c->hmadr;
+        break;
+    case 0x06:
+        ret = i2c->cntl;
+        break;
+    case 0x07:
+        ret = i2c->mdcntl;
+        break;
+    case 0x08:
+        ret = i2c->sts;
+        break;
+    case 0x09:
+        ret = i2c->extsts;
+        break;
+    case 0x0A:
+        ret = i2c->lsadr;
+        break;
+    case 0x0B:
+        ret = i2c->hsadr;
+        break;
+    case 0x0C:
+        ret = i2c->clkdiv;
+        break;
+    case 0x0D:
+        ret = i2c->intrmsk;
+        break;
+    case 0x0E:
+        ret = i2c->xfrcnt;
+        break;
+    case 0x0F:
+        ret = i2c->xtcntlss;
+        break;
+    case 0x10:
+        ret = i2c->directcntl;
+        break;
+    default:
+        ret = 0x00;
+        break;
+    }
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " %02x\n", __func__, addr, ret);
+#endif
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_i2c_t *i2c;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    i2c = opaque;
+    switch (addr - i2c->base) {
+    case 0x00:
+        i2c->mdata = value;
+        //        i2c_sendbyte(&i2c->mdata);
+        break;
+    case 0x02:
+        i2c->sdata = value;
+        break;
+    case 0x04:
+        i2c->lmadr = value;
+        break;
+    case 0x05:
+        i2c->hmadr = value;
+        break;
+    case 0x06:
+        i2c->cntl = value;
+        break;
+    case 0x07:
+        i2c->mdcntl = value & 0xDF;
+        break;
+    case 0x08:
+        i2c->sts &= ~(value & 0x0A);
+        break;
+    case 0x09:
+        i2c->extsts &= ~(value & 0x8F);
+        break;
+    case 0x0A:
+        i2c->lsadr = value;
+        break;
+    case 0x0B:
+        i2c->hsadr = value;
+        break;
+    case 0x0C:
+        i2c->clkdiv = value;
+        break;
+    case 0x0D:
+        i2c->intrmsk = value;
+        break;
+    case 0x0E:
+        i2c->xfrcnt = value & 0x77;
+        break;
+    case 0x0F:
+        i2c->xtcntlss = value;
+        break;
+    case 0x10:
+        i2c->directcntl = value & 0x7;
+        break;
+    }
+}
+
+static uint32_t ppc4xx_i2c_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value);
+}
+
+static uint32_t ppc4xx_i2c_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    ret = ppc4xx_i2c_readb(opaque, addr) << 24;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 1) << 16;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 2) << 8;
+    ret |= ppc4xx_i2c_readb(opaque, addr + 3);
+
+    return ret;
+}
+
+static void ppc4xx_i2c_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    ppc4xx_i2c_writeb(opaque, addr, value >> 24);
+    ppc4xx_i2c_writeb(opaque, addr + 1, value >> 16);
+    ppc4xx_i2c_writeb(opaque, addr + 2, value >> 8);
+    ppc4xx_i2c_writeb(opaque, addr + 3, value);
+}
+
+static CPUReadMemoryFunc *i2c_read[] = {
+    &ppc4xx_i2c_readb,
+    &ppc4xx_i2c_readw,
+    &ppc4xx_i2c_readl,
+};
+
+static CPUWriteMemoryFunc *i2c_write[] = {
+    &ppc4xx_i2c_writeb,
+    &ppc4xx_i2c_writew,
+    &ppc4xx_i2c_writel,
+};
+
+static void ppc4xx_i2c_reset (void *opaque)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = opaque;
+    i2c->mdata = 0x00;
+    i2c->sdata = 0x00;
+    i2c->cntl = 0x00;
+    i2c->mdcntl = 0x00;
+    i2c->sts = 0x00;
+    i2c->extsts = 0x00;
+    i2c->clkdiv = 0x00;
+    i2c->xfrcnt = 0x00;
+    i2c->directcntl = 0x0F;
+}
+
+void ppc405_i2c_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irq)
+{
+    ppc4xx_i2c_t *i2c;
+
+    i2c = qemu_mallocz(sizeof(ppc4xx_i2c_t));
+    if (i2c != NULL) {
+        i2c->base = offset;
+        i2c->irq = irq;
+        ppc4xx_i2c_reset(i2c);
+#ifdef DEBUG_I2C
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x011,
+                             i2c_read, i2c_write, i2c);
+        qemu_register_reset(ppc4xx_i2c_reset, i2c);
+    }
+}
+
+/*****************************************************************************/
+/* General purpose timers */
+typedef struct ppc4xx_gpt_t ppc4xx_gpt_t;
+struct ppc4xx_gpt_t {
+    target_phys_addr_t base;
+    int64_t tb_offset;
+    uint32_t tb_freq;
+    struct QEMUTimer *timer;
+    qemu_irq irqs[5];
+    uint32_t oe;
+    uint32_t ol;
+    uint32_t im;
+    uint32_t is;
+    uint32_t ie;
+    uint32_t comp[5];
+    uint32_t mask[5];
+};
+
+static uint32_t ppc4xx_gpt_readb (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writeb (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static uint32_t ppc4xx_gpt_readw (void *opaque, target_phys_addr_t addr)
+{
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    /* XXX: generate a bus fault */
+    return -1;
+}
+
+static void ppc4xx_gpt_writew (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    /* XXX: generate a bus fault */
+}
+
+static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
+{
+    /* XXX: TODO */
+    return 0;
+}
+
+static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level)
+{
+    /* XXX: TODO */
+}
+
+static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x80000000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->oe & mask) {
+            /* Output is enabled */
+            if (ppc4xx_gpt_compare(gpt, i)) {
+                /* Comparison is OK */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask);
+            } else {
+                /* Comparison is KO */
+                ppc4xx_gpt_set_output(gpt, i, gpt->ol & mask ? 0 : 1);
+            }
+        }
+        mask = mask >> 1;
+    }
+        
+}
+
+static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt)
+{
+    uint32_t mask;
+    int i;
+
+    mask = 0x00008000;
+    for (i = 0; i < 5; i++) {
+        if (gpt->is & gpt->im & mask)
+            qemu_irq_raise(gpt->irqs[i]);
+        else
+            qemu_irq_lower(gpt->irqs[i]);
+        mask = mask >> 1;
+    }
+        
+}
+
+static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
+{
+    /* XXX: TODO */
+}
+
+static uint32_t ppc4xx_gpt_readl (void *opaque, target_phys_addr_t addr)
+{
+    ppc4xx_gpt_t *gpt;
+    uint32_t ret;
+    int idx;
+
+#ifdef DEBUG_GPT
+    printf("%s: addr " PADDRX "\n", __func__, addr);
+#endif
+    gpt = opaque;
+    switch (addr - gpt->base) {
+    case 0x00:
+        /* Time base counter */
+        ret = muldiv64(qemu_get_clock(vm_clock) + gpt->tb_offset,
+                       gpt->tb_freq, ticks_per_sec);
+        break;
+    case 0x10:
+        /* Output enable */
+        ret = gpt->oe;
+        break;
+    case 0x14:
+        /* Output level */
+        ret = gpt->ol;
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        ret = gpt->im;
+        break;
+    case 0x1C:
+    case 0x20:
+        /* Interrupt status */
+        ret = gpt->is;
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        ret = gpt->ie;
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = ((addr - gpt->base) - 0x80) >> 2;
+        ret = gpt->comp[idx];
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = ((addr - gpt->base) - 0xC0) >> 2;
+        ret = gpt->mask[idx];
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void ppc4xx_gpt_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    ppc4xx_gpt_t *gpt;
+    int idx;
+
+#ifdef DEBUG_I2C
+    printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
+#endif
+    gpt = opaque;
+    switch (addr - gpt->base) {
+    case 0x00:
+        /* Time base counter */
+        gpt->tb_offset = muldiv64(value, ticks_per_sec, gpt->tb_freq)
+            - qemu_get_clock(vm_clock);
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0x10:
+        /* Output enable */
+        gpt->oe = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x14:
+        /* Output level */
+        gpt->ol = value & 0xF8000000;
+        ppc4xx_gpt_set_outputs(gpt);
+        break;
+    case 0x18:
+        /* Interrupt mask */
+        gpt->im = value & 0x0000F800;
+        break;
+    case 0x1C:
+        /* Interrupt status set */
+        gpt->is |= value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x20:
+        /* Interrupt status clear */
+        gpt->is &= ~(value & 0x0000F800);
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x24:
+        /* Interrupt enable */
+        gpt->ie = value & 0x0000F800;
+        ppc4xx_gpt_set_irqs(gpt);
+        break;
+    case 0x80 ... 0x90:
+        /* Compare timer */
+        idx = ((addr - gpt->base) - 0x80) >> 2;
+        gpt->comp[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    case 0xC0 ... 0xD0:
+        /* Compare mask */
+        idx = ((addr - gpt->base) - 0xC0) >> 2;
+        gpt->mask[idx] = value & 0xF8000000;
+        ppc4xx_gpt_compute_timer(gpt);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *gpt_read[] = {
+    &ppc4xx_gpt_readb,
+    &ppc4xx_gpt_readw,
+    &ppc4xx_gpt_readl,
+};
+
+static CPUWriteMemoryFunc *gpt_write[] = {
+    &ppc4xx_gpt_writeb,
+    &ppc4xx_gpt_writew,
+    &ppc4xx_gpt_writel,
+};
+
+static void ppc4xx_gpt_cb (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+
+    gpt = opaque;
+    ppc4xx_gpt_set_irqs(gpt);
+    ppc4xx_gpt_set_outputs(gpt);
+    ppc4xx_gpt_compute_timer(gpt);
+}
+
+static void ppc4xx_gpt_reset (void *opaque)
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = opaque;
+    qemu_del_timer(gpt->timer);
+    gpt->oe = 0x00000000;
+    gpt->ol = 0x00000000;
+    gpt->im = 0x00000000;
+    gpt->is = 0x00000000;
+    gpt->ie = 0x00000000;
+    for (i = 0; i < 5; i++) {
+        gpt->comp[i] = 0x00000000;
+        gpt->mask[i] = 0x00000000;
+    }
+}
+
+void ppc4xx_gpt_init (CPUState *env, ppc4xx_mmio_t *mmio,
+                      target_phys_addr_t offset, qemu_irq irqs[5])
+{
+    ppc4xx_gpt_t *gpt;
+    int i;
+
+    gpt = qemu_mallocz(sizeof(ppc4xx_gpt_t));
+    if (gpt != NULL) {
+        gpt->base = offset;
+        for (i = 0; i < 5; i++)
+            gpt->irqs[i] = irqs[i];
+        gpt->timer = qemu_new_timer(vm_clock, &ppc4xx_gpt_cb, gpt);
+        ppc4xx_gpt_reset(gpt);
+#ifdef DEBUG_GPT
+        printf("%s: offset=" PADDRX "\n", __func__, offset);
+#endif
+        ppc4xx_mmio_register(env, mmio, offset, 0x0D4,
+                             gpt_read, gpt_write, gpt);
+        qemu_register_reset(ppc4xx_gpt_reset, gpt);
+    }
+}
+
+/*****************************************************************************/
+/* MAL */
+enum {
+    MAL0_CFG      = 0x180,
+    MAL0_ESR      = 0x181,
+    MAL0_IER      = 0x182,
+    MAL0_TXCASR   = 0x184,
+    MAL0_TXCARR   = 0x185,
+    MAL0_TXEOBISR = 0x186,
+    MAL0_TXDEIR   = 0x187,
+    MAL0_RXCASR   = 0x190,
+    MAL0_RXCARR   = 0x191,
+    MAL0_RXEOBISR = 0x192,
+    MAL0_RXDEIR   = 0x193,
+    MAL0_TXCTP0R  = 0x1A0,
+    MAL0_TXCTP1R  = 0x1A1,
+    MAL0_TXCTP2R  = 0x1A2,
+    MAL0_TXCTP3R  = 0x1A3,
+    MAL0_RXCTP0R  = 0x1C0,
+    MAL0_RXCTP1R  = 0x1C1,
+    MAL0_RCBS0    = 0x1E0,
+    MAL0_RCBS1    = 0x1E1,
+};
+
+typedef struct ppc40x_mal_t ppc40x_mal_t;
+struct ppc40x_mal_t {
+    qemu_irq irqs[4];
+    uint32_t cfg;
+    uint32_t esr;
+    uint32_t ier;
+    uint32_t txcasr;
+    uint32_t txcarr;
+    uint32_t txeobisr;
+    uint32_t txdeir;
+    uint32_t rxcasr;
+    uint32_t rxcarr;
+    uint32_t rxeobisr;
+    uint32_t rxdeir;
+    uint32_t txctpr[4];
+    uint32_t rxctpr[2];
+    uint32_t rcbs[2];
+};
+
+static void ppc40x_mal_reset (void *opaque);
+
+static target_ulong dcr_read_mal (void *opaque, int dcrn)
+{
+    ppc40x_mal_t *mal;
+    target_ulong ret;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        ret = mal->cfg;
+        break;
+    case MAL0_ESR:
+        ret = mal->esr;
+        break;
+    case MAL0_IER:
+        ret = mal->ier;
+        break;
+    case MAL0_TXCASR:
+        ret = mal->txcasr;
+        break;
+    case MAL0_TXCARR:
+        ret = mal->txcarr;
+        break;
+    case MAL0_TXEOBISR:
+        ret = mal->txeobisr;
+        break;
+    case MAL0_TXDEIR:
+        ret = mal->txdeir;
+        break;
+    case MAL0_RXCASR:
+        ret = mal->rxcasr;
+        break;
+    case MAL0_RXCARR:
+        ret = mal->rxcarr;
+        break;
+    case MAL0_RXEOBISR:
+        ret = mal->rxeobisr;
+        break;
+    case MAL0_RXDEIR:
+        ret = mal->rxdeir;
+        break;
+    case MAL0_TXCTP0R:
+        ret = mal->txctpr[0];
+        break;
+    case MAL0_TXCTP1R:
+        ret = mal->txctpr[1];
+        break;
+    case MAL0_TXCTP2R:
+        ret = mal->txctpr[2];
+        break;
+    case MAL0_TXCTP3R:
+        ret = mal->txctpr[3];
+        break;
+    case MAL0_RXCTP0R:
+        ret = mal->rxctpr[0];
+        break;
+    case MAL0_RXCTP1R:
+        ret = mal->rxctpr[1];
+        break;
+    case MAL0_RCBS0:
+        ret = mal->rcbs[0];
+        break;
+    case MAL0_RCBS1:
+        ret = mal->rcbs[1];
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_mal (void *opaque, int dcrn, target_ulong val)
+{
+    ppc40x_mal_t *mal;
+    int idx;
+
+    mal = opaque;
+    switch (dcrn) {
+    case MAL0_CFG:
+        if (val & 0x80000000)
+            ppc40x_mal_reset(mal);
+        mal->cfg = val & 0x00FFC087;
+        break;
+    case MAL0_ESR:
+        /* Read/clear */
+        mal->esr &= ~val;
+        break;
+    case MAL0_IER:
+        mal->ier = val & 0x0000001F;
+        break;
+    case MAL0_TXCASR:
+        mal->txcasr = val & 0xF0000000;
+        break;
+    case MAL0_TXCARR:
+        mal->txcarr = val & 0xF0000000;
+        break;
+    case MAL0_TXEOBISR:
+        /* Read/clear */
+        mal->txeobisr &= ~val;
+        break;
+    case MAL0_TXDEIR:
+        /* Read/clear */
+        mal->txdeir &= ~val;
+        break;
+    case MAL0_RXCASR:
+        mal->rxcasr = val & 0xC0000000;
+        break;
+    case MAL0_RXCARR:
+        mal->rxcarr = val & 0xC0000000;
+        break;
+    case MAL0_RXEOBISR:
+        /* Read/clear */
+        mal->rxeobisr &= ~val;
+        break;
+    case MAL0_RXDEIR:
+        /* Read/clear */
+        mal->rxdeir &= ~val;
+        break;
+    case MAL0_TXCTP0R:
+        idx = 0;
+        goto update_tx_ptr;
+    case MAL0_TXCTP1R:
+        idx = 1;
+        goto update_tx_ptr;
+    case MAL0_TXCTP2R:
+        idx = 2;
+        goto update_tx_ptr;
+    case MAL0_TXCTP3R:
+        idx = 3;
+    update_tx_ptr:
+        mal->txctpr[idx] = val;
+        break;
+    case MAL0_RXCTP0R:
+        idx = 0;
+        goto update_rx_ptr;
+    case MAL0_RXCTP1R:
+        idx = 1;
+    update_rx_ptr:
+        mal->rxctpr[idx] = val;
+        break;
+    case MAL0_RCBS0:
+        idx = 0;
+        goto update_rx_size;
+    case MAL0_RCBS1:
+        idx = 1;
+    update_rx_size:
+        mal->rcbs[idx] = val & 0x000000FF;
+        break;
+    }
+}
+
+static void ppc40x_mal_reset (void *opaque)
+{
+    ppc40x_mal_t *mal;
+
+    mal = opaque;
+    mal->cfg = 0x0007C000;
+    mal->esr = 0x00000000;
+    mal->ier = 0x00000000;
+    mal->rxcasr = 0x00000000;
+    mal->rxdeir = 0x00000000;
+    mal->rxeobisr = 0x00000000;
+    mal->txcasr = 0x00000000;
+    mal->txdeir = 0x00000000;
+    mal->txeobisr = 0x00000000;
+}
+
+void ppc405_mal_init (CPUState *env, qemu_irq irqs[4])
+{
+    ppc40x_mal_t *mal;
+    int i;
+
+    mal = qemu_mallocz(sizeof(ppc40x_mal_t));
+    if (mal != NULL) {
+        for (i = 0; i < 4; i++)
+            mal->irqs[i] = irqs[i];
+        ppc40x_mal_reset(mal);
+        qemu_register_reset(&ppc40x_mal_reset, mal);
+        ppc_dcr_register(env, MAL0_CFG,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_ESR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_IER,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCASR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCARR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXEOBISR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXDEIR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCASR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCARR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXEOBISR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXDEIR,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP0R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP1R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP2R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_TXCTP3R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCTP0R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RXCTP1R,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RCBS0,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+        ppc_dcr_register(env, MAL0_RCBS1,
+                         mal, &dcr_read_mal, &dcr_write_mal);
+    }
+}
+
+/*****************************************************************************/
+/* SPR */
+void ppc40x_core_reset (CPUState *env)
+{
+    target_ulong dbsr;
+
+    printf("Reset PowerPC core\n");
+    cpu_ppc_reset(env);
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000100;
+    env->spr[SPR_40x_DBSR] = dbsr;
+    cpu_loop_exit();
+}
+
+void ppc40x_chip_reset (CPUState *env)
+{
+    target_ulong dbsr;
+
+    printf("Reset PowerPC chip\n");
+    cpu_ppc_reset(env);
+    /* XXX: TODO reset all internal peripherals */
+    dbsr = env->spr[SPR_40x_DBSR];
+    dbsr &= ~0x00000300;
+    dbsr |= 0x00000200;
+    env->spr[SPR_40x_DBSR] = dbsr;
+    cpu_loop_exit();
+}
+
+void ppc40x_system_reset (CPUState *env)
+{
+    printf("Reset PowerPC system\n");
+    qemu_system_reset_request();
+}
+
+void store_40x_dbcr0 (CPUState *env, uint32_t val)
+{
+    switch ((val >> 28) & 0x3) {
+    case 0x0:
+        /* No action */
+        break;
+    case 0x1:
+        /* Core reset */
+        ppc40x_core_reset(env);
+        break;
+    case 0x2:
+        /* Chip reset */
+        ppc40x_chip_reset(env);
+        break;
+    case 0x3:
+        /* System reset */
+        ppc40x_system_reset(env);
+        break;
+    }
+}
+
+/*****************************************************************************/
+/* PowerPC 405CR */
+enum {
+    PPC405CR_CPC0_PLLMR  = 0x0B0,
+    PPC405CR_CPC0_CR0    = 0x0B1,
+    PPC405CR_CPC0_CR1    = 0x0B2,
+    PPC405CR_CPC0_PSR    = 0x0B4,
+    PPC405CR_CPC0_JTAGID = 0x0B5,
+    PPC405CR_CPC0_ER     = 0x0B9,
+    PPC405CR_CPC0_FR     = 0x0BA,
+    PPC405CR_CPC0_SR     = 0x0BB,
+};
+
+enum {
+    PPC405CR_CPU_CLK   = 0,
+    PPC405CR_TMR_CLK   = 1,
+    PPC405CR_PLB_CLK   = 2,
+    PPC405CR_SDRAM_CLK = 3,
+    PPC405CR_OPB_CLK   = 4,
+    PPC405CR_EXT_CLK   = 5,
+    PPC405CR_UART_CLK  = 6,
+    PPC405CR_CLK_NB    = 7,
+};
+
+typedef struct ppc405cr_cpc_t ppc405cr_cpc_t;
+struct ppc405cr_cpc_t {
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    uint32_t sysclk;
+    uint32_t psr;
+    uint32_t cr0;
+    uint32_t cr1;
+    uint32_t jtagid;
+    uint32_t pllmr;
+    uint32_t er;
+    uint32_t fr;
+};
+
+static void ppc405cr_clk_setup (ppc405cr_cpc_t *cpc)
+{
+    uint64_t VCO_out, PLL_out;
+    uint32_t CPU_clk, TMR_clk, SDRAM_clk, PLB_clk, OPB_clk, EXT_clk, UART_clk;
+    int M, D0, D1, D2;
+
+    D0 = ((cpc->pllmr >> 26) & 0x3) + 1; /* CBDV */
+    if (cpc->pllmr & 0x80000000) {
+        D1 = (((cpc->pllmr >> 20) - 1) & 0xF) + 1; /* FBDV */
+        D2 = 8 - ((cpc->pllmr >> 16) & 0x7); /* FWDVA */
+        M = D0 * D1 * D2;
+        VCO_out = cpc->sysclk * M;
+        if (VCO_out < 400000000 || VCO_out > 800000000) {
+            /* PLL cannot lock */
+            cpc->pllmr &= ~0x80000000;
+            goto bypass_pll;
+        }
+        PLL_out = VCO_out / D2;
+    } else {
+        /* Bypass PLL */
+    bypass_pll:
+        M = D0;
+        PLL_out = cpc->sysclk * M;
+    }
+    CPU_clk = PLL_out;
+    if (cpc->cr1 & 0x00800000)
+        TMR_clk = cpc->sysclk; /* Should have a separate clock */
+    else
+        TMR_clk = CPU_clk;
+    PLB_clk = CPU_clk / D0;
+    SDRAM_clk = PLB_clk;
+    D0 = ((cpc->pllmr >> 10) & 0x3) + 1;
+    OPB_clk = PLB_clk / D0;
+    D0 = ((cpc->pllmr >> 24) & 0x3) + 2;
+    EXT_clk = PLB_clk / D0;
+    D0 = ((cpc->cr0 >> 1) & 0x1F) + 1;
+    UART_clk = CPU_clk / D0;
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405CR_CPU_CLK], CPU_clk);
+    /* Setup time-base clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_TMR_CLK], TMR_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_PLB_CLK], PLB_clk);
+    /* Setup SDRAM clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_SDRAM_CLK], SDRAM_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_EXT_CLK], EXT_clk);
+    /* Setup UART clock */
+    clk_setup(&cpc->clk_setup[PPC405CR_UART_CLK], UART_clk);
+}
+
+static target_ulong dcr_read_crcpc (void *opaque, int dcrn)
+{
+    ppc405cr_cpc_t *cpc;
+    target_ulong ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        ret = cpc->pllmr;
+        break;
+    case PPC405CR_CPC0_CR0:
+        ret = cpc->cr0;
+        break;
+    case PPC405CR_CPC0_CR1:
+        ret = cpc->cr1;
+        break;
+    case PPC405CR_CPC0_PSR:
+        ret = cpc->psr;
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405CR_CPC0_ER:
+        ret = cpc->er;
+        break;
+    case PPC405CR_CPC0_FR:
+        ret = cpc->fr;
+        break;
+    case PPC405CR_CPC0_SR:
+        ret = ~(cpc->er | cpc->fr) & 0xFFFF0000;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_crcpc (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405CR_CPC0_PLLMR:
+        cpc->pllmr = val & 0xFFF77C3F;
+        break;
+    case PPC405CR_CPC0_CR0:
+        cpc->cr0 = val & 0x0FFFFFFE;
+        break;
+    case PPC405CR_CPC0_CR1:
+        cpc->cr1 = val & 0x00800000;
+        break;
+    case PPC405CR_CPC0_PSR:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405CR_CPC0_ER:
+        cpc->er = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_FR:
+        cpc->fr = val & 0xBFFC0000;
+        break;
+    case PPC405CR_CPC0_SR:
+        /* Read-only */
+        break;
+    }
+}
+
+static void ppc405cr_cpc_reset (void *opaque)
+{
+    ppc405cr_cpc_t *cpc;
+    int D;
+
+    cpc = opaque;
+    /* Compute PLLMR value from PSR settings */
+    cpc->pllmr = 0x80000000;
+    /* PFWD */
+    switch ((cpc->psr >> 30) & 3) {
+    case 0:
+        /* Bypass */
+        cpc->pllmr &= ~0x80000000;
+        break;
+    case 1:
+        /* Divide by 3 */
+        cpc->pllmr |= 5 << 16;
+        break;
+    case 2:
+        /* Divide by 4 */
+        cpc->pllmr |= 4 << 16;
+        break;
+    case 3:
+        /* Divide by 6 */
+        cpc->pllmr |= 2 << 16;
+        break;
+    }
+    /* PFBD */
+    D = (cpc->psr >> 28) & 3;
+    cpc->pllmr |= (D + 1) << 20;
+    /* PT   */
+    D = (cpc->psr >> 25) & 7;
+    switch (D) {
+    case 0x2:
+        cpc->pllmr |= 0x13;
+        break;
+    case 0x4:
+        cpc->pllmr |= 0x15;
+        break;
+    case 0x5:
+        cpc->pllmr |= 0x16;
+        break;
+    default:
+        break;
+    }
+    /* PDC  */
+    D = (cpc->psr >> 23) & 3;
+    cpc->pllmr |= D << 26;
+    /* ODP  */
+    D = (cpc->psr >> 21) & 3;
+    cpc->pllmr |= D << 10;
+    /* EBPD */
+    D = (cpc->psr >> 17) & 3;
+    cpc->pllmr |= D << 24;
+    cpc->cr0 = 0x0000003C;
+    cpc->cr1 = 0x2B0D8800;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    ppc405cr_clk_setup(cpc);
+}
+
+static void ppc405cr_clk_init (ppc405cr_cpc_t *cpc)
+{
+    int D;
+
+    /* XXX: this should be read from IO pins */
+    cpc->psr = 0x00000000; /* 8 bits ROM */
+    /* PFWD */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 30;
+    /* PFBD */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 28;
+    /* PDC */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 23;
+    /* PT */
+    D = 0x5; /* M = 16 */
+    cpc->psr |= D << 25;
+    /* ODP */
+    D = 0x1; /* Divide by 2 */
+    cpc->psr |= D << 21;
+    /* EBDP */
+    D = 0x2; /* Divide by 4 */
+    cpc->psr |= D << 17;
+}
+
+static void ppc405cr_cpc_init (CPUState *env, clk_setup_t clk_setup[7],
+                               uint32_t sysclk)
+{
+    ppc405cr_cpc_t *cpc;
+
+    cpc = qemu_mallocz(sizeof(ppc405cr_cpc_t));
+    if (cpc != NULL) {
+        memcpy(cpc->clk_setup, clk_setup,
+               PPC405CR_CLK_NB * sizeof(clk_setup_t));
+        cpc->sysclk = sysclk;
+        cpc->jtagid = 0x42051049;
+        ppc_dcr_register(env, PPC405CR_CPC0_PSR, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_CR0, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_CR1, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_JTAGID, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_PLLMR, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_ER, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_FR, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc_dcr_register(env, PPC405CR_CPC0_SR, cpc,
+                         &dcr_read_crcpc, &dcr_write_crcpc);
+        ppc405cr_clk_init(cpc);
+        qemu_register_reset(ppc405cr_cpc_reset, cpc);
+        ppc405cr_cpc_reset(cpc);
+    }
+}
+
+CPUState *ppc405cr_init (target_ulong ram_bases[4], target_ulong ram_sizes[4],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init)
+{
+    clk_setup_t clk_setup[PPC405CR_CLK_NB];
+    qemu_irq dma_irqs[4];
+    CPUState *env;
+    ppc4xx_mmio_t *mmio;
+    qemu_irq *pic, *irqs;
+    ram_addr_t offset;
+    int i;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
+                      &clk_setup[PPC405CR_TMR_CLK], sysclk);
+    /* Memory mapped devices registers */
+    mmio = ppc4xx_mmio_init(env, 0xEF600000);
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(env, mmio, 0x600);
+    /* Universal interrupt controller */
+    irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+    ppc405_sdram_init(env, pic[14], 1, ram_bases, ram_sizes, do_init);
+    offset = 0;
+    for (i = 0; i < 4; i++)
+        offset += ram_sizes[i];
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[26];
+    dma_irqs[1] = pic[25];
+    dma_irqs[2] = pic[24];
+    dma_irqs[3] = pic[23];
+    ppc405_dma_init(env, dma_irqs);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]);
+    }
+    if (serial_hds[1] != NULL) {
+        ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]);
+    }
+    /* IIC controller */
+    ppc405_i2c_init(env, mmio, 0x500, pic[29]);
+    /* GPIO */
+    ppc405_gpio_init(env, mmio, 0x700);
+    /* CPU control */
+    ppc405cr_cpc_init(env, clk_setup, sysclk);
+    *offsetp = offset;
+
+    return env;
+}
+
+/*****************************************************************************/
+/* PowerPC 405EP */
+/* CPU control */
+enum {
+    PPC405EP_CPC0_PLLMR0 = 0x0F0,
+    PPC405EP_CPC0_BOOT   = 0x0F1,
+    PPC405EP_CPC0_EPCTL  = 0x0F3,
+    PPC405EP_CPC0_PLLMR1 = 0x0F4,
+    PPC405EP_CPC0_UCR    = 0x0F5,
+    PPC405EP_CPC0_SRR    = 0x0F6,
+    PPC405EP_CPC0_JTAGID = 0x0F7,
+    PPC405EP_CPC0_PCI    = 0x0F9,
+#if 0
+    PPC405EP_CPC0_ER     = xxx,
+    PPC405EP_CPC0_FR     = xxx,
+    PPC405EP_CPC0_SR     = xxx,
+#endif
+};
+
+enum {
+    PPC405EP_CPU_CLK   = 0,
+    PPC405EP_PLB_CLK   = 1,
+    PPC405EP_OPB_CLK   = 2,
+    PPC405EP_EBC_CLK   = 3,
+    PPC405EP_MAL_CLK   = 4,
+    PPC405EP_PCI_CLK   = 5,
+    PPC405EP_UART0_CLK = 6,
+    PPC405EP_UART1_CLK = 7,
+    PPC405EP_CLK_NB    = 8,
+};
+
+typedef struct ppc405ep_cpc_t ppc405ep_cpc_t;
+struct ppc405ep_cpc_t {
+    uint32_t sysclk;
+    clk_setup_t clk_setup[PPC405EP_CLK_NB];
+    uint32_t boot;
+    uint32_t epctl;
+    uint32_t pllmr[2];
+    uint32_t ucr;
+    uint32_t srr;
+    uint32_t jtagid;
+    uint32_t pci;
+    /* Clock and power management */
+    uint32_t er;
+    uint32_t fr;
+    uint32_t sr;
+};
+
+static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc)
+{
+    uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk;
+    uint32_t UART0_clk, UART1_clk;
+    uint64_t VCO_out, PLL_out;
+    int M, D;
+
+    VCO_out = 0;
+    if ((cpc->pllmr[1] & 0x80000000) && !(cpc->pllmr[1] & 0x40000000)) {
+        M = (((cpc->pllmr[1] >> 20) - 1) & 0xF) + 1; /* FBMUL */
+        //        printf("FBMUL %01x %d\n", (cpc->pllmr[1] >> 20) & 0xF, M);
+        D = 8 - ((cpc->pllmr[1] >> 16) & 0x7); /* FWDA */
+        //        printf("FWDA %01x %d\n", (cpc->pllmr[1] >> 16) & 0x7, D);
+        VCO_out = cpc->sysclk * M * D;
+        if (VCO_out < 500000000UL || VCO_out > 1000000000UL) {
+            /* Error - unlock the PLL */
+            printf("VCO out of range %" PRIu64 "\n", VCO_out);
+#if 0
+            cpc->pllmr[1] &= ~0x80000000;
+            goto pll_bypass;
+#endif
+        }
+        PLL_out = VCO_out / D;
+        /* Pretend the PLL is locked */
+        cpc->boot |= 0x00000001;
+    } else {
+#if 0
+    pll_bypass:
+#endif
+        PLL_out = cpc->sysclk;
+        if (cpc->pllmr[1] & 0x40000000) {
+            /* Pretend the PLL is not locked */
+            cpc->boot &= ~0x00000001;
+        }
+    }
+    /* Now, compute all other clocks */
+    D = ((cpc->pllmr[0] >> 20) & 0x3) + 1; /* CCDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("CCDV %01x %d\n", (cpc->pllmr[0] >> 20) & 0x3, D);
+#endif
+    CPU_clk = PLL_out / D;
+    D = ((cpc->pllmr[0] >> 16) & 0x3) + 1; /* CBDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("CBDV %01x %d\n", (cpc->pllmr[0] >> 16) & 0x3, D);
+#endif
+    PLB_clk = CPU_clk / D;
+    D = ((cpc->pllmr[0] >> 12) & 0x3) + 1; /* OPDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("OPDV %01x %d\n", (cpc->pllmr[0] >> 12) & 0x3, D);
+#endif
+    OPB_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 8) & 0x3) + 2; /* EPDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("EPDV %01x %d\n", (cpc->pllmr[0] >> 8) & 0x3, D);
+#endif
+    EBC_clk = PLB_clk / D;
+    D = ((cpc->pllmr[0] >> 4) & 0x3) + 1; /* MPDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("MPDV %01x %d\n", (cpc->pllmr[0] >> 4) & 0x3, D);
+#endif
+    MAL_clk = PLB_clk / D;
+    D = (cpc->pllmr[0] & 0x3) + 1; /* PPDV */
+#ifdef DEBUG_CLOCKS
+    //    printf("PPDV %01x %d\n", cpc->pllmr[0] & 0x3, D);
+#endif
+    PCI_clk = PLB_clk / D;
+    D = ((cpc->ucr - 1) & 0x7F) + 1; /* U0DIV */
+#ifdef DEBUG_CLOCKS
+    //    printf("U0DIV %01x %d\n", cpc->ucr & 0x7F, D);
+#endif
+    UART0_clk = PLL_out / D;
+    D = (((cpc->ucr >> 8) - 1) & 0x7F) + 1; /* U1DIV */
+#ifdef DEBUG_CLOCKS
+    //    printf("U1DIV %01x %d\n", (cpc->ucr >> 8) & 0x7F, D);
+#endif
+    UART1_clk = PLL_out / D;
+#ifdef DEBUG_CLOCKS
+    printf("Setup PPC405EP clocks - sysclk %d VCO %" PRIu64
+           " PLL out %" PRIu64 " Hz\n", cpc->sysclk, VCO_out, PLL_out);
+    printf("CPU %d PLB %d OPB %d EBC %d MAL %d PCI %d UART0 %d UART1 %d\n",
+           CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk,
+           UART0_clk, UART1_clk);
+    printf("CB %p opaque %p\n", cpc->clk_setup[PPC405EP_CPU_CLK].cb,
+           cpc->clk_setup[PPC405EP_CPU_CLK].opaque);
+#endif
+    /* Setup CPU clocks */
+    clk_setup(&cpc->clk_setup[PPC405EP_CPU_CLK], CPU_clk);
+    /* Setup PLB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PLB_CLK], PLB_clk);
+    /* Setup OPB clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_OPB_CLK], OPB_clk);
+    /* Setup external clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_EBC_CLK], EBC_clk);
+    /* Setup MAL clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_MAL_CLK], MAL_clk);
+    /* Setup PCI clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_PCI_CLK], PCI_clk);
+    /* Setup UART0 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART0_CLK], UART0_clk);
+    /* Setup UART1 clock */
+    clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk);
+}
+
+static target_ulong dcr_read_epcpc (void *opaque, int dcrn)
+{
+    ppc405ep_cpc_t *cpc;
+    target_ulong ret;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        ret = cpc->boot;
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        ret = cpc->epctl;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        ret = cpc->pllmr[0];
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        ret = cpc->pllmr[1];
+        break;
+    case PPC405EP_CPC0_UCR:
+        ret = cpc->ucr;
+        break;
+    case PPC405EP_CPC0_SRR:
+        ret = cpc->srr;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        ret = cpc->jtagid;
+        break;
+    case PPC405EP_CPC0_PCI:
+        ret = cpc->pci;
+        break;
+    default:
+        /* Avoid gcc warning */
+        ret = 0;
+        break;
+    }
+
+    return ret;
+}
+
+static void dcr_write_epcpc (void *opaque, int dcrn, target_ulong val)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = opaque;
+    switch (dcrn) {
+    case PPC405EP_CPC0_BOOT:
+        /* Read-only register */
+        break;
+    case PPC405EP_CPC0_EPCTL:
+        /* Don't care for now */
+        cpc->epctl = val & 0xC00000F3;
+        break;
+    case PPC405EP_CPC0_PLLMR0:
+        cpc->pllmr[0] = val & 0x00633333;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_PLLMR1:
+        cpc->pllmr[1] = val & 0xC0F73FFF;
+        ppc405ep_compute_clocks(cpc);
+        break;
+    case PPC405EP_CPC0_UCR:
+        /* UART control - don't care for now */
+        cpc->ucr = val & 0x003F7F7F;
+        break;
+    case PPC405EP_CPC0_SRR:
+        cpc->srr = val;
+        break;
+    case PPC405EP_CPC0_JTAGID:
+        /* Read-only */
+        break;
+    case PPC405EP_CPC0_PCI:
+        cpc->pci = val;
+        break;
+    }
+}
+
+static void ppc405ep_cpc_reset (void *opaque)
+{
+    ppc405ep_cpc_t *cpc = opaque;
+
+    cpc->boot = 0x00000010;     /* Boot from PCI - IIC EEPROM disabled */
+    cpc->epctl = 0x00000000;
+    cpc->pllmr[0] = 0x00011010;
+    cpc->pllmr[1] = 0x40000000;
+    cpc->ucr = 0x00000000;
+    cpc->srr = 0x00040000;
+    cpc->pci = 0x00000000;
+    cpc->er = 0x00000000;
+    cpc->fr = 0x00000000;
+    cpc->sr = 0x00000000;
+    ppc405ep_compute_clocks(cpc);
+}
+
+/* XXX: sysclk should be between 25 and 100 MHz */
+static void ppc405ep_cpc_init (CPUState *env, clk_setup_t clk_setup[8],
+                               uint32_t sysclk)
+{
+    ppc405ep_cpc_t *cpc;
+
+    cpc = qemu_mallocz(sizeof(ppc405ep_cpc_t));
+    if (cpc != NULL) {
+        memcpy(cpc->clk_setup, clk_setup,
+               PPC405EP_CLK_NB * sizeof(clk_setup_t));
+        cpc->jtagid = 0x20267049;
+        cpc->sysclk = sysclk;
+        ppc405ep_cpc_reset(cpc);
+        qemu_register_reset(&ppc405ep_cpc_reset, cpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+#if 0
+        ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+        ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc,
+                         &dcr_read_epcpc, &dcr_write_epcpc);
+#endif
+    }
+}
+
+CPUState *ppc405ep_init (target_ulong ram_bases[2], target_ulong ram_sizes[2],
+                         uint32_t sysclk, qemu_irq **picp,
+                         ram_addr_t *offsetp, int do_init)
+{
+    clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
+    qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
+    CPUState *env;
+    ppc4xx_mmio_t *mmio;
+    qemu_irq *pic, *irqs;
+    ram_addr_t offset;
+    int i;
+
+    memset(clk_setup, 0, sizeof(clk_setup));
+    /* init CPUs */
+    env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
+                      &tlb_clk_setup, sysclk);
+    clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
+    clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
+    /* Internal devices init */
+    /* Memory mapped devices registers */
+    mmio = ppc4xx_mmio_init(env, 0xEF600000);
+    /* PLB arbitrer */
+    ppc4xx_plb_init(env);
+    /* PLB to OPB bridge */
+    ppc4xx_pob_init(env);
+    /* OBP arbitrer */
+    ppc4xx_opba_init(env, mmio, 0x600);
+    /* Universal interrupt controller */
+    irqs = qemu_mallocz(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+    irqs[PPCUIC_OUTPUT_INT] =
+        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_INT];
+    irqs[PPCUIC_OUTPUT_CINT] =
+        ((qemu_irq *)env->irq_inputs)[PPC405_INPUT_CINT];
+    pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
+    *picp = pic;
+    /* SDRAM controller */
+    ppc405_sdram_init(env, pic[14], 2, ram_bases, ram_sizes, do_init);
+    offset = 0;
+    for (i = 0; i < 2; i++)
+        offset += ram_sizes[i];
+    /* External bus controller */
+    ppc405_ebc_init(env);
+    /* DMA controller */
+    dma_irqs[0] = pic[26];
+    dma_irqs[1] = pic[25];
+    dma_irqs[2] = pic[24];
+    dma_irqs[3] = pic[23];
+    ppc405_dma_init(env, dma_irqs);
+    /* IIC controller */
+    ppc405_i2c_init(env, mmio, 0x500, pic[29]);
+    /* GPIO */
+    ppc405_gpio_init(env, mmio, 0x700);
+    /* Serial ports */
+    if (serial_hds[0] != NULL) {
+        ppc405_serial_init(env, mmio, 0x300, pic[31], serial_hds[0]);
+    }
+    if (serial_hds[1] != NULL) {
+        ppc405_serial_init(env, mmio, 0x400, pic[30], serial_hds[1]);
+    }
+    /* OCM */
+    ppc405_ocm_init(env, ram_sizes[0] + ram_sizes[1]);
+    offset += 4096;
+    /* GPT */
+    gpt_irqs[0] = pic[12];
+    gpt_irqs[1] = pic[11];
+    gpt_irqs[2] = pic[10];
+    gpt_irqs[3] = pic[9];
+    gpt_irqs[4] = pic[8];
+    ppc4xx_gpt_init(env, mmio, 0x000, gpt_irqs);
+    /* PCI */
+    /* Uses pic[28], pic[15], pic[13] */
+    /* MAL */
+    mal_irqs[0] = pic[20];
+    mal_irqs[1] = pic[19];
+    mal_irqs[2] = pic[18];
+    mal_irqs[3] = pic[17];
+    ppc405_mal_init(env, mal_irqs);
+    /* Ethernet */
+    /* Uses pic[22], pic[16], pic[14] */
+    /* CPU control */
+    ppc405ep_cpc_init(env, clk_setup, sysclk);
+    *offsetp = offset;
+
+    return env;
+}

Modified: trunk/src/host/qemu-neo1973/hw/ppc_chrp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_chrp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc_chrp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU PPC CHRP/PMAC hardware System Emulator
  * 
- * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004-2007 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,9 @@
  */
 #include "vl.h"
 
+/* SMP is not enabled, for now */
+#define MAX_CPUS 1
+
 #define BIOS_FILENAME "ppc_rom.bin"
 #define VGABIOS_FILENAME "video.x"
 #define NVRAM_SIZE        0x2000
@@ -45,7 +48,7 @@
 
 static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
 {
-    printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value);
+    printf("%s: 0x" PADDRX " <= 0x%08x\n", __func__, addr, value);
 }
 
 static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
@@ -58,7 +61,7 @@
 
 static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
 {
-    printf("%s: 0x%08x => 0x00000000\n", __func__, addr);
+    printf("%s: 0x" PADDRX " => 0x00000000\n", __func__, addr);
     return 0;
 }
 
@@ -258,17 +261,12 @@
         /* R6 = x, R7 = y, R8 = visible, R9 = data */
         break;
     default:
-        fprintf(stderr, "unsupported OSI call R5=%08x\n", env->gpr[5]);
+        fprintf(stderr, "unsupported OSI call R5=" REGX "\n", env->gpr[5]);
         break;
     }
     return 1; /* osi_call handled */
 }
 
-/* XXX: suppress that */
-static void pic_irq_request(void *opaque, int level)
-{
-}
-
 static uint8_t nvram_chksum(const uint8_t *buf, int n)
 {
     int sum, i;
@@ -292,18 +290,18 @@
 }    
 
 /* PowerPC CHRP hardware initialisation */
-static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
-                          DisplayState *ds, const char **fd_filename, 
-                          int snapshot,
-                          const char *kernel_filename, 
-                          const char *kernel_cmdline,
-                          const char *initrd_filename,
-                          int is_heathrow)
+static void ppc_chrp_init (int ram_size, int vga_ram_size, int boot_device,
+                           DisplayState *ds, const char **fd_filename,
+                           int snapshot,
+                           const char *kernel_filename,
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           const char *cpu_model,
+                           int is_heathrow)
 {
-    CPUState *env;
+    CPUState *env, *envs[MAX_CPUS];
     char buf[1024];
-    SetIRQFunc *set_irq;
-    void *pic;
+    qemu_irq *pic, **openpic_irqs;
     m48t59_t *nvram;
     int unin_memory;
     int linux_boot, i;
@@ -313,39 +311,36 @@
     PCIBus *pci_bus;
     const char *arch_name;
     int vga_bios_size, bios_size;
+    qemu_irq *dummy_irq;
 
     linux_boot = (kernel_filename != NULL);
 
     /* init CPUs */
     env = cpu_init();
+    qemu_register_reset(&cpu_ppc_reset, env);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
 
-    /* Register CPU as a 74x/75x */
+    /* Default CPU is a generic 74x/75x */
+    if (cpu_model == NULL)
+        cpu_model = "750";
     /* XXX: CPU model (or PVR) should be provided on command line */
     //    ppc_find_by_name("750gx", &def); // Linux boot OK
     //    ppc_find_by_name("750fx", &def); // Linux boot OK
     /* Linux does not boot on 750cxe (and probably other 750cx based)
      * because it assumes it has 8 IBAT & DBAT pairs as it only have 4.
      */
-    //    ppc_find_by_name("750cxe", &def);
-    //    ppc_find_by_name("750p", &def);
-    //    ppc_find_by_name("740p", &def);
-    ppc_find_by_name("750", &def);
-    //    ppc_find_by_name("740", &def);
-    //    ppc_find_by_name("G3", &def);
-    //    ppc_find_by_name("604r", &def);
-    //    ppc_find_by_name("604e", &def);
-    //    ppc_find_by_name("604", &def);
+    ppc_find_by_name(cpu_model, &def);
     if (def == NULL) {
         cpu_abort(env, "Unable to find PowerPC CPU definition\n");
     }
-    cpu_ppc_register(env, def);
+    for (i = 0; i < smp_cpus; i++) {
+        cpu_ppc_register(env, def);
+        /* Set time-base frequency to 100 Mhz */
+        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        env->osi_call = vga_osi_call;
+        envs[i] = env;
+    }
 
-    /* Set time-base frequency to 100 Mhz */
-    cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
-    
-    env->osi_call = vga_osi_call;
-
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
@@ -354,11 +349,11 @@
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
-        fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", buf);
+        cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
         exit(1);
     }
     bios_size = (bios_size + 0xfff) & ~0xfff;
-    cpu_register_physical_memory((uint32_t)(-bios_size), 
+    cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
     
     /* allocate and load VGA BIOS */
@@ -387,8 +382,8 @@
         /* now we can load the kernel */
         kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
         if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
-                    kernel_filename);
+            cpu_abort(env, "qemu: could not load kernel '%s'\n",
+                      kernel_filename);
             exit(1);
         }
         /* load initrd */
@@ -397,8 +392,8 @@
             initrd_size = load_image(initrd_filename,
                                      phys_ram_base + initrd_base);
             if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
-                        initrd_filename);
+                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
+                          initrd_filename);
                 exit(1);
             }
         } else {
@@ -415,34 +410,37 @@
 
     if (is_heathrow) {
         isa_mem_base = 0x80000000;
-        
+
         /* Register 2 MB of ISA IO space */
         isa_mmio_init(0xfe000000, 0x00200000);
 
         /* init basic PC hardware */
+        if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
+            cpu_abort(env, "Only 6xx bus is supported on heathrow machine\n");
+            exit(1);
+        }
         pic = heathrow_pic_init(&heathrow_pic_mem_index);
-        set_irq = heathrow_pic_set_irq;
         pci_bus = pci_grackle_init(0xfec00000, pic);
-        pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, 
+        pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
                      ram_size, vga_ram_size,
                      vga_bios_offset, vga_bios_size);
 
         /* XXX: suppress that */
-        isa_pic = pic_init(pic_irq_request, NULL);
+        dummy_irq = i8259_init(NULL);
         
         /* XXX: use Mac Serial port */
-        serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
+        serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
         
         for(i = 0; i < nb_nics; i++) {
             if (!nd_table[i].model)
                 nd_table[i].model = "ne2k_pci";
-            pci_nic_init(pci_bus, &nd_table[i]);
+            pci_nic_init(pci_bus, &nd_table[i], -1);
         }
         
         pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
 
         /* cuda also initialize ADB */
-        cuda_mem_index = cuda_init(set_irq, pic, 0x12);
+        cuda_mem_index = cuda_init(pic[0x12]);
         
         adb_kbd_init(&adb_bus);
         adb_mouse_init(&adb_bus);
@@ -454,22 +452,64 @@
         }
 
         macio_init(pci_bus, 0x0017);
-        
-        nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
-        
+
+        nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+
         arch_name = "HEATHROW";
     } else {
         isa_mem_base = 0x80000000;
-        
+
         /* Register 8 MB of ISA IO space */
         isa_mmio_init(0xf2000000, 0x00800000);
-        
+
         /* UniN init */
         unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
         cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
 
-        pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
-        set_irq = openpic_set_irq;
+        openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
+        openpic_irqs[0] =
+            qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+        for (i = 0; i < smp_cpus; i++) {
+            /* Mac99 IRQ connection between OpenPIC outputs pins
+             * and PowerPC input pins
+             */
+            switch (PPC_INPUT(env)) {
+            case PPC_FLAGS_INPUT_6xx:
+                openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
+                openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+                    ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+                openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+                    ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
+                openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+                    ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
+                /* Not connected ? */
+                openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+                /* Check this */
+                openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+                    ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
+                break;
+            case PPC_FLAGS_INPUT_970:
+                openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
+                openpic_irqs[i][OPENPIC_OUTPUT_INT] =
+                    ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
+                openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
+                    ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
+                openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
+                    ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
+                /* Not connected ? */
+                openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
+                /* Check this */
+                openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
+                    ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
+                break;
+            default:
+                cpu_abort(env,
+                          "Only bus model not supported on mac99 machine\n");
+                exit(1);
+            }
+        }
+        pic = openpic_init(NULL, &openpic_mem_index, smp_cpus,
+                           openpic_irqs, NULL);
         pci_bus = pci_pmac_init(pic);
         /* init basic PC hardware */
         pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
@@ -477,30 +517,30 @@
                      vga_bios_offset, vga_bios_size);
 
         /* XXX: suppress that */
-        isa_pic = pic_init(pic_irq_request, NULL);
-        
+        dummy_irq = i8259_init(NULL);
+
         /* XXX: use Mac Serial port */
-        serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
-        
+        serial_init(0x3f8, dummy_irq[4], serial_hds[0]);
         for(i = 0; i < nb_nics; i++) {
-            pci_ne2000_init(pci_bus, &nd_table[i]);
+            if (!nd_table[i].model)
+                nd_table[i].model = "ne2k_pci";
+            pci_nic_init(pci_bus, &nd_table[i], -1);
         }
-        
 #if 1
-        ide0_mem_index = pmac_ide_init(&bs_table[0], set_irq, pic, 0x13);
-        ide1_mem_index = pmac_ide_init(&bs_table[2], set_irq, pic, 0x14);
+        ide0_mem_index = pmac_ide_init(&bs_table[0], pic[0x13]);
+        ide1_mem_index = pmac_ide_init(&bs_table[2], pic[0x14]);
 #else
         pci_cmd646_ide_init(pci_bus, &bs_table[0], 0);
 #endif
         /* cuda also initialize ADB */
-        cuda_mem_index = cuda_init(set_irq, pic, 0x19);
+        cuda_mem_index = cuda_init(pic[0x19]);
         
         adb_kbd_init(&adb_bus);
         adb_mouse_init(&adb_bus);
         
         macio_init(pci_bus, 0x0022);
         
-        nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
+        nvram = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
         
         arch_name = "MAC99";
     }
@@ -525,30 +565,32 @@
     register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
 }
 
-static void ppc_core99_init(int ram_size, int vga_ram_size, int boot_device,
-                            DisplayState *ds, const char **fd_filename, 
-                            int snapshot,
-                            const char *kernel_filename, 
-                            const char *kernel_cmdline,
-                            const char *initrd_filename)
+static void ppc_core99_init (int ram_size, int vga_ram_size, int boot_device,
+                             DisplayState *ds, const char **fd_filename,
+                             int snapshot,
+                             const char *kernel_filename,
+                             const char *kernel_cmdline,
+                             const char *initrd_filename,
+                             const char *cpu_model)
 {
     ppc_chrp_init(ram_size, vga_ram_size, boot_device,
                   ds, fd_filename, snapshot,
                   kernel_filename, kernel_cmdline,
-                  initrd_filename, 0);
+                  initrd_filename, cpu_model, 0);
 }
     
-static void ppc_heathrow_init(int ram_size, int vga_ram_size, int boot_device,
-                              DisplayState *ds, const char **fd_filename, 
-                              int snapshot,
-                              const char *kernel_filename, 
-                              const char *kernel_cmdline,
-                              const char *initrd_filename)
+static void ppc_heathrow_init (int ram_size, int vga_ram_size, int boot_device,
+                               DisplayState *ds, const char **fd_filename,
+                               int snapshot,
+                               const char *kernel_filename,
+                               const char *kernel_cmdline,
+                               const char *initrd_filename,
+                               const char *cpu_model)
 {
     ppc_chrp_init(ram_size, vga_ram_size, boot_device,
                   ds, fd_filename, snapshot,
                   kernel_filename, kernel_cmdline,
-                  initrd_filename, 1);
+                  initrd_filename, cpu_model, 1);
 }
 
 QEMUMachine core99_machine = {

Modified: trunk/src/host/qemu-neo1973/hw/ppc_prep.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ppc_prep.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ppc_prep.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU PPC PREP hardware System Emulator
  * 
- * Copyright (c) 2003-2004 Jocelyn Mayer
+ * Copyright (c) 2003-2007 Jocelyn Mayer
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -84,29 +84,22 @@
 #endif
 }
 
-static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
+static uint32_t speaker_ioport_read (void *opaque, uint32_t addr)
 {
 #if 0
     int out;
     out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
     dummy_refresh_clock ^= 1;
     return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
-      (dummy_refresh_clock << 4);
+        (dummy_refresh_clock << 4);
 #endif
     return 0;
 }
 
-static void pic_irq_request(void *opaque, int level)
-{
-    if (level)
-        cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
-}
-
 /* PCI intack register */
 /* Read-only register (?) */
-static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void _PPC_intack_write (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
 {
     //    printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
 }
@@ -294,7 +287,7 @@
         /* Special port 92 */
         /* Check soft reset asked */
         if (val & 0x01) {
-            //            cpu_interrupt(first_cpu, CPU_INTERRUPT_RESET);
+            //            cpu_interrupt(first_cpu, PPC_INTERRUPT_RESET);
         }
         /* Check LE mode */
         if (val & 0x02) {
@@ -518,10 +511,12 @@
 #define NVRAM_SIZE        0x2000
 
 /* PowerPC PREP hardware initialisation */
-static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
-                          DisplayState *ds, const char **fd_filename, int snapshot,
-                          const char *kernel_filename, const char *kernel_cmdline,
-                          const char *initrd_filename)
+static void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
+                           DisplayState *ds, const char **fd_filename,
+                           int snapshot, const char *kernel_filename,
+                           const char *kernel_cmdline,
+                           const char *initrd_filename,
+                           const char *cpu_model)
 {
     CPUState *env;
     char buf[1024];
@@ -532,23 +527,24 @@
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
     ppc_def_t *def;
     PCIBus *pci_bus;
+    qemu_irq *i8259;
 
     sysctrl = qemu_mallocz(sizeof(sysctrl_t));
     if (sysctrl == NULL)
-	return;
+        return;
 
     linux_boot = (kernel_filename != NULL);
-    
+
     /* init CPUs */
 
     env = cpu_init();
+    qemu_register_reset(&cpu_ppc_reset, env);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
-    
-    /* Register CPU as a 604 */
-    /* XXX: CPU model (or PVR) should be provided on command line */
-    //    ppc_find_by_name("604r", &def);
-    //    ppc_find_by_name("604e", &def);
-    ppc_find_by_name("604", &def);
+
+    /* Default CPU is a 604 */
+    if (cpu_model == NULL)
+        cpu_model = "604";
+    ppc_find_by_name(cpu_model, &def);
     if (def == NULL) {
         cpu_abort(env, "Unable to find PowerPC CPU definition\n");
     }
@@ -564,11 +560,11 @@
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
     bios_size = load_image(buf, phys_ram_base + bios_offset);
     if (bios_size < 0 || bios_size > BIOS_SIZE) {
-        fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
+        cpu_abort(env, "qemu: could not load PPC PREP bios '%s'\n", buf);
         exit(1);
     }
     bios_size = (bios_size + 0xfff) & ~0xfff;
-    cpu_register_physical_memory((uint32_t)(-bios_size), 
+    cpu_register_physical_memory((uint32_t)(-bios_size),
                                  bios_size, bios_offset | IO_MEM_ROM);
 
     if (linux_boot) {
@@ -576,8 +572,8 @@
         /* now we can load the kernel */
         kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
         if (kernel_size < 0) {
-            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
-                    kernel_filename);
+            cpu_abort(env, "qemu: could not load kernel '%s'\n",
+                      kernel_filename);
             exit(1);
         }
         /* load initrd */
@@ -586,8 +582,8 @@
             initrd_size = load_image(initrd_filename,
                                      phys_ram_base + initrd_base);
             if (initrd_size < 0) {
-                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
-                        initrd_filename);
+                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
+                          initrd_filename);
                 exit(1);
             }
         } else {
@@ -603,7 +599,12 @@
     }
 
     isa_mem_base = 0xc0000000;
-    pci_bus = pci_prep_init();
+    if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
+        cpu_abort(env, "Only 6xx bus is supported on PREP machine\n");
+        exit(1);
+    }
+    i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
+    pci_bus = pci_prep_init(i8259);
     //    pci_bus = i440fx_init();
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
     PPC_io_memory = cpu_register_io_memory(0, PPC_prep_io_read,
@@ -613,35 +614,35 @@
     /* init basic PC hardware */
     pci_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, 
                  vga_ram_size, 0, 0);
-    rtc_init(0x70, 8);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
-    isa_pic = pic_init(pic_irq_request, first_cpu);
-    //    pit = pit_init(0x40, 0);
+    //    pit = pit_init(0x40, i8259[0]);
+    rtc_init(0x70, i8259[8]);
 
-    serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
+    serial_init(0x3f8, i8259[4], serial_hds[0]);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
     for(i = 0; i < nb_nics1; i++) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
-            isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
+            isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
         } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+            /* Why ? */
+            cpu_abort(env, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
         }
     }
 
     for(i = 0; i < 2; i++) {
-        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                      bs_table[2 * i], bs_table[2 * i + 1]);
     }
-    kbd_init();
+    i8042_init(i8259[1], i8259[12], 0x60);
     DMA_init(1);
     //    AUD_init();
     //    SB16_init();
 
-    fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+    fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table);
 
     /* Register speaker port */
     register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
@@ -668,7 +669,7 @@
         usb_ohci_init_pci(pci_bus, 3, -1);
     }
 
-    nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
+    nvram = m48t59_init(i8259[8], 0, 0x0074, NVRAM_SIZE, 59);
     if (nvram == NULL)
         return;
     sysctrl->nvram = nvram;

Modified: trunk/src/host/qemu-neo1973/hw/prep_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/prep_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/prep_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -123,19 +123,19 @@
     return (irq_num + (pci_dev->devfn >> 3)) & 1;
 }
 
-static void prep_set_irq(void *pic, int irq_num, int level)
+static void prep_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    pic_set_irq(irq_num ? 11 : 9, level);
+    qemu_set_irq(pic[irq_num ? 11 : 9], level);
 }
 
-PCIBus *pci_prep_init(void)
+PCIBus *pci_prep_init(qemu_irq *pic)
 {
     PREPPCIState *s;
     PCIDevice *d;
     int PPC_io_memory;
 
     s = qemu_mallocz(sizeof(PREPPCIState));
-    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, NULL, 0, 2);
+    s->bus = pci_register_bus(prep_set_irq, prep_map_irq, pic, 0, 2);
 
     register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
     register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);

Modified: trunk/src/host/qemu-neo1973/hw/ps2.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ps2.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/ps2.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -324,6 +324,11 @@
     }
 }
 
+void ps2_mouse_fake_event(void *opaque)
+{
+    ps2_mouse_event(opaque, 1, 0, 0, 0);
+}
+
 void ps2_write_mouse(void *opaque, int val)
 {
     PS2MouseState *s = (PS2MouseState *)opaque;

Modified: trunk/src/host/qemu-neo1973/hw/pxa.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -7,10 +7,8 @@
  * This code is licenced under the GPL.
  */
 #ifndef PXA_H
-# define PXA_H	1
+# define PXA_H			"pxa.h"
 
-# include "arm_pic.h"
-
 /* Interrupt numbers */
 # define PXA2XX_PIC_SSP3	0
 # define PXA2XX_PIC_USBH2	2
@@ -22,10 +20,12 @@
 # define PXA2XX_PIC_GPIO_1	9
 # define PXA2XX_PIC_GPIO_X	10
 # define PXA2XX_PIC_I2S 	13
+# define PXA26X_PIC_ASSP	15
 # define PXA25X_PIC_NSSP	16
 # define PXA27X_PIC_SSP2	16
 # define PXA2XX_PIC_LCD		17
 # define PXA2XX_PIC_I2C		18
+# define PXA2XX_PIC_ICP		19
 # define PXA2XX_PIC_STUART	20
 # define PXA2XX_PIC_BTUART	21
 # define PXA2XX_PIC_FFUART	22
@@ -47,6 +47,8 @@
 # define PXA2XX_TX_RQ_SSP1	14
 # define PXA2XX_RX_RQ_SSP2	15
 # define PXA2XX_TX_RQ_SSP2	16
+# define PXA2XX_RX_RQ_ICP	17
+# define PXA2XX_TX_RQ_ICP	18
 # define PXA2XX_RX_RQ_STUART	19
 # define PXA2XX_TX_RQ_STUART	20
 # define PXA2XX_RX_RQ_MMCI	21
@@ -55,23 +57,22 @@
 # define PXA2XX_RX_RQ_SSP3	66
 # define PXA2XX_TX_RQ_SSP3	67
 
-# define PXA2XX_RAM_BASE	0xa0000000
+# define PXA2XX_SDRAM_BASE	0xa0000000
+# define PXA2XX_INTERNAL_BASE	0x5c000000
 
 /* pxa2xx_pic.c */
-struct pxa2xx_pic_state_s;
-struct pxa2xx_pic_state_s *pxa2xx_pic_init(target_phys_addr_t base,
-                CPUState *env, int parent_irq, int parent_fiq);
+qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
 
 /* pxa2xx_timer.c */
 void pxa25x_timer_init(target_phys_addr_t base,
-                void *pic, int irq, CPUState *cpustate);
+                qemu_irq *irqs, CPUState *cpustate);
 void pxa27x_timer_init(target_phys_addr_t base,
-                void *pic, int irq, CPUState *cpustate);
+                qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate);
 
 /* pxa2xx_gpio.c */
 struct pxa2xx_gpio_info_s;
 struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, void *pic, int lines);
+                CPUState *env, qemu_irq *pic, int lines);
 void pxa2xx_gpio_set(struct pxa2xx_gpio_info_s *s, int line, int level);
 void pxa2xx_gpio_handler_set(struct pxa2xx_gpio_info_s *s, int line,
                 gpio_handler_t handler, void *opaque);
@@ -81,15 +82,15 @@
 /* pxa2xx_dma.c */
 struct pxa2xx_dma_state_s;
 struct pxa2xx_dma_state_s *pxa255_dma_init(target_phys_addr_t base,
-                void *pic, int irq);
+                qemu_irq irq);
 struct pxa2xx_dma_state_s *pxa27x_dma_init(target_phys_addr_t base,
-                void *pic, int irq);
+                qemu_irq irq);
 void pxa2xx_dma_request(struct pxa2xx_dma_state_s *s, int req_num, int on);
 
 /* pxa2xx_lcd.c */
 struct pxa2xx_lcdc_s;
 struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base,
-                void *pic, DisplayState *ds);
+                qemu_irq irq, DisplayState *ds);
 void pxa2xx_lcd_vsync_cb(struct pxa2xx_lcdc_s *s,
                 void (*cb)(void *opaque), void *opaque);
 void pxa2xx_lcdc_oritentation(void *opaque, int angle);
@@ -97,7 +98,7 @@
 /* pxa2xx_mmci.c */
 struct pxa2xx_mmci_s;
 struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
-                void *pic, void *dma);
+                qemu_irq irq, void *dma);
 void pxa2xx_mmci_handlers(struct pxa2xx_mmci_s *s, void *opaque,
                 void (*readonly_cb)(void *, int),
                 void (*coverswitch_cb)(void *, int));
@@ -107,54 +108,30 @@
 struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base);
 int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card);
 int pxa2xx_pcmcia_dettach(void *opaque);
-void pxa2xx_pcmcia_set_irq_cb(void *opaque, void (*set_irq)(void *opaque,
-                int line, int level), int irq, int cd_irq, void *pic);
+void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq);
 
-static struct {
-    target_phys_addr_t io_base;
-    int irq;
-} pxa255_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0x41600000, PXA25X_PIC_HWUART },
-    { 0, 0 }
-}, pxa270_serial[] = {
-    { 0x40100000, PXA2XX_PIC_FFUART },
-    { 0x40200000, PXA2XX_PIC_BTUART },
-    { 0x40700000, PXA2XX_PIC_STUART },
-    { 0, 0 }
-};
-
-static struct {
-    target_phys_addr_t io_base;
-    int irq;
-} pxa27x_ssp[] = {
-    { 0x41000000, PXA2XX_PIC_SSP },
-    { 0x41700000, PXA27X_PIC_SSP2 },
-    { 0x41900000, PXA2XX_PIC_SSP3 },
-    { 0, 0 }
-};
-
-/* The CPU is also modeled as an interrupt controller.  */
-# define PXA2XX_PIC_CPU_IRQ 0
-# define PXA2XX_PIC_CPU_FIQ 1
-
+/* pxa2xx.c */
 struct pxa2xx_ssp_s;
+void pxa2xx_ssp_attach(struct pxa2xx_ssp_s *port,
+                uint32_t (*readfn)(void *opaque),
+                void (*writefn)(void *opaque, uint32_t value), void *opaque);
+
 struct pxa2xx_i2c_s;
 struct pxa2xx_i2s_s;
+struct pxa2xx_fir_s;
 
 struct pxa2xx_state_s {
     CPUState *env;
-    struct pxa2xx_pic_state_s *pic;
+    qemu_irq *pic;
     struct pxa2xx_dma_state_s *dma;
     struct pxa2xx_gpio_info_s *gpio;
     struct pxa2xx_lcdc_s *lcd;
     struct pxa2xx_ssp_s **ssp;
+    struct pxa2xx_i2c_s *i2c[2];
     struct pxa2xx_mmci_s *mmc;
     struct pxa2xx_pcmcia_s *pcmcia[2];
-    struct pxa2xx_i2c_s *i2c[2];
     struct pxa2xx_i2s_s *i2s;
+    struct pxa2xx_fir_s *fir;
 
     /* Power management */
     target_phys_addr_t pm_base;
@@ -200,1250 +177,22 @@
     QEMUTimer *rtc_pi;
 };
 
-# define PMCR	0x00	/* Power Manager Control Register */
-# define PSSR	0x04	/* Power Manager Sleep Status Register */
-# define PSPR	0x08	/* Power Manager Scratch-Pad Register */
-# define PWER	0x0c	/* Power Manager Wake-Up Enable Register */
-# define PRER	0x10	/* Power Manager Rising-Edge Detect Enable Register */
-# define PFER	0x14	/* Power Manager Falling-Edge Detect Enable Register */
-# define PEDR	0x18	/* Power Manager Edge-Detect Status Register */
-# define PCFR	0x1c	/* Power Manager General Configuration Register */
-# define PGSR0	0x20	/* Power Manager GPIO Sleep-State Register 0 */
-# define PGSR1	0x24	/* Power Manager GPIO Sleep-State Register 1 */
-# define PGSR2	0x28	/* Power Manager GPIO Sleep-State Register 2 */
-# define PGSR3	0x2c	/* Power Manager GPIO Sleep-State Register 3 */
-# define RCSR	0x30	/* Reset Controller Status Register */
-# define PSLR	0x34	/* Power Manager Sleep Configuration Register */
-# define PTSR	0x38	/* Power Manager Standby Configuration Register */
-# define PVCR	0x40	/* Power Manager Voltage Change Control Register */
-# define PUCR	0x4c	/* Power Manager USIM Card Control/Status Register */
-# define PKWR	0x50	/* Power Manager Keyboard Wake-Up Enable Register */
-# define PKSR	0x54	/* Power Manager Keyboard Level-Detect Status */
-# define PCMD0	0x80	/* Power Manager I2C Command Register File 0 */
-# define PCMD31	0xfc	/* Power Manager I2C Command Register File 31 */
-
-static uint32_t pxa2xx_i2c_read(void *, target_phys_addr_t);
-static void pxa2xx_i2c_write(void *, target_phys_addr_t, uint32_t);
-
-static uint32_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    if (addr > s->pm_base + PCMD31) {
-        /* Special case: PWRI2C registers appear in the same range.  */
-        return pxa2xx_i2c_read(s->i2c[1], addr);
-    }
-    addr -= s->pm_base;
-
-    switch (addr) {
-    case PMCR ... PCMD31:
-        if (addr & 3)
-            goto fail;
-
-        return s->pm_regs[addr >> 2];
-    default:
-    fail:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    if (addr > s->pm_base + PCMD31) {
-        /* Special case: PWRI2C registers appear in the same range.  */
-        pxa2xx_i2c_write(s->i2c[1], addr, value);
-        return;
-    }
-    addr -= s->pm_base;
-
-    switch (addr) {
-    case PMCR:
-        s->pm_regs[addr >> 2] &= 0x15 & ~(value & 0x2a);
-        s->pm_regs[addr >> 2] |= value & 0x15;
-        break;
-
-    case PSSR:	/* Read-clean registers */
-    case RCSR:
-    case PKSR:
-        s->pm_regs[addr >> 2] &= ~value;
-        break;
-
-    default:	/* Read-write registers */
-        if (addr >= PMCR && addr <= PCMD31 && !(addr & 3)) {
-            s->pm_regs[addr >> 2] = value;
-            break;
-        }
-
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static CPUReadMemoryFunc *pxa2xx_pm_readfn[] = {
-    pxa2xx_pm_read,
-    pxa2xx_pm_read,
-    pxa2xx_pm_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_pm_writefn[] = {
-    pxa2xx_pm_write,
-    pxa2xx_pm_write,
-    pxa2xx_pm_write,
-};
-
-# define CCCR	0x00	/* Core Clock Configuration Register */
-# define CKEN	0x04	/* Clock Enable Register */
-# define OSCC	0x08	/* Oscillator Configuration Register */
-# define CCSR	0x0c	/* Core Clock Status Register */
-
-static uint32_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->cm_base;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-    case OSCC:
-        return s->cm_regs[addr >> 2];
-
-    case CCSR:
-        return s->cm_regs[CCCR >> 2] | (3 << 28);
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_cm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->cm_base;
-
-    switch (addr) {
-    case CCCR:
-    case CKEN:
-        s->cm_regs[addr >> 2] = value;
-        break;
-
-    case OSCC:
-        s->cm_regs[addr >> 2] &= ~0x6e;
-        s->cm_regs[addr >> 2] |= value & 0x6e;
-        break;
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static CPUReadMemoryFunc *pxa2xx_cm_readfn[] = {
-    pxa2xx_cm_read,
-    pxa2xx_cm_read,
-    pxa2xx_cm_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_cm_writefn[] = {
-    pxa2xx_cm_write,
-    pxa2xx_cm_write,
-    pxa2xx_cm_write,
-};
-
-static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-
-    switch (reg) {
-    case 6:	/* Clock Configuration Register */
-        return s->clkcfg;
-
-    case 7:	/* Power Mode Register */
-        return 0;
-
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    static const char *pwrmode[8] = {
-        "Normal", "Idle", "Deep-idle", "Standby",
-        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
-    };
-
-    switch (reg) {
-    case 6:	/* Clock Configuration Register */
-        s->clkcfg = value & 0xf;
-        if (value & 2)
-            printf("%s: CPU frequency change attempt\n", __FUNCTION__);
-        break;
-
-    case 7:	/* Power Mode Register */
-        if (value & 8)
-            printf("%s: CPU voltage change attempt\n", __FUNCTION__);
-        switch (value & 7) {
-        case 0:
-            /* Do nothing */
-            break;
-
-        case 1:
-            /* Idle */
-            if (!(s->cm_regs[CCCR] & (1 << 31))) {	/* CPDIS */
-                cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
-                break;
-            }
-            /* Fall through.  */
-
-        case 2:
-            /* Deep-Idle */
-            cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
-            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
-            goto message;
-
-        case 3:
-            cpu_reset(s->env);
-            s->env->cp15.c1_sys = 0;
-            s->env->cp15.c1_coproc = 0;
-            s->env->cp15.c2 = 0;
-            s->env->cp15.c3 = 0;
-            s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
-            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
-
-            /*
-             * The scratch-pad register is almost universally used
-             * for storing the return address on suspend.  For the
-             * lack of a resuming bootloader, perform a jump
-             * directly to that address.
-             */
-            memset(s->env->regs, 0, 4 * 15);
-            s->env->regs[15] = s->pm_regs[PSPR >> 2];
-
-#if 0
-            buffer = 0xe59ff000;	/* ldr     pc, [pc, #0] */
-            cpu_physical_memory_write(0, &buffer, 4);
-            buffer = s->pm_regs[PSPR >> 2];
-            cpu_physical_memory_write(8, &buffer, 4);
-#endif
-
-            /* Suspend */
-            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
-
-            goto message;
-
-        default:
-        message:
-            printf("%s: machine entered %s mode\n", __FUNCTION__,
-                            pwrmode[value & 7]);
-        }
-        break;
-
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-}
-
-/* Performace Monitoring registers */
-# define CPPMNC		0	/* Performance Monitor Control Register */
-# define CPCCNT		1	/* Clock Counter Register */
-# define CPINTEN	4	/* Interrupt Enable Register */
-# define CPFLAG		5	/* Overflow Flag Register */
-# define CPEVTSEL	8	/* Event Selection Register */
-
-# define CPPMN0		0	/* Performance Count Register 0 */
-# define CPPMN1		1	/* Performance Count Register 1 */
-# define CPPMN2		2	/* Performance Count Register 2 */
-# define CPPMN3		3	/* Performance Count Register 3 */
-
-static uint32_t pxa2xx_perf_read(void *opaque, int op2, int reg, int crm)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-
-    switch (reg) {
-    case CPPMNC:
-        return s->pmnc;
-    case CPCCNT:
-        if (s->pmnc & 1)
-            return qemu_get_clock(vm_clock);
-        else
-            return 0;
-    case CPINTEN:
-    case CPFLAG:
-    case CPEVTSEL:
-        return 0;
-
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_perf_write(void *opaque, int op2, int reg, int crm,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-
-    switch (reg) {
-    case CPPMNC:
-        s->pmnc = value;
-        break;
-
-    case CPCCNT:
-    case CPINTEN:
-    case CPFLAG:
-    case CPEVTSEL:
-        break;
-
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-}
-
-static uint32_t pxa2xx_cp14_read(void *opaque, int op2, int reg, int crm)
-{
-    switch (crm) {
-    case 0:
-        return pxa2xx_clkpwr_read(opaque, op2, reg, crm);
-    case 1:
-        return pxa2xx_perf_read(opaque, op2, reg, crm);
-    case 2:
-        switch (reg) {
-        case CPPMN0:
-        case CPPMN1:
-        case CPPMN2:
-        case CPPMN3:
-            return 0;
-        }
-        /* Fall through */
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_cp14_write(void *opaque, int op2, int reg, int crm,
-                uint32_t value)
-{
-    switch (crm) {
-    case 0:
-        pxa2xx_clkpwr_write(opaque, op2, reg, crm, value);
-        break;
-    case 1:
-        pxa2xx_perf_write(opaque, op2, reg, crm, value);
-        break;
-    case 2:
-        switch (reg) {
-        case CPPMN0:
-        case CPPMN1:
-        case CPPMN2:
-        case CPPMN3:
-            return;
-        }
-        /* Fall through */
-    default:
-        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
-        break;
-    }
-}
-
-# define MDCNFG		0x00	/* SDRAM Configuration Register */
-# define MDREFR		0x04	/* SDRAM Refresh Control Register */
-# define MSC0		0x08	/* Static Memory Control Register 0 */
-# define MSC1		0x0c	/* Static Memory Control Register 1 */
-# define MSC2		0x10	/* Static Memory Control Register 2 */
-# define MECR		0x14	/* Expansion Memory Bus Config Register */
-# define SXCNFG		0x1c	/* Synchronous Static Memory Config Register */
-# define MCMEM0		0x28	/* PC Card Memory Socket 0 Timing Register */
-# define MCMEM1		0x2c	/* PC Card Memory Socket 1 Timing Register */
-# define MCATT0		0x30	/* PC Card Attribute Socket 0 Register */
-# define MCATT1		0x34	/* PC Card Attribute Socket 1 Register */
-# define MCIO0		0x38	/* PC Card I/O Socket 0 Timing Register */
-# define MCIO1		0x3c	/* PC Card I/O Socket 1 Timing Register */
-# define MDMRS		0x40	/* SDRAM Mode Register Set Config Register */
-# define BOOT_DEF	0x44	/* Boot-time Default Configuration Register */
-# define ARB_CNTL	0x48	/* Arbiter Control Register */
-# define BSCNTR0	0x4c	/* Memory Buffer Strength Control Register 0 */
-# define BSCNTR1	0x50	/* Memory Buffer Strength Control Register 1 */
-# define LCDBSCNTR	0x54	/* LCD Buffer Strength Control Register */
-# define MDMRSLP	0x58	/* Low Power SDRAM Mode Set Config Register */
-# define BSCNTR2	0x5c	/* Memory Buffer Strength Control Register 2 */
-# define BSCNTR3	0x60	/* Memory Buffer Strength Control Register 3 */
-# define SA1110		0x64	/* SA-1110 Memory Compatibility Register */
-
-static uint32_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->mm_base;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0)
-            return s->mm_regs[addr >> 2];
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_mm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->mm_base;
-
-    switch (addr) {
-    case MDCNFG ... SA1110:
-        if ((addr & 3) == 0) {
-            s->mm_regs[addr >> 2] = value;
-            break;
-        }
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static CPUReadMemoryFunc *pxa2xx_mm_readfn[] = {
-    pxa2xx_mm_read,
-    pxa2xx_mm_read,
-    pxa2xx_mm_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_mm_writefn[] = {
-    pxa2xx_mm_write,
-    pxa2xx_mm_write,
-    pxa2xx_mm_write,
-};
-
-/* Synchronous Serial Ports */
-struct pxa2xx_ssp_s {
-    target_phys_addr_t base;
-    int irq;
-    struct pxa2xx_pic_state_s *pic;
-    int enable;
-
-    uint32_t sscr[2];
-    uint32_t sspsp;
-    uint32_t ssto;
-    uint32_t ssitr;
-    uint32_t sssr;
-    uint8_t sstsa;
-    uint8_t ssrsa;
-    uint8_t ssacd;
-
-    uint32_t rx_fifo[16];
-    int rx_level;
-    int rx_start;
-
-    uint32_t (*readfn)(void *opaque);
-    void (*writefn)(void *opaque, uint32_t value);
-    void *opaque;
-};
-
-# define SSCR0	0x00	/* SSP Control Register 0 */
-# define SSCR1	0x04	/* SSP Control Register 1 */
-# define SSSR	0x08	/* SSP Status Register */
-# define SSITR	0x0c	/* SSP Interrupt Test Register */
-# define SSDR	0x10	/* SSP Data Register */
-# define SSTO	0x28	/* SSP Time-Out Register */
-# define SSPSP	0x2c	/* SSP Programmable Serial Protocol Register */
-# define SSTSA	0x30	/* SSP TX Time Slot Active Register */
-# define SSRSA	0x34	/* SSP RX Time Slot Active Register */
-# define SSTSS	0x38	/* SSP Time Slot Status Register */
-# define SSACD	0x3c	/* SSP Audio Clock Divider Register */
-
-/* Bitfields for above registers */
-# define SSCR0_SPI(x)	(((x) & 0x30) == 0x00)
-# define SSCR0_SSP(x)	(((x) & 0x30) == 0x10)
-# define SSCR0_UWIRE(x)	(((x) & 0x30) == 0x20)
-# define SSCR0_PSP(x)	(((x) & 0x30) == 0x30)
-# define SSCR0_SSE	(1 << 7)
-# define SSCR0_RIM	(1 << 22)
-# define SSCR0_TIM	(1 << 23)
-# define SSCR0_MOD	(1 << 31)
-# define SSCR0_DSS(x)	(((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
-# define SSCR1_RIE	(1 << 0)
-# define SSCR1_TIE	(1 << 1)
-# define SSCR1_LBM	(1 << 2)
-# define SSCR1_MWDS	(1 << 5)
-# define SSCR1_TFT(x)	((((x) >> 6) & 0xf) + 1)
-# define SSCR1_RFT(x)	((((x) >> 10) & 0xf) + 1)
-# define SSCR1_EFWR	(1 << 14)
-# define SSCR1_PINTE	(1 << 18)
-# define SSCR1_TINTE	(1 << 19)
-# define SSCR1_RSRE	(1 << 20)
-# define SSCR1_TSRE	(1 << 21)
-# define SSCR1_EBCEI	(1 << 29)
-# define SSITR_INT	(7 << 5)
-# define SSSR_TNF	(1 << 2)
-# define SSSR_RNE	(1 << 3)
-# define SSSR_TFS	(1 << 5)
-# define SSSR_RFS	(1 << 6)
-# define SSSR_ROR	(1 << 7)
-# define SSSR_PINT	(1 << 18)
-# define SSSR_TINT	(1 << 19)
-# define SSSR_EOC	(1 << 20)
-# define SSSR_TUR	(1 << 21)
-# define SSSR_BCE	(1 << 23)
-# define SSSR_RW	0x00bc0080
-
-static void pxa2xx_ssp_int_update(struct pxa2xx_ssp_s *s)
-{
-    int level = 0;
-
-    level |= s->ssitr & SSITR_INT;
-    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
-    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
-    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
-    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
-    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
-    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
-    level |= (s->sssr & SSSR_RFS)  &&  (s->sscr[1] & SSCR1_RIE);
-    level |= (s->sssr & SSSR_TFS)  &&  (s->sscr[1] & SSCR1_TIE);
-    pic_set_irq_new(s->pic, s->irq, !!level);
-}
-
-static void pxa2xx_ssp_fifo_update(struct pxa2xx_ssp_s *s)
-{
-    s->sssr &= ~(0xf << 12);	/* Clear RFL */
-    s->sssr &= ~(0xf << 8);	/* Clear TFL */
-    s->sssr &= ~SSSR_TNF;
-    if (s->enable) {
-        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
-        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
-            s->sssr |= SSSR_RFS;
-        else
-            s->sssr &= ~SSSR_RFS;
-        if (0 <= SSCR1_TFT(s->sscr[1]))
-            s->sssr |= SSSR_TFS;
-        else
-            s->sssr &= ~SSSR_TFS;
-        if (s->rx_level)
-            s->sssr |= SSSR_RNE;
-        else
-            s->sssr &= ~SSSR_RNE;
-        s->sssr |= SSSR_TNF;
-    }
-
-    pxa2xx_ssp_int_update(s);
-}
-
-static uint32_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
-    uint32_t retval;
-    addr -= s->base;
-
-    switch (addr) {
-    case SSCR0:
-        return s->sscr[0];
-    case SSCR1:
-        return s->sscr[1];
-    case SSPSP:
-        return s->sspsp;
-    case SSTO:
-        return s->ssto;
-    case SSITR:
-        return s->ssitr;
-    case SSSR:
-        return s->sssr | s->ssitr;
-    case SSDR:
-        if (!s->enable)
-            return 0xffffffff;
-        if (s->rx_level < 1) {
-            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
-            return 0xffffffff;
-        }
-        s->rx_level --;
-        retval = s->rx_fifo[s->rx_start ++];
-        s->rx_start &= 0xf;
-        pxa2xx_ssp_fifo_update(s);
-        return retval;
-    case SSTSA:
-        return s->sstsa;
-    case SSRSA:
-        return s->ssrsa;
-    case SSTSS:
-        return 0;
-    case SSACD:
-        return s->ssacd;
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_ssp_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
-    addr -= s->base;
-
-    switch (addr) {
-    case SSCR0:
-        s->sscr[0] = value & 0xc7ffffff;
-        s->enable = value & SSCR0_SSE;
-        if (value & SSCR0_MOD)
-            printf("%s: Attempt to use network mode\n", __FUNCTION__);
-        if (s->enable && SSCR0_DSS(value) < 4)
-            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
-                            SSCR0_DSS(value));
-        if (!(value & SSCR0_SSE)) {
-            s->sssr = 0;
-            s->ssitr = 0;
-            s->rx_level = 0;
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSCR1:
-        s->sscr[1] = value;
-        if (value & (SSCR1_LBM | SSCR1_EFWR))
-            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSPSP:
-        s->sspsp = value;
-        break;
-
-    case SSTO:
-        s->ssto = value;
-        break;
-
-    case SSITR:
-        s->ssitr = value & SSITR_INT;
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSSR:
-        s->sssr &= ~(value & SSSR_RW);
-        pxa2xx_ssp_int_update(s);
-        break;
-
-    case SSDR:
-        if (SSCR0_UWIRE(s->sscr[0])) {
-            if (s->sscr[1] & SSCR1_MWDS)
-                value &= 0xffff;
-            else
-                value &= 0xff;
-        } else
-            /* Note how 32bits overflow does no harm here */
-            value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
-
-        /* Data goes from here to the Tx FIFO and is shifted out from
-         * there directly to the slave, no need to buffer it.
-         */
-        if (s->enable) {
-            if (s->writefn)
-                s->writefn(s->opaque, value);
-
-            if (s->rx_level < 0x10) {
-                if (s->readfn)
-                    s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] =
-                            s->readfn(s->opaque);
-                else
-                    s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = 0x0;
-            } else
-                s->sssr |= SSSR_ROR;
-        }
-        pxa2xx_ssp_fifo_update(s);
-        break;
-
-    case SSTSA:
-        s->sstsa = value;
-        break;
-
-    case SSRSA:
-        s->ssrsa = value;
-        break;
-
-    case SSACD:
-        s->ssacd = value;
-        break;
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-}
-
-static inline void pxa2xx_ssp_attach(struct pxa2xx_ssp_s *port,
-                uint32_t (*readfn)(void *opaque),
-                void (*writefn)(void *opaque, uint32_t value), void *opaque)
-{
-    if (!port) {
-        printf("%s: no such SSP\n", __FUNCTION__);
-        exit(-1);
-    }
-
-    port->opaque = opaque;
-    port->readfn = readfn;
-    port->writefn = writefn;
-}
-
-static CPUReadMemoryFunc *pxa2xx_ssp_readfn[] = {
-    pxa2xx_ssp_read,
-    pxa2xx_ssp_read,
-    pxa2xx_ssp_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_ssp_writefn[] = {
-    pxa2xx_ssp_write,
-    pxa2xx_ssp_write,
-    pxa2xx_ssp_write,
-};
-
-# define RCNR		0x00	/* RTC Counter Register */
-# define RTAR		0x04	/* RTC Alarm Register */
-# define RTSR		0x08	/* RTC Status Register */
-# define RTTR		0x0c	/* RTC Timer Trim Register */
-# define RDCR		0x10	/* RTC Day Counter Register */
-# define RYCR		0x14	/* RTC Year Counter Register */
-# define RDAR1		0x18	/* RTC Wristwatch Day Alarm Register 1 */
-# define RYAR1		0x1c	/* RTC Wristwatch Year Alarm Register 1 */
-# define RDAR2		0x20	/* RTC Wristwatch Day Alarm Register 2 */
-# define RYAR2		0x24	/* RTC Wristwatch Year Alarm Register 2 */
-# define SWCR		0x28	/* RTC Stopwatch Counter Register */
-# define SWAR1		0x2c	/* RTC Stopwatch Alarm Register 1 */
-# define SWAR2		0x30	/* RTC Stopwatch Alarm Register 2 */
-# define RTCPICR	0x34	/* RTC Periodic Interrupt Counter Register */
-# define PIAR		0x38	/* RTC Periodic Interrupt Alarm Register */
-
-static inline void pxa2xx_rtc_int_update(struct pxa2xx_state_s *s)
-{
-    pic_set_irq_new(s->pic, PXA2XX_PIC_RTCALARM, !!(s->rtsr & 0x2553));
-}
-
-static void pxa2xx_rtc_hzupdate(struct pxa2xx_state_s *s)
-{
-    int64_t rt = qemu_get_clock(rt_clock);
-    s->last_rcnr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_rdcr += ((rt - s->last_hz) << 15) /
-            (1000 * ((s->rttr & 0xffff) + 1));
-    s->last_hz = rt;
-}
-
-static void pxa2xx_rtc_swupdate(struct pxa2xx_state_s *s)
-{
-    int64_t rt = qemu_get_clock(rt_clock);
-    if (s->rtsr & (1 << 12))
-        s->last_swcr += (rt - s->last_sw) / 10;
-    s->last_sw = rt;
-}
-
-static void pxa2xx_rtc_piupdate(struct pxa2xx_state_s *s)
-{
-    int64_t rt = qemu_get_clock(rt_clock);
-    if (s->rtsr & (1 << 15))
-        s->last_swcr += rt - s->last_pi;
-    s->last_pi = rt;
-}
-
-static inline void pxa2xx_rtc_alarm_update(struct pxa2xx_state_s *s,
-                uint32_t rtsr)
-{
-    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
-        qemu_mod_timer(s->rtc_hz, s->last_hz +
-                (((s->rtar - s->last_rcnr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15));
-    else
-        qemu_del_timer(s->rtc_hz);
-
-    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
-        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
-                (((s->rdar1 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal1);
-
-    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
-        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
-                (((s->rdar2 - s->last_rdcr) * 1000 *
-                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_rdal2);
-
-    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
-        qemu_mod_timer(s->rtc_swal1, s->last_sw +
-                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal1);
-
-    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
-        qemu_mod_timer(s->rtc_swal2, s->last_sw +
-                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
-    else
-        qemu_del_timer(s->rtc_swal2);
-
-    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
-        qemu_mod_timer(s->rtc_pi, s->last_pi +
-                        (s->piar & 0xffff) - s->last_rtcpicr);
-    else
-        qemu_del_timer(s->rtc_pi);
-}
-
-static inline void pxa2xx_rtc_hz_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 0);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 4);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 6);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal1_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 8);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_swal2_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 10);
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static inline void pxa2xx_rtc_pi_tick(void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    s->rtsr |= (1 << 13);
-    pxa2xx_rtc_piupdate(s);
-    s->last_rtcpicr = 0;
-    pxa2xx_rtc_alarm_update(s, s->rtsr);
-    pxa2xx_rtc_int_update(s);
-}
-
-static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->rtc_base;
-
-    switch (addr) {
-    case RTTR:
-        return s->rttr;
-    case RTSR:
-        return s->rtsr;
-    case RTAR:
-        return s->rtar;
-    case RDAR1:
-        return s->rdar1;
-    case RDAR2:
-        return s->rdar2;
-    case RYAR1:
-        return s->ryar1;
-    case RYAR2:
-        return s->ryar2;
-    case SWAR1:
-        return s->swar1;
-    case SWAR2:
-        return s->swar2;
-    case PIAR:
-        return s->piar;
-    case RCNR:
-        return s->last_rcnr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
-                (1000 * ((s->rttr & 0xffff) + 1));
-    case RDCR:
-        return s->last_rdcr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
-                (1000 * ((s->rttr & 0xffff) + 1));
-    case RYCR:
-        return s->last_rycr;
-    case SWCR:
-        if (s->rtsr & (1 << 12))
-            return s->last_swcr + (qemu_get_clock(rt_clock) - s->last_sw) / 10;
-        else
-            return s->last_swcr;
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    addr -= s->rtc_base;
-
-    switch (addr) {
-    case RTTR:
-        if (!(s->rttr & (1 << 31))) {
-            pxa2xx_rtc_hzupdate(s);
-            s->rttr = value;
-            pxa2xx_rtc_alarm_update(s, s->rtsr);
-        }
-        break;
-
-    case RTSR:
-        if ((s->rtsr ^ value) & (1 << 15))
-            pxa2xx_rtc_piupdate(s);
-
-        if ((s->rtsr ^ value) & (1 << 12))
-            pxa2xx_rtc_swupdate(s);
-
-        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
-            pxa2xx_rtc_alarm_update(s, value);
-
-        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
-        pxa2xx_rtc_int_update(s);
-        break;
-
-    case RTAR:
-        s->rtar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR1:
-        s->rdar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDAR2:
-        s->rdar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR1:
-        s->ryar1 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYAR2:
-        s->ryar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR1:
-        pxa2xx_rtc_swupdate(s);
-        s->swar1 = value;
-        s->last_swcr = 0;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case SWAR2:
-        s->swar2 = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case PIAR:
-        s->piar = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RCNR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rcnr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RDCR:
-        pxa2xx_rtc_hzupdate(s);
-        s->last_rdcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RYCR:
-        s->last_rycr = value;
-        break;
-
-    case SWCR:
-        pxa2xx_rtc_swupdate(s);
-        s->last_swcr = value;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    case RTCPICR:
-        pxa2xx_rtc_piupdate(s);
-        s->last_rtcpicr = value & 0xffff;
-        pxa2xx_rtc_alarm_update(s, s->rtsr);
-        break;
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-    }
-}
-
-static void pxa2xx_rtc_reset(struct pxa2xx_state_s *s)
-{
-    struct tm *tm;
-    time_t ti;
-    int wom;
-
-    s->rttr = 0x7fff;
-    s->rtsr = 0;
-
-    time(&ti);
-    if (rtc_utc)
-        tm = gmtime(&ti);
-    else
-        tm = localtime(&ti);
-    wom = ((tm->tm_mday - 1) / 7) + 1;
-
-    s->last_rcnr = (uint32_t) ti;
-    s->last_rdcr = (wom << 20) | ((tm->tm_wday + 1) << 17) |
-            (tm->tm_hour << 12) | (tm->tm_min << 6) | tm->tm_sec;
-    s->last_rycr = ((tm->tm_year + 1900) << 9) |
-            ((tm->tm_mon + 1) << 5) | tm->tm_mday;
-    s->last_swcr = (tm->tm_hour << 19) |
-            (tm->tm_min << 13) | (tm->tm_sec << 7);
-    s->last_rtcpicr = 0;
-    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock);
-
-    s->rtc_hz    = qemu_new_timer(rt_clock, pxa2xx_rtc_hz_tick,    s);
-    s->rtc_rdal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal1_tick, s);
-    s->rtc_rdal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal2_tick, s);
-    s->rtc_swal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal1_tick, s);
-    s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s);
-    s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
-}
-
-static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = {
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
-};
-
-/* I2C Interface */
 struct pxa2xx_i2c_s {
+    i2c_slave slave;
+    i2c_bus *bus;
     target_phys_addr_t base;
-    int irq;
-    struct pxa2xx_pic_state_s *pic;
-    struct i2c_master_s master;
-    struct i2c_slave_s slave;
+    qemu_irq irq;
 
     uint16_t control;
     uint16_t status;
     uint8_t ibmr;
+    uint8_t data;
 };
 
-# define IBMR	0x80	/* I2C Bus Monitor Register */
-# define IDBR	0x88	/* I2C Data Buffer Register */
-# define ICR	0x90	/* I2C Control Register */
-# define ISR	0x98	/* I2C Status Register */
-# define ISAR	0xa0	/* I2C Slave Address Register */
-
-static void pxa2xx_i2c_update(struct pxa2xx_i2c_s *s)
-{
-    uint16_t level = 0;
-    level |= s->status & s->control & (1 << 10);		/* BED */
-    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));	/* IRF */
-    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));	/* ITE */
-    level |= s->status & (1 << 9);				/* SAD */
-    pic_set_irq_new(s->pic, s->irq, !!level);
-}
-
-static void pxa2xx_i2c_start(void *opaque, int dir)
-{
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
-    s->status |= (1 << 9);				/* set SAD */
-    if (dir)
-        s->status |= 1 << 0;				/* set RWM */
-    else
-        s->status &= ~(1 << 0);				/* clear RWM */
-}
-
-static void pxa2xx_i2c_stop(void *opaque)
-{
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
-    s->status |= (1 << 4);				/* set SSD */
-}
-
-static int pxa2xx_i2c_tx(void *opaque, uint8_t *message, int len)
-{
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
-    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
-        return 1;
-
-    if (len) {
-        if (s->status & (1 << 0)) {			/* RWM */
-            s->status |= 1 << 6;			/* set ITE */
-            s->master.data = message[0];		/* TODO */
-	} else {
-            s->status |= 1 << 7;			/* set IRF */
-            message[0] = s->master.data;		/* TODO */
-        }
-    }
-    pxa2xx_i2c_update(s);
-
-    return !s->master.ack;
-}
-
-static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
-    addr -= s->base;
-
-    switch (addr) {
-    case ICR:
-        return s->control;
-    case ISR:
-        return s->status;
-    case ISAR:
-        return s->slave.address;
-    case IDBR:
-        return s->master.data;
-    case IBMR:
-        if (s->status & (1 << 2))
-            s->ibmr ^= 3;	/* Fake SCL and SDA pin changes */
-        else
-            s->ibmr = 0;
-        return s->ibmr;
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
-    addr -= s->base;
-
-    switch (addr) {
-    case ICR:
-        s->control = value & 0xfff7;
-        if ((value & (1 << 3)) && (value & (1 << 6))) {	/* TB and IUE */
-            /* TODO: slave mode */
-            if (value & (1 << 0)) {			/* START condition */
-                if (s->master.data & 1)
-                    s->status |= 1 << 0;		/* set RWM */
-                else
-                    s->status &= ~(1 << 0);		/* clear RWM */
-                s->status |= 1 << 2;			/* set UB */
-            }
-
-            i2c_master_submit(&s->master,
-                            value & (1 << 0),		/* START condition */
-                            value & (1 << 1));		/* STOP condition */
-
-            if (s->master.ack) {
-                if (s->status & (1 << 0))		/* RWM */
-                    s->status |= 1 << 7;		/* set IRF */
-                else
-                    s->status |= 1 << 6;		/* set ITE */
-                s->status &= ~(1 << 1);			/* clear ACKNAK */
-            } else {
-                s->status |= 1 << 6;			/* set ITE */
-                s->status |= 1 << 10;			/* set BED */
-                s->status |= 1 << 1;			/* set ACKNAK */
-                s->status &= ~(1 << 2);			/* clear UB */
-            }
-            if (value & (1 << 1))			/* STOP condition */
-                s->status &= ~(1 << 2);			/* clear UB */
-        }
-        if (value & (1 << 4))				/* MA */
-            s->status &= ~(1 << 2);			/* clear UB */
-        if (!(value & (1 << 3)) && (value & (1 << 6)))	/* !TB and IUE */
-            s->status &= ~(1 << 2);			/* clear UB */
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISR:
-        s->status &= ~(value & 0x07f0);
-        pxa2xx_i2c_update(s);
-        break;
-
-    case ISAR:
-        if (s->master.bus)
-            i2c_slave_attach(s->master.bus, value & 0x7f, &s->slave);
-        break;
-
-    case IDBR:
-        s->master.data = value & 0xff;
-        break;
-
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-    }
-}
-
-static CPUReadMemoryFunc *pxa2xx_i2c_readfn[] = {
-    pxa2xx_i2c_read,
-    pxa2xx_i2c_read,
-    pxa2xx_i2c_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_i2c_writefn[] = {
-    pxa2xx_i2c_write,
-    pxa2xx_i2c_write,
-    pxa2xx_i2c_write,
-};
-
-static struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, int irq,
-                struct pxa2xx_pic_state_s *pic)
-{
-    int iomemtype;
-    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *)
-            qemu_mallocz(sizeof(struct pxa2xx_i2c_s));
-
-    s->base = base;
-    s->irq = irq;
-    s->pic = pic;
-    s->slave.tx = pxa2xx_i2c_tx;
-    s->slave.start = pxa2xx_i2c_start;
-    s->slave.stop = pxa2xx_i2c_stop;
-    s->slave.opaque = s;
-
-    iomemtype = cpu_register_io_memory(0, pxa2xx_i2c_readfn,
-                    pxa2xx_i2c_writefn, s);
-    cpu_register_physical_memory(s->base & 0xfffff000, 0xfff, iomemtype);
-
-    return s;
-}
-
-/* PXA Inter-IC Sound Controller */
 struct pxa2xx_i2s_s {
     target_phys_addr_t base;
-    int irq;
+    qemu_irq irq;
     struct pxa2xx_dma_state_s *dma;
-    struct pxa2xx_pic_state_s *pic;
     void (*data_req)(void *, int, int);
 
     uint32_t control[2];
@@ -1462,304 +211,13 @@
     uint32_t fifo[16];
 };
 
-static void pxa2xx_i2s_reset(struct pxa2xx_i2s_s *i2s)
-{
-    i2s->rx_len = 0;
-    i2s->tx_len = 0;
-    i2s->fifo_len = 0;
-    i2s->clk = 0x1a;
-    i2s->control[0] = 0x00;
-    i2s->control[1] = 0x00;
-    i2s->status = 0x00;
-    i2s->mask = 0x00;
-}
+# define PA_FMT			"0x%08lx"
+# define REG_FMT		"0x%lx"
 
-# define SACR_TFTH(val)	((val >> 8) & 0xf)
-# define SACR_RFTH(val)	((val >> 12) & 0xf)
-# define SACR_DREC(val)	(val & (1 << 3))
-# define SACR_DPRL(val)	(val & (1 << 4))
+struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, DisplayState *ds,
+                const char *revision);
+struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, DisplayState *ds);
 
-static inline void pxa2xx_i2s_update(struct pxa2xx_i2s_s *i2s)
-{
-    int rfs, tfs;
-    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
-            !SACR_DREC(i2s->control[1]);
-    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
-            i2s->enable && !SACR_DPRL(i2s->control[1]);
+void pxa2xx_reset(int line, int level, void *opaque);
 
-    pxa2xx_dma_request(i2s->dma, PXA2XX_RX_RQ_I2S, rfs);
-    pxa2xx_dma_request(i2s->dma, PXA2XX_TX_RQ_I2S, tfs);
-
-    i2s->status &= 0xe0;
-    if (i2s->rx_len)
-        i2s->status |= 1 << 1;			/* RNE */
-    if (i2s->enable)
-        i2s->status |= 1 << 2;			/* BSY */
-    if (tfs)
-        i2s->status |= 1 << 3;			/* TFS */
-    if (rfs)
-        i2s->status |= 1 << 4;			/* RFS */
-    if (!(i2s->tx_len && i2s->enable))
-        i2s->status |= i2s->fifo_len << 8;	/* TFL */
-    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;	/* RFL */
-
-    pic_set_irq_new(i2s->pic, i2s->irq, i2s->status & i2s->mask);
-}
-
-# define SACR0	0x00	/* Serial Audio Global Control Register */
-# define SACR1	0x04	/* Serial Audio I2S/MSB-Justified Control Register */
-# define SASR0	0x0c	/* Serial Audio Interface and FIFO Status Register */
-# define SAIMR	0x14	/* Serial Audio Interrupt Mask Register */
-# define SAICR	0x18	/* Serial Audio Interrupt Clear Register */
-# define SADIV	0x60	/* Serial Audio Clock Divider Register */
-# define SADR	0x80	/* Serial Audio Data Register */
-
-static uint32_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr)
-{
-    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
-    addr -= s->base;
-
-    switch (addr) {
-    case SACR0:
-        return s->control[0];
-    case SACR1:
-        return s->control[1];
-    case SASR0:
-        return s->status;
-    case SAIMR:
-        return s->mask;
-    case SAICR:
-        return 0;
-    case SADIV:
-        return s->clk;
-    case SADR:
-        if (s->rx_len > 0) {
-            s->rx_len --;
-            pxa2xx_i2s_update(s);
-            return s->codec_in(s->opaque);
-        }
-        return 0;
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-        break;
-    }
-    return 0;
-}
-
-static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
-    uint32_t *sample;
-    addr -= s->base;
-
-    switch (addr) {
-    case SACR0:
-        if (value & (1 << 3))				/* RST */
-            pxa2xx_i2s_reset(s);
-        s->control[0] = value & 0xff3d;
-        if (!s->enable && (value & 1) && s->tx_len) {	/* ENB */
-            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
-                s->codec_out(s->opaque, *sample);
-            s->status &= ~(1 << 7);			/* I2SOFF */
-        }
-        if (value & (1 << 4))				/* EFWR */
-            printf("%s: Attempt to use special function\n", __FUNCTION__);
-        s->enable = ((value ^ 4) & 5) == 5;		/* ENB && !RST*/
-        pxa2xx_i2s_update(s);
-        break;
-    case SACR1:
-        s->control[1] = value & 0x0039;
-        if (value & (1 << 5))				/* ENLBF */
-            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
-        if (value & (1 << 4))				/* DPRL */
-            s->fifo_len = 0;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAIMR:
-        s->mask = value & 0x0078;
-        pxa2xx_i2s_update(s);
-        break;
-    case SAICR:
-        s->status &= ~(value & (3 << 5));
-        pxa2xx_i2s_update(s);
-        break;
-    case SADIV:
-        s->clk = value & 0x007f;
-        break;
-    case SADR:
-        if (s->tx_len && s->enable) {
-            s->tx_len --;
-            pxa2xx_i2s_update(s);
-            s->codec_out(s->opaque, value);
-        } else if (s->fifo_len < 16) {
-            s->fifo[s->fifo_len ++] = value;
-            pxa2xx_i2s_update(s);
-        }
-        break;
-    default:
-        printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
-    }
-}
-
-static CPUReadMemoryFunc *pxa2xx_i2s_readfn[] = {
-    pxa2xx_i2s_read,
-    pxa2xx_i2s_read,
-    pxa2xx_i2s_read,
-};
-
-static CPUWriteMemoryFunc *pxa2xx_i2s_writefn[] = {
-    pxa2xx_i2s_write,
-    pxa2xx_i2s_write,
-    pxa2xx_i2s_write,
-};
-
-static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
-{
-    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
-    uint32_t *sample;
-
-    /* Signal FIFO errors */
-    if (s->enable && s->tx_len)
-        s->status |= 1 << 5;		/* TUR */
-    if (s->enable && s->rx_len)
-        s->status |= 1 << 6;		/* ROR */
-
-    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
-     * handle the cases where it makes a difference.  */
-    s->tx_len = tx - s->fifo_len;
-    s->rx_len = rx;
-    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
-    if (s->enable)
-        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
-            s->codec_out(s->opaque, *sample);
-    pxa2xx_i2s_update(s);
-}
-
-static struct pxa2xx_i2s_s *pxa2xx_i2s_init(target_phys_addr_t base, int irq,
-                struct pxa2xx_pic_state_s *pic, struct pxa2xx_dma_state_s *dma)
-{
-    int iomemtype;
-    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *)
-            qemu_mallocz(sizeof(struct pxa2xx_i2s_s));
-
-    s->base = base;
-    s->irq = irq;
-    s->pic = pic;
-    s->dma = dma;
-    s->data_req = pxa2xx_i2s_data_req;
-
-    pxa2xx_i2s_reset(s);
-
-    iomemtype = cpu_register_io_memory(0, pxa2xx_i2s_readfn,
-                    pxa2xx_i2s_writefn, s);
-    cpu_register_physical_memory(s->base & 0xfff00000, 0xfffff, iomemtype);
-
-    return s;
-}
-
-static void pxa2xx_reset(int line, int level, void *opaque)
-{
-    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
-    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {	/* GPR_EN */
-        cpu_reset(s->env);
-        /* TODO: reset peripherals */
-    }
-}
-
-/* Initialise a PXA270 integrated chip (ARM based core).  */
-static inline struct pxa2xx_state_s *pxa270_init(DisplayState *ds,
-                int revision)
-{
-    struct pxa2xx_state_s *s;
-    struct pxa2xx_ssp_s *ssp;
-    int iomemtype, i;
-    s = (struct pxa2xx_state_s *) qemu_mallocz(sizeof(struct pxa2xx_state_s));
-
-    s->env = cpu_init();
-    cpu_arm_set_model(s->env, ARM_CPUID_PXA270 | revision);
-
-    s->pic = pxa2xx_pic_init(0x40d00000, s->env,
-                    PXA2XX_PIC_CPU_IRQ, PXA2XX_PIC_CPU_FIQ);
-
-    s->dma = pxa27x_dma_init(0x40000000, s->pic, PXA2XX_PIC_DMA);
-
-    pxa27x_timer_init(0x40a00000, s->pic, PXA2XX_PIC_OST_0, s->env);
-
-    s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
-
-    s->mmc = pxa2xx_mmci_init(0x41100000, s->pic, s->dma);
-
-    for (i = 0; pxa270_serial[i].io_base; i ++)
-        if (serial_hds[i])
-            serial_mm_init(*(arm_pic_handler *) s->pic, s->pic,
-                            pxa270_serial[i].io_base, 2,
-                            pxa270_serial[i].irq, serial_hds[i]);
-
-    if (ds)
-        s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic, ds);
-
-    s->cm_base = 0x41300000;
-    s->cm_regs[CCCR >> 4] = 0x02000210;	/* 416.0 MHz */
-    s->clkcfg = 0x00000009;		/* Turbo mode active */
-    iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn,
-                    pxa2xx_cm_writefn, s);
-    cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype);
-
-    cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
-
-    s->mm_base = 0x48000000;
-    s->mm_regs[MDMRS >> 2] = 0x00020002;
-    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
-    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
-    iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn,
-                    pxa2xx_mm_writefn, s);
-    cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype);
-
-    for (i = 0; pxa27x_ssp[i].io_base; i ++);
-    s->ssp = (struct pxa2xx_ssp_s **)
-            qemu_mallocz(sizeof(struct pxa2xx_ssp_s *) * i);
-    ssp = (struct pxa2xx_ssp_s *)
-            qemu_mallocz(sizeof(struct pxa2xx_ssp_s) * i);
-    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
-        s->ssp[i] = &ssp[i];
-        ssp[i].base = pxa27x_ssp[i].io_base;
-        ssp[i].irq = pxa27x_ssp[i].irq;
-        ssp[i].pic = s->pic;
-
-        iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn,
-                        pxa2xx_ssp_writefn, &ssp[i]);
-        cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
-    }
-
-    if (usb_enabled) {
-        usb_ohci_init_memio(0x4c000000, 3, -1, s->pic, PXA2XX_PIC_USBH1);
-    }
-
-    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
-    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
-
-    s->rtc_base = 0x40900000;
-    iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s);
-    cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype);
-    pxa2xx_rtc_reset(s);
-
-    s->i2c[0] = pxa2xx_i2c_init(0x40301600, PXA2XX_PIC_I2C, s->pic);
-    s->i2c[1] = pxa2xx_i2c_init(0x40f00100, PXA2XX_PIC_PWRI2C, s->pic);
-
-    /* Register PM after PWRI2C to get the register mappings right.  */
-    s->pm_base = 0x40f00000;
-    iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn,
-                    pxa2xx_pm_writefn, s);
-    cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype);
-
-    s->i2s = pxa2xx_i2s_init(0x40400000, PXA2XX_PIC_I2S, s->pic, s->dma);
-
-    /* GPIO1 resets the processor */
-    /* The handler can be overriden by board-specific code */
-    pxa2xx_gpio_handler_set(s->gpio, 1, pxa2xx_reset, s);
-    return s;
-}
-
 #endif	/* PXA_H */

Added: trunk/src/host/qemu-neo1973/hw/pxa2xx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1944 @@
+/*
+ * Intel XScale PXA255/270 processor support.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * This code is licenced under the GPL.
+ */
+
+# include "vl.h"
+
+static struct {
+    target_phys_addr_t io_base;
+    int irqn;
+} pxa255_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0x41600000, PXA25X_PIC_HWUART },
+    { 0, 0 }
+}, pxa270_serial[] = {
+    { 0x40100000, PXA2XX_PIC_FFUART },
+    { 0x40200000, PXA2XX_PIC_BTUART },
+    { 0x40700000, PXA2XX_PIC_STUART },
+    { 0, 0 }
+};
+
+static struct {
+    target_phys_addr_t io_base;
+    int irqn;
+} pxa250_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0, 0 }
+}, pxa255_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0, 0 }
+}, pxa26x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41400000, PXA25X_PIC_NSSP },
+    { 0x41500000, PXA26X_PIC_ASSP },
+    { 0, 0 }
+}, pxa27x_ssp[] = {
+    { 0x41000000, PXA2XX_PIC_SSP },
+    { 0x41700000, PXA27X_PIC_SSP2 },
+    { 0x41900000, PXA2XX_PIC_SSP3 },
+    { 0, 0 }
+};
+
+#define PMCR	0x00	/* Power Manager Control register */
+#define PSSR	0x04	/* Power Manager Sleep Status register */
+#define PSPR	0x08	/* Power Manager Scratch-Pad register */
+#define PWER	0x0c	/* Power Manager Wake-Up Enable register */
+#define PRER	0x10	/* Power Manager Rising-Edge Detect Enable register */
+#define PFER	0x14	/* Power Manager Falling-Edge Detect Enable register */
+#define PEDR	0x18	/* Power Manager Edge-Detect Status register */
+#define PCFR	0x1c	/* Power Manager General Configuration register */
+#define PGSR0	0x20	/* Power Manager GPIO Sleep-State register 0 */
+#define PGSR1	0x24	/* Power Manager GPIO Sleep-State register 1 */
+#define PGSR2	0x28	/* Power Manager GPIO Sleep-State register 2 */
+#define PGSR3	0x2c	/* Power Manager GPIO Sleep-State register 3 */
+#define RCSR	0x30	/* Reset Controller Status register */
+#define PSLR	0x34	/* Power Manager Sleep Configuration register */
+#define PTSR	0x38	/* Power Manager Standby Configuration register */
+#define PVCR	0x40	/* Power Manager Voltage Change Control register */
+#define PUCR	0x4c	/* Power Manager USIM Card Control/Status register */
+#define PKWR	0x50	/* Power Manager Keyboard Wake-Up Enable register */
+#define PKSR	0x54	/* Power Manager Keyboard Level-Detect Status */
+#define PCMD0	0x80	/* Power Manager I2C Command register File 0 */
+#define PCMD31	0xfc	/* Power Manager I2C Command register File 31 */
+
+static uint32_t pxa2xx_i2c_read(void *, target_phys_addr_t);
+static void pxa2xx_i2c_write(void *, target_phys_addr_t, uint32_t);
+
+static uint32_t pxa2xx_pm_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    if (addr > s->pm_base + PCMD31) {
+        /* Special case: PWRI2C registers appear in the same range.  */
+        return pxa2xx_i2c_read(s->i2c[1], addr);
+    }
+    addr -= s->pm_base;
+
+    switch (addr) {
+    case PMCR ... PCMD31:
+        if (addr & 3)
+            goto fail;
+
+        return s->pm_regs[addr >> 2];
+    default:
+    fail:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    if (addr > s->pm_base + PCMD31) {
+        /* Special case: PWRI2C registers appear in the same range.  */
+        pxa2xx_i2c_write(s->i2c[1], addr, value);
+        return;
+    }
+    addr -= s->pm_base;
+
+    switch (addr) {
+    case PMCR:
+        s->pm_regs[addr >> 2] &= 0x15 & ~(value & 0x2a);
+        s->pm_regs[addr >> 2] |= value & 0x15;
+        break;
+
+    case PSSR:	/* Read-clean registers */
+    case RCSR:
+    case PKSR:
+        s->pm_regs[addr >> 2] &= ~value;
+        break;
+
+    default:	/* Read-write registers */
+        if (addr >= PMCR && addr <= PCMD31 && !(addr & 3)) {
+            s->pm_regs[addr >> 2] = value;
+            break;
+        }
+
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_pm_readfn[] = {
+    pxa2xx_pm_read,
+    pxa2xx_pm_read,
+    pxa2xx_pm_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_pm_writefn[] = {
+    pxa2xx_pm_write,
+    pxa2xx_pm_write,
+    pxa2xx_pm_write,
+};
+
+#define CCCR	0x00	/* Core Clock Configuration register */
+#define CKEN	0x04	/* Clock Enable register */
+#define OSCC	0x08	/* Oscillator Configuration register */
+#define CCSR	0x0c	/* Core Clock Status register */
+
+static uint32_t pxa2xx_cm_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->cm_base;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+    case OSCC:
+        return s->cm_regs[addr >> 2];
+
+    case CCSR:
+        return s->cm_regs[CCCR >> 2] | (3 << 28);
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_cm_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->cm_base;
+
+    switch (addr) {
+    case CCCR:
+    case CKEN:
+        s->cm_regs[addr >> 2] = value;
+        break;
+
+    case OSCC:
+        s->cm_regs[addr >> 2] &= ~0x6c;
+        s->cm_regs[addr >> 2] |= value & 0x6e;
+        if ((value >> 1) & 1)			/* OON */
+            s->cm_regs[addr >> 2] |= 1 << 0;	/* Oscillator is now stable */
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_cm_readfn[] = {
+    pxa2xx_cm_read,
+    pxa2xx_cm_read,
+    pxa2xx_cm_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_cm_writefn[] = {
+    pxa2xx_cm_write,
+    pxa2xx_cm_write,
+    pxa2xx_cm_write,
+};
+
+static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+
+    switch (reg) {
+    case 6:	/* Clock Configuration register */
+        return s->clkcfg;
+
+    case 7:	/* Power Mode register */
+        return 0;
+
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_clkpwr_write(void *opaque, int op2, int reg, int crm,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    static const char *pwrmode[8] = {
+        "Normal", "Idle", "Deep-idle", "Standby",
+        "Sleep", "reserved (!)", "reserved (!)", "Deep-sleep",
+    };
+
+    switch (reg) {
+    case 6:	/* Clock Configuration register */
+        s->clkcfg = value & 0xf;
+        if (value & 2)
+            printf("%s: CPU frequency change attempt\n", __FUNCTION__);
+        break;
+
+    case 7:	/* Power Mode register */
+        if (value & 8)
+            printf("%s: CPU voltage change attempt\n", __FUNCTION__);
+        switch (value & 7) {
+        case 0:
+            /* Do nothing */
+            break;
+
+        case 1:
+            /* Idle */
+            if (!(s->cm_regs[CCCR] & (1 << 31))) {	/* CPDIS */
+                cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+                break;
+            }
+            /* Fall through.  */
+
+        case 2:
+            /* Deep-Idle */
+            cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
+            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
+            goto message;
+
+        case 3:
+            s->env->uncached_cpsr =
+                    ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+            s->env->cp15.c1_sys = 0;
+            s->env->cp15.c1_coproc = 0;
+            s->env->cp15.c2_base = 0;
+            s->env->cp15.c3 = 0;
+            s->pm_regs[PSSR >> 2] |= 0x8;	/* Set STS */
+            s->pm_regs[RCSR >> 2] |= 0x8;	/* Set GPR */
+
+            /*
+             * The scratch-pad register is almost universally used
+             * for storing the return address on suspend.  For the
+             * lack of a resuming bootloader, perform a jump
+             * directly to that address.
+             */
+            memset(s->env->regs, 0, 4 * 15);
+            s->env->regs[15] = s->pm_regs[PSPR >> 2];
+
+#if 0
+            buffer = 0xe59ff000;	/* ldr     pc, [pc, #0] */
+            cpu_physical_memory_write(0, &buffer, 4);
+            buffer = s->pm_regs[PSPR >> 2];
+            cpu_physical_memory_write(8, &buffer, 4);
+#endif
+
+            /* Suspend */
+            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
+
+            goto message;
+
+        default:
+        message:
+            printf("%s: machine entered %s mode\n", __FUNCTION__,
+                            pwrmode[value & 7]);
+        }
+        break;
+
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+}
+
+/* Performace Monitoring Registers */
+#define CPPMNC		0	/* Performance Monitor Control register */
+#define CPCCNT		1	/* Clock Counter register */
+#define CPINTEN		4	/* Interrupt Enable register */
+#define CPFLAG		5	/* Overflow Flag register */
+#define CPEVTSEL	8	/* Event Selection register */
+
+#define CPPMN0		0	/* Performance Count register 0 */
+#define CPPMN1		1	/* Performance Count register 1 */
+#define CPPMN2		2	/* Performance Count register 2 */
+#define CPPMN3		3	/* Performance Count register 3 */
+
+static uint32_t pxa2xx_perf_read(void *opaque, int op2, int reg, int crm)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+
+    switch (reg) {
+    case CPPMNC:
+        return s->pmnc;
+    case CPCCNT:
+        if (s->pmnc & 1)
+            return qemu_get_clock(vm_clock);
+        else
+            return 0;
+    case CPINTEN:
+    case CPFLAG:
+    case CPEVTSEL:
+        return 0;
+
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_perf_write(void *opaque, int op2, int reg, int crm,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+
+    switch (reg) {
+    case CPPMNC:
+        s->pmnc = value;
+        break;
+
+    case CPCCNT:
+    case CPINTEN:
+    case CPFLAG:
+    case CPEVTSEL:
+        break;
+
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+}
+
+static uint32_t pxa2xx_cp14_read(void *opaque, int op2, int reg, int crm)
+{
+    switch (crm) {
+    case 0:
+        return pxa2xx_clkpwr_read(opaque, op2, reg, crm);
+    case 1:
+        return pxa2xx_perf_read(opaque, op2, reg, crm);
+    case 2:
+        switch (reg) {
+        case CPPMN0:
+        case CPPMN1:
+        case CPPMN2:
+        case CPPMN3:
+            return 0;
+        }
+        /* Fall through */
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_cp14_write(void *opaque, int op2, int reg, int crm,
+                uint32_t value)
+{
+    switch (crm) {
+    case 0:
+        pxa2xx_clkpwr_write(opaque, op2, reg, crm, value);
+        break;
+    case 1:
+        pxa2xx_perf_write(opaque, op2, reg, crm, value);
+        break;
+    case 2:
+        switch (reg) {
+        case CPPMN0:
+        case CPPMN1:
+        case CPPMN2:
+        case CPPMN3:
+            return;
+        }
+        /* Fall through */
+    default:
+        printf("%s: Bad register 0x%x\n", __FUNCTION__, reg);
+        break;
+    }
+}
+
+#define MDCNFG		0x00	/* SDRAM Configuration register */
+#define MDREFR		0x04	/* SDRAM Refresh Control register */
+#define MSC0		0x08	/* Static Memory Control register 0 */
+#define MSC1		0x0c	/* Static Memory Control register 1 */
+#define MSC2		0x10	/* Static Memory Control register 2 */
+#define MECR		0x14	/* Expansion Memory Bus Config register */
+#define SXCNFG		0x1c	/* Synchronous Static Memory Config register */
+#define MCMEM0		0x28	/* PC Card Memory Socket 0 Timing register */
+#define MCMEM1		0x2c	/* PC Card Memory Socket 1 Timing register */
+#define MCATT0		0x30	/* PC Card Attribute Socket 0 register */
+#define MCATT1		0x34	/* PC Card Attribute Socket 1 register */
+#define MCIO0		0x38	/* PC Card I/O Socket 0 Timing register */
+#define MCIO1		0x3c	/* PC Card I/O Socket 1 Timing register */
+#define MDMRS		0x40	/* SDRAM Mode Register Set Config register */
+#define BOOT_DEF	0x44	/* Boot-time Default Configuration register */
+#define ARB_CNTL	0x48	/* Arbiter Control register */
+#define BSCNTR0		0x4c	/* Memory Buffer Strength Control register 0 */
+#define BSCNTR1		0x50	/* Memory Buffer Strength Control register 1 */
+#define LCDBSCNTR	0x54	/* LCD Buffer Strength Control register */
+#define MDMRSLP		0x58	/* Low Power SDRAM Mode Set Config register */
+#define BSCNTR2		0x5c	/* Memory Buffer Strength Control register 2 */
+#define BSCNTR3		0x60	/* Memory Buffer Strength Control register 3 */
+#define SA1110		0x64	/* SA-1110 Memory Compatibility register */
+
+static uint32_t pxa2xx_mm_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->mm_base;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0)
+            return s->mm_regs[addr >> 2];
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_mm_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->mm_base;
+
+    switch (addr) {
+    case MDCNFG ... SA1110:
+        if ((addr & 3) == 0) {
+            s->mm_regs[addr >> 2] = value;
+            break;
+        }
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_mm_readfn[] = {
+    pxa2xx_mm_read,
+    pxa2xx_mm_read,
+    pxa2xx_mm_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_mm_writefn[] = {
+    pxa2xx_mm_write,
+    pxa2xx_mm_write,
+    pxa2xx_mm_write,
+};
+
+/* Synchronous Serial Ports */
+struct pxa2xx_ssp_s {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    int enable;
+
+    uint32_t sscr[2];
+    uint32_t sspsp;
+    uint32_t ssto;
+    uint32_t ssitr;
+    uint32_t sssr;
+    uint8_t sstsa;
+    uint8_t ssrsa;
+    uint8_t ssacd;
+
+    uint32_t rx_fifo[16];
+    int rx_level;
+    int rx_start;
+
+    uint32_t (*readfn)(void *opaque);
+    void (*writefn)(void *opaque, uint32_t value);
+    void *opaque;
+};
+
+#define SSCR0	0x00	/* SSP Control register 0 */
+#define SSCR1	0x04	/* SSP Control register 1 */
+#define SSSR	0x08	/* SSP Status register */
+#define SSITR	0x0c	/* SSP Interrupt Test register */
+#define SSDR	0x10	/* SSP Data register */
+#define SSTO	0x28	/* SSP Time-Out register */
+#define SSPSP	0x2c	/* SSP Programmable Serial Protocol register */
+#define SSTSA	0x30	/* SSP TX Time Slot Active register */
+#define SSRSA	0x34	/* SSP RX Time Slot Active register */
+#define SSTSS	0x38	/* SSP Time Slot Status register */
+#define SSACD	0x3c	/* SSP Audio Clock Divider register */
+
+/* Bitfields for above registers */
+#define SSCR0_SPI(x)	(((x) & 0x30) == 0x00)
+#define SSCR0_SSP(x)	(((x) & 0x30) == 0x10)
+#define SSCR0_UWIRE(x)	(((x) & 0x30) == 0x20)
+#define SSCR0_PSP(x)	(((x) & 0x30) == 0x30)
+#define SSCR0_SSE	(1 << 7)
+#define SSCR0_RIM	(1 << 22)
+#define SSCR0_TIM	(1 << 23)
+#define SSCR0_MOD	(1 << 31)
+#define SSCR0_DSS(x)	(((((x) >> 16) & 0x10) | ((x) & 0xf)) + 1)
+#define SSCR1_RIE	(1 << 0)
+#define SSCR1_TIE	(1 << 1)
+#define SSCR1_LBM	(1 << 2)
+#define SSCR1_MWDS	(1 << 5)
+#define SSCR1_TFT(x)	((((x) >> 6) & 0xf) + 1)
+#define SSCR1_RFT(x)	((((x) >> 10) & 0xf) + 1)
+#define SSCR1_EFWR	(1 << 14)
+#define SSCR1_PINTE	(1 << 18)
+#define SSCR1_TINTE	(1 << 19)
+#define SSCR1_RSRE	(1 << 20)
+#define SSCR1_TSRE	(1 << 21)
+#define SSCR1_EBCEI	(1 << 29)
+#define SSITR_INT	(7 << 5)
+#define SSSR_TNF	(1 << 2)
+#define SSSR_RNE	(1 << 3)
+#define SSSR_TFS	(1 << 5)
+#define SSSR_RFS	(1 << 6)
+#define SSSR_ROR	(1 << 7)
+#define SSSR_PINT	(1 << 18)
+#define SSSR_TINT	(1 << 19)
+#define SSSR_EOC	(1 << 20)
+#define SSSR_TUR	(1 << 21)
+#define SSSR_BCE	(1 << 23)
+#define SSSR_RW		0x00bc0080
+
+static void pxa2xx_ssp_int_update(struct pxa2xx_ssp_s *s)
+{
+    int level = 0;
+
+    level |= s->ssitr & SSITR_INT;
+    level |= (s->sssr & SSSR_BCE)  &&  (s->sscr[1] & SSCR1_EBCEI);
+    level |= (s->sssr & SSSR_TUR)  && !(s->sscr[0] & SSCR0_TIM);
+    level |= (s->sssr & SSSR_EOC)  &&  (s->sssr & (SSSR_TINT | SSSR_PINT));
+    level |= (s->sssr & SSSR_TINT) &&  (s->sscr[1] & SSCR1_TINTE);
+    level |= (s->sssr & SSSR_PINT) &&  (s->sscr[1] & SSCR1_PINTE);
+    level |= (s->sssr & SSSR_ROR)  && !(s->sscr[0] & SSCR0_RIM);
+    level |= (s->sssr & SSSR_RFS)  &&  (s->sscr[1] & SSCR1_RIE);
+    level |= (s->sssr & SSSR_TFS)  &&  (s->sscr[1] & SSCR1_TIE);
+    qemu_set_irq(s->irq, !!level);
+}
+
+static void pxa2xx_ssp_fifo_update(struct pxa2xx_ssp_s *s)
+{
+    s->sssr &= ~(0xf << 12);	/* Clear RFL */
+    s->sssr &= ~(0xf << 8);	/* Clear TFL */
+    s->sssr &= ~SSSR_TNF;
+    if (s->enable) {
+        s->sssr |= ((s->rx_level - 1) & 0xf) << 12;
+        if (s->rx_level >= SSCR1_RFT(s->sscr[1]))
+            s->sssr |= SSSR_RFS;
+        else
+            s->sssr &= ~SSSR_RFS;
+        if (0 <= SSCR1_TFT(s->sscr[1]))
+            s->sssr |= SSSR_TFS;
+        else
+            s->sssr &= ~SSSR_TFS;
+        if (s->rx_level)
+            s->sssr |= SSSR_RNE;
+        else
+            s->sssr &= ~SSSR_RNE;
+        s->sssr |= SSSR_TNF;
+    }
+
+    pxa2xx_ssp_int_update(s);
+}
+
+static uint32_t pxa2xx_ssp_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
+    uint32_t retval;
+    addr -= s->base;
+
+    switch (addr) {
+    case SSCR0:
+        return s->sscr[0];
+    case SSCR1:
+        return s->sscr[1];
+    case SSPSP:
+        return s->sspsp;
+    case SSTO:
+        return s->ssto;
+    case SSITR:
+        return s->ssitr;
+    case SSSR:
+        return s->sssr | s->ssitr;
+    case SSDR:
+        if (!s->enable)
+            return 0xffffffff;
+        if (s->rx_level < 1) {
+            printf("%s: SSP Rx Underrun\n", __FUNCTION__);
+            return 0xffffffff;
+        }
+        s->rx_level --;
+        retval = s->rx_fifo[s->rx_start ++];
+        s->rx_start &= 0xf;
+        pxa2xx_ssp_fifo_update(s);
+        return retval;
+    case SSTSA:
+        return s->sstsa;
+    case SSRSA:
+        return s->ssrsa;
+    case SSTSS:
+        return 0;
+    case SSACD:
+        return s->ssacd;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_ssp_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
+    addr -= s->base;
+
+    switch (addr) {
+    case SSCR0:
+        s->sscr[0] = value & 0xc7ffffff;
+        s->enable = value & SSCR0_SSE;
+        if (value & SSCR0_MOD)
+            printf("%s: Attempt to use network mode\n", __FUNCTION__);
+        if (s->enable && SSCR0_DSS(value) < 4)
+            printf("%s: Wrong data size: %i bits\n", __FUNCTION__,
+                            SSCR0_DSS(value));
+        if (!(value & SSCR0_SSE)) {
+            s->sssr = 0;
+            s->ssitr = 0;
+            s->rx_level = 0;
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSCR1:
+        s->sscr[1] = value;
+        if (value & (SSCR1_LBM | SSCR1_EFWR))
+            printf("%s: Attempt to use SSP test mode\n", __FUNCTION__);
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSPSP:
+        s->sspsp = value;
+        break;
+
+    case SSTO:
+        s->ssto = value;
+        break;
+
+    case SSITR:
+        s->ssitr = value & SSITR_INT;
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSSR:
+        s->sssr &= ~(value & SSSR_RW);
+        pxa2xx_ssp_int_update(s);
+        break;
+
+    case SSDR:
+        if (SSCR0_UWIRE(s->sscr[0])) {
+            if (s->sscr[1] & SSCR1_MWDS)
+                value &= 0xffff;
+            else
+                value &= 0xff;
+        } else
+            /* Note how 32bits overflow does no harm here */
+            value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
+
+        /* Data goes from here to the Tx FIFO and is shifted out from
+         * there directly to the slave, no need to buffer it.
+         */
+        if (s->enable) {
+            if (s->writefn)
+                s->writefn(s->opaque, value);
+
+            if (s->rx_level < 0x10) {
+                if (s->readfn)
+                    s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] =
+                            s->readfn(s->opaque);
+                else
+                    s->rx_fifo[(s->rx_start + s->rx_level ++) & 0xf] = 0x0;
+            } else
+                s->sssr |= SSSR_ROR;
+        }
+        pxa2xx_ssp_fifo_update(s);
+        break;
+
+    case SSTSA:
+        s->sstsa = value;
+        break;
+
+    case SSRSA:
+        s->ssrsa = value;
+        break;
+
+    case SSACD:
+        s->ssacd = value;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+}
+
+void pxa2xx_ssp_attach(struct pxa2xx_ssp_s *port,
+                uint32_t (*readfn)(void *opaque),
+                void (*writefn)(void *opaque, uint32_t value), void *opaque)
+{
+    if (!port) {
+        printf("%s: no such SSP\n", __FUNCTION__);
+        exit(-1);
+    }
+
+    port->opaque = opaque;
+    port->readfn = readfn;
+    port->writefn = writefn;
+}
+
+static CPUReadMemoryFunc *pxa2xx_ssp_readfn[] = {
+    pxa2xx_ssp_read,
+    pxa2xx_ssp_read,
+    pxa2xx_ssp_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_ssp_writefn[] = {
+    pxa2xx_ssp_write,
+    pxa2xx_ssp_write,
+    pxa2xx_ssp_write,
+};
+
+/* Real-Time Clock */
+#define RCNR		0x00	/* RTC Counter register */
+#define RTAR		0x04	/* RTC Alarm register */
+#define RTSR		0x08	/* RTC Status register */
+#define RTTR		0x0c	/* RTC Timer Trim register */
+#define RDCR		0x10	/* RTC Day Counter register */
+#define RYCR		0x14	/* RTC Year Counter register */
+#define RDAR1		0x18	/* RTC Wristwatch Day Alarm register 1 */
+#define RYAR1		0x1c	/* RTC Wristwatch Year Alarm register 1 */
+#define RDAR2		0x20	/* RTC Wristwatch Day Alarm register 2 */
+#define RYAR2		0x24	/* RTC Wristwatch Year Alarm register 2 */
+#define SWCR		0x28	/* RTC Stopwatch Counter register */
+#define SWAR1		0x2c	/* RTC Stopwatch Alarm register 1 */
+#define SWAR2		0x30	/* RTC Stopwatch Alarm register 2 */
+#define RTCPICR		0x34	/* RTC Periodic Interrupt Counter register */
+#define PIAR		0x38	/* RTC Periodic Interrupt Alarm register */
+
+static inline void pxa2xx_rtc_int_update(struct pxa2xx_state_s *s)
+{
+    qemu_set_irq(s->pic[PXA2XX_PIC_RTCALARM], !!(s->rtsr & 0x2553));
+}
+
+static void pxa2xx_rtc_hzupdate(struct pxa2xx_state_s *s)
+{
+    int64_t rt = qemu_get_clock(rt_clock);
+    s->last_rcnr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_rdcr += ((rt - s->last_hz) << 15) /
+            (1000 * ((s->rttr & 0xffff) + 1));
+    s->last_hz = rt;
+}
+
+static void pxa2xx_rtc_swupdate(struct pxa2xx_state_s *s)
+{
+    int64_t rt = qemu_get_clock(rt_clock);
+    if (s->rtsr & (1 << 12))
+        s->last_swcr += (rt - s->last_sw) / 10;
+    s->last_sw = rt;
+}
+
+static void pxa2xx_rtc_piupdate(struct pxa2xx_state_s *s)
+{
+    int64_t rt = qemu_get_clock(rt_clock);
+    if (s->rtsr & (1 << 15))
+        s->last_swcr += rt - s->last_pi;
+    s->last_pi = rt;
+}
+
+static inline void pxa2xx_rtc_alarm_update(struct pxa2xx_state_s *s,
+                uint32_t rtsr)
+{
+    if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
+        qemu_mod_timer(s->rtc_hz, s->last_hz +
+                (((s->rtar - s->last_rcnr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15));
+    else
+        qemu_del_timer(s->rtc_hz);
+
+    if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
+        qemu_mod_timer(s->rtc_rdal1, s->last_hz +
+                (((s->rdar1 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal1);
+
+    if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
+        qemu_mod_timer(s->rtc_rdal2, s->last_hz +
+                (((s->rdar2 - s->last_rdcr) * 1000 *
+                  ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_rdal2);
+
+    if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
+        qemu_mod_timer(s->rtc_swal1, s->last_sw +
+                        (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal1);
+
+    if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
+        qemu_mod_timer(s->rtc_swal2, s->last_sw +
+                        (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
+    else
+        qemu_del_timer(s->rtc_swal2);
+
+    if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
+        qemu_mod_timer(s->rtc_pi, s->last_pi +
+                        (s->piar & 0xffff) - s->last_rtcpicr);
+    else
+        qemu_del_timer(s->rtc_pi);
+}
+
+static inline void pxa2xx_rtc_hz_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 0);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal1_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 4);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_rdal2_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 6);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal1_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 8);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_swal2_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 10);
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static inline void pxa2xx_rtc_pi_tick(void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    s->rtsr |= (1 << 13);
+    pxa2xx_rtc_piupdate(s);
+    s->last_rtcpicr = 0;
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+    pxa2xx_rtc_int_update(s);
+}
+
+static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->rtc_base;
+
+    switch (addr) {
+    case RTTR:
+        return s->rttr;
+    case RTSR:
+        return s->rtsr;
+    case RTAR:
+        return s->rtar;
+    case RDAR1:
+        return s->rdar1;
+    case RDAR2:
+        return s->rdar2;
+    case RYAR1:
+        return s->ryar1;
+    case RYAR2:
+        return s->ryar2;
+    case SWAR1:
+        return s->swar1;
+    case SWAR2:
+        return s->swar2;
+    case PIAR:
+        return s->piar;
+    case RCNR:
+        return s->last_rcnr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    case RDCR:
+        return s->last_rdcr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) /
+                (1000 * ((s->rttr & 0xffff) + 1));
+    case RYCR:
+        return s->last_rycr;
+    case SWCR:
+        if (s->rtsr & (1 << 12))
+            return s->last_swcr + (qemu_get_clock(rt_clock) - s->last_sw) / 10;
+        else
+            return s->last_swcr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    addr -= s->rtc_base;
+
+    switch (addr) {
+    case RTTR:
+        if (!(s->rttr & (1 << 31))) {
+            pxa2xx_rtc_hzupdate(s);
+            s->rttr = value;
+            pxa2xx_rtc_alarm_update(s, s->rtsr);
+        }
+        break;
+
+    case RTSR:
+        if ((s->rtsr ^ value) & (1 << 15))
+            pxa2xx_rtc_piupdate(s);
+
+        if ((s->rtsr ^ value) & (1 << 12))
+            pxa2xx_rtc_swupdate(s);
+
+        if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac))
+            pxa2xx_rtc_alarm_update(s, value);
+
+        s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac));
+        pxa2xx_rtc_int_update(s);
+        break;
+
+    case RTAR:
+        s->rtar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR1:
+        s->rdar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDAR2:
+        s->rdar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR1:
+        s->ryar1 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYAR2:
+        s->ryar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR1:
+        pxa2xx_rtc_swupdate(s);
+        s->swar1 = value;
+        s->last_swcr = 0;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case SWAR2:
+        s->swar2 = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case PIAR:
+        s->piar = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RCNR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rcnr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RDCR:
+        pxa2xx_rtc_hzupdate(s);
+        s->last_rdcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RYCR:
+        s->last_rycr = value;
+        break;
+
+    case SWCR:
+        pxa2xx_rtc_swupdate(s);
+        s->last_swcr = value;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    case RTCPICR:
+        pxa2xx_rtc_piupdate(s);
+        s->last_rtcpicr = value & 0xffff;
+        pxa2xx_rtc_alarm_update(s, s->rtsr);
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static void pxa2xx_rtc_reset(struct pxa2xx_state_s *s)
+{
+    struct tm *tm;
+    time_t ti;
+    int wom;
+
+    s->rttr = 0x7fff;
+    s->rtsr = 0;
+
+    time(&ti);
+    if (rtc_utc)
+        tm = gmtime(&ti);
+    else
+        tm = localtime(&ti);
+    wom = ((tm->tm_mday - 1) / 7) + 1;
+
+    s->last_rcnr = (uint32_t) ti;
+    s->last_rdcr = (wom << 20) | ((tm->tm_wday + 1) << 17) |
+            (tm->tm_hour << 12) | (tm->tm_min << 6) | tm->tm_sec;
+    s->last_rycr = ((tm->tm_year + 1900) << 9) |
+            ((tm->tm_mon + 1) << 5) | tm->tm_mday;
+    s->last_swcr = (tm->tm_hour << 19) |
+            (tm->tm_min << 13) | (tm->tm_sec << 7);
+    s->last_rtcpicr = 0;
+    s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock);
+
+    s->rtc_hz    = qemu_new_timer(rt_clock, pxa2xx_rtc_hz_tick,    s);
+    s->rtc_rdal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal1_tick, s);
+    s->rtc_rdal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal2_tick, s);
+    s->rtc_swal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal1_tick, s);
+    s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s);
+    s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
+}
+
+static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = {
+    pxa2xx_rtc_read,
+    pxa2xx_rtc_read,
+    pxa2xx_rtc_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {
+    pxa2xx_rtc_write,
+    pxa2xx_rtc_write,
+    pxa2xx_rtc_write,
+};
+
+/* I2C Interface */
+#define IBMR	0x80	/* I2C Bus Monitor register */
+#define IDBR	0x88	/* I2C Data Buffer register */
+#define ICR	0x90	/* I2C Control register */
+#define ISR	0x98	/* I2C Status register */
+#define ISAR	0xa0	/* I2C Slave Address register */
+
+static void pxa2xx_i2c_update(struct pxa2xx_i2c_s *s)
+{
+    uint16_t level = 0;
+    level |= s->status & s->control & (1 << 10);		/* BED */
+    level |= (s->status & (1 << 7)) && (s->control & (1 << 9));	/* IRF */
+    level |= (s->status & (1 << 6)) && (s->control & (1 << 8));	/* ITE */
+    level |= s->status & (1 << 9);				/* SAD */
+    qemu_set_irq(s->irq, !!level);
+}
+
+/* These are only stubs now.  */
+static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->status |= (1 << 9);				/* set SAD */
+        s->status &= ~(1 << 0);				/* clear RWM */
+        break;
+    case I2C_START_RECV:
+        s->status |= (1 << 9);				/* set SAD */
+        s->status |= 1 << 0;				/* set RWM */
+        break;
+    case I2C_FINISH:
+        s->status |= (1 << 4);				/* set SSD */
+        break;
+    case I2C_NACK:
+        s->status |= 1 << 1;				/* set ACKNAK */
+        break;
+    }
+    pxa2xx_i2c_update(s);
+}
+
+static int pxa2xx_i2c_rx(i2c_slave *i2c)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 0;
+
+    if (s->status & (1 << 0)) {			/* RWM */
+        s->status |= 1 << 6;			/* set ITE */
+    }
+    pxa2xx_i2c_update(s);
+
+    return s->data;
+}
+
+static int pxa2xx_i2c_tx(i2c_slave *i2c, uint8_t data)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c;
+    if ((s->control & (1 << 14)) || !(s->control & (1 << 6)))
+        return 1;
+
+    if (!(s->status & (1 << 0))) {		/* RWM */
+        s->status |= 1 << 7;			/* set IRF */
+        s->data = data;
+    }
+    pxa2xx_i2c_update(s);
+
+    return 1;
+}
+
+static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
+    addr -= s->base;
+
+    switch (addr) {
+    case ICR:
+        return s->control;
+    case ISR:
+        return s->status | (i2c_bus_busy(s->bus) << 2);
+    case ISAR:
+        return s->slave.address;
+    case IDBR:
+        return s->data;
+    case IBMR:
+        if (s->status & (1 << 2))
+            s->ibmr ^= 3;	/* Fake SCL and SDA pin changes */
+        else
+            s->ibmr = 0;
+        return s->ibmr;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
+    int ack;
+    addr -= s->base;
+
+    switch (addr) {
+    case ICR:
+        s->control = value & 0xfff7;
+        if ((value & (1 << 3)) && (value & (1 << 6))) {	/* TB and IUE */
+            /* TODO: slave mode */
+            if (value & (1 << 0)) {			/* START condition */
+                if (s->data & 1)
+                    s->status |= 1 << 0;		/* set RWM */
+                else
+                    s->status &= ~(1 << 0);		/* clear RWM */
+                ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1);
+            } else {
+                if (s->status & (1 << 0)) {		/* RWM */
+                    s->data = i2c_recv(s->bus);
+                    if (value & (1 << 2))		/* ACKNAK */
+                        i2c_nack(s->bus);
+                    ack = 1;
+                } else
+                    ack = !i2c_send(s->bus, s->data);
+            }
+
+            if (value & (1 << 1))			/* STOP condition */
+                i2c_end_transfer(s->bus);
+
+            if (ack) {
+                if (value & (1 << 0))			/* START condition */
+                    s->status |= 1 << 6;		/* set ITE */
+                else
+                    if (s->status & (1 << 0))		/* RWM */
+                        s->status |= 1 << 7;		/* set IRF */
+                    else
+                        s->status |= 1 << 6;		/* set ITE */
+                s->status &= ~(1 << 1);			/* clear ACKNAK */
+            } else {
+                s->status |= 1 << 6;			/* set ITE */
+                s->status |= 1 << 10;			/* set BED */
+                s->status |= 1 << 1;			/* set ACKNAK */
+            }
+        }
+        if (!(value & (1 << 3)) && (value & (1 << 6)))	/* !TB and IUE */
+            if (value & (1 << 4))			/* MA */
+                i2c_end_transfer(s->bus);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISR:
+        s->status &= ~(value & 0x07f0);
+        pxa2xx_i2c_update(s);
+        break;
+
+    case ISAR:
+        i2c_set_slave_address(&s->slave, value & 0x7f);
+        break;
+
+    case IDBR:
+        s->data = value & 0xff;
+        break;
+
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_i2c_readfn[] = {
+    pxa2xx_i2c_read,
+    pxa2xx_i2c_read,
+    pxa2xx_i2c_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_i2c_writefn[] = {
+    pxa2xx_i2c_write,
+    pxa2xx_i2c_write,
+    pxa2xx_i2c_write,
+};
+
+static struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base,
+                qemu_irq irq, int ioregister)
+{
+    int iomemtype;
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *)
+            qemu_mallocz(sizeof(struct pxa2xx_i2c_s));
+
+    s->base = base;
+    s->irq = irq;
+    s->slave.event = pxa2xx_i2c_event;
+    s->slave.recv = pxa2xx_i2c_rx;
+    s->slave.send = pxa2xx_i2c_tx;
+    s->bus = i2c_init_bus();
+
+    if (ioregister) {
+        iomemtype = cpu_register_io_memory(0, pxa2xx_i2c_readfn,
+                        pxa2xx_i2c_writefn, s);
+        cpu_register_physical_memory(s->base & 0xfffff000, 0xfff, iomemtype);
+    }
+
+    return s;
+}
+
+/* PXA Inter-IC Sound Controller */
+static void pxa2xx_i2s_reset(struct pxa2xx_i2s_s *i2s)
+{
+    i2s->rx_len = 0;
+    i2s->tx_len = 0;
+    i2s->fifo_len = 0;
+    i2s->clk = 0x1a;
+    i2s->control[0] = 0x00;
+    i2s->control[1] = 0x00;
+    i2s->status = 0x00;
+    i2s->mask = 0x00;
+}
+
+#define SACR_TFTH(val)	((val >> 8) & 0xf)
+#define SACR_RFTH(val)	((val >> 12) & 0xf)
+#define SACR_DREC(val)	(val & (1 << 3))
+#define SACR_DPRL(val)	(val & (1 << 4))
+
+static inline void pxa2xx_i2s_update(struct pxa2xx_i2s_s *i2s)
+{
+    int rfs, tfs;
+    rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len &&
+            !SACR_DREC(i2s->control[1]);
+    tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) &&
+            i2s->enable && !SACR_DPRL(i2s->control[1]);
+
+    pxa2xx_dma_request(i2s->dma, PXA2XX_RX_RQ_I2S, rfs);
+    pxa2xx_dma_request(i2s->dma, PXA2XX_TX_RQ_I2S, tfs);
+
+    i2s->status &= 0xe0;
+    if (i2s->rx_len)
+        i2s->status |= 1 << 1;			/* RNE */
+    if (i2s->enable)
+        i2s->status |= 1 << 2;			/* BSY */
+    if (tfs)
+        i2s->status |= 1 << 3;			/* TFS */
+    if (rfs)
+        i2s->status |= 1 << 4;			/* RFS */
+    if (!(i2s->tx_len && i2s->enable))
+        i2s->status |= i2s->fifo_len << 8;	/* TFL */
+    i2s->status |= MAX(i2s->rx_len, 0xf) << 12;	/* RFL */
+
+    qemu_set_irq(i2s->irq, i2s->status & i2s->mask);
+}
+
+#define SACR0	0x00	/* Serial Audio Global Control register */
+#define SACR1	0x04	/* Serial Audio I2S/MSB-Justified Control register */
+#define SASR0	0x0c	/* Serial Audio Interface and FIFO Status register */
+#define SAIMR	0x14	/* Serial Audio Interrupt Mask register */
+#define SAICR	0x18	/* Serial Audio Interrupt Clear register */
+#define SADIV	0x60	/* Serial Audio Clock Divider register */
+#define SADR	0x80	/* Serial Audio Data register */
+
+static uint32_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
+    addr -= s->base;
+
+    switch (addr) {
+    case SACR0:
+        return s->control[0];
+    case SACR1:
+        return s->control[1];
+    case SASR0:
+        return s->status;
+    case SAIMR:
+        return s->mask;
+    case SAICR:
+        return 0;
+    case SADIV:
+        return s->clk;
+    case SADR:
+        if (s->rx_len > 0) {
+            s->rx_len --;
+            pxa2xx_i2s_update(s);
+            return s->codec_in(s->opaque);
+        }
+        return 0;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
+    uint32_t *sample;
+    addr -= s->base;
+
+    switch (addr) {
+    case SACR0:
+        if (value & (1 << 3))				/* RST */
+            pxa2xx_i2s_reset(s);
+        s->control[0] = value & 0xff3d;
+        if (!s->enable && (value & 1) && s->tx_len) {	/* ENB */
+            for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++)
+                s->codec_out(s->opaque, *sample);
+            s->status &= ~(1 << 7);			/* I2SOFF */
+        }
+        if (value & (1 << 4))				/* EFWR */
+            printf("%s: Attempt to use special function\n", __FUNCTION__);
+        s->enable = ((value ^ 4) & 5) == 5;		/* ENB && !RST*/
+        pxa2xx_i2s_update(s);
+        break;
+    case SACR1:
+        s->control[1] = value & 0x0039;
+        if (value & (1 << 5))				/* ENLBF */
+            printf("%s: Attempt to use loopback function\n", __FUNCTION__);
+        if (value & (1 << 4))				/* DPRL */
+            s->fifo_len = 0;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAIMR:
+        s->mask = value & 0x0078;
+        pxa2xx_i2s_update(s);
+        break;
+    case SAICR:
+        s->status &= ~(value & (3 << 5));
+        pxa2xx_i2s_update(s);
+        break;
+    case SADIV:
+        s->clk = value & 0x007f;
+        break;
+    case SADR:
+        if (s->tx_len && s->enable) {
+            s->tx_len --;
+            pxa2xx_i2s_update(s);
+            s->codec_out(s->opaque, value);
+        } else if (s->fifo_len < 16) {
+            s->fifo[s->fifo_len ++] = value;
+            pxa2xx_i2s_update(s);
+        }
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_i2s_readfn[] = {
+    pxa2xx_i2s_read,
+    pxa2xx_i2s_read,
+    pxa2xx_i2s_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_i2s_writefn[] = {
+    pxa2xx_i2s_write,
+    pxa2xx_i2s_write,
+    pxa2xx_i2s_write,
+};
+
+static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
+{
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
+    uint32_t *sample;
+
+    /* Signal FIFO errors */
+    if (s->enable && s->tx_len)
+        s->status |= 1 << 5;		/* TUR */
+    if (s->enable && s->rx_len)
+        s->status |= 1 << 6;		/* ROR */
+
+    /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to
+     * handle the cases where it makes a difference.  */
+    s->tx_len = tx - s->fifo_len;
+    s->rx_len = rx;
+    /* Note that is s->codec_out wasn't set, we wouldn't get called.  */
+    if (s->enable)
+        for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++)
+            s->codec_out(s->opaque, *sample);
+    pxa2xx_i2s_update(s);
+}
+
+static struct pxa2xx_i2s_s *pxa2xx_i2s_init(target_phys_addr_t base,
+                qemu_irq irq, struct pxa2xx_dma_state_s *dma)
+{
+    int iomemtype;
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *)
+            qemu_mallocz(sizeof(struct pxa2xx_i2s_s));
+
+    s->base = base;
+    s->irq = irq;
+    s->dma = dma;
+    s->data_req = pxa2xx_i2s_data_req;
+
+    pxa2xx_i2s_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, pxa2xx_i2s_readfn,
+                    pxa2xx_i2s_writefn, s);
+    cpu_register_physical_memory(s->base & 0xfff00000, 0xfffff, iomemtype);
+
+    return s;
+}
+
+/* PXA Fast Infra-red Communications Port */
+struct pxa2xx_fir_s {
+    target_phys_addr_t base;
+    qemu_irq irq;
+    struct pxa2xx_dma_state_s *dma;
+    int enable;
+    CharDriverState *chr;
+
+    uint8_t control[3];
+    uint8_t status[2];
+
+    int rx_len;
+    int rx_start;
+    uint8_t rx_fifo[64];
+};
+
+static void pxa2xx_fir_reset(struct pxa2xx_fir_s *s)
+{
+    s->control[0] = 0x00;
+    s->control[1] = 0x00;
+    s->control[2] = 0x00;
+    s->status[0] = 0x00;
+    s->status[1] = 0x00;
+    s->enable = 0;
+}
+
+static inline void pxa2xx_fir_update(struct pxa2xx_fir_s *s)
+{
+    static const int tresh[4] = { 8, 16, 32, 0 };
+    int intr = 0;
+    if ((s->control[0] & (1 << 4)) &&			/* RXE */
+                    s->rx_len >= tresh[s->control[2] & 3])	/* TRIG */
+        s->status[0] |= 1 << 4;				/* RFS */
+    else
+        s->status[0] &= ~(1 << 4);			/* RFS */
+    if (s->control[0] & (1 << 3))			/* TXE */
+        s->status[0] |= 1 << 3;				/* TFS */
+    else
+        s->status[0] &= ~(1 << 3);			/* TFS */
+    if (s->rx_len)
+        s->status[1] |= 1 << 2;				/* RNE */
+    else
+        s->status[1] &= ~(1 << 2);			/* RNE */
+    if (s->control[0] & (1 << 4))			/* RXE */
+        s->status[1] |= 1 << 0;				/* RSY */
+    else
+        s->status[1] &= ~(1 << 0);			/* RSY */
+
+    intr |= (s->control[0] & (1 << 5)) &&		/* RIE */
+            (s->status[0] & (1 << 4));			/* RFS */
+    intr |= (s->control[0] & (1 << 6)) &&		/* TIE */
+            (s->status[0] & (1 << 3));			/* TFS */
+    intr |= (s->control[2] & (1 << 4)) &&		/* TRAIL */
+            (s->status[0] & (1 << 6));			/* EOC */
+    intr |= (s->control[0] & (1 << 2)) &&		/* TUS */
+            (s->status[0] & (1 << 1));			/* TUR */
+    intr |= s->status[0] & 0x25;			/* FRE, RAB, EIF */
+
+    pxa2xx_dma_request(s->dma, PXA2XX_RX_RQ_ICP, (s->status[0] >> 4) & 1);
+    pxa2xx_dma_request(s->dma, PXA2XX_TX_RQ_ICP, (s->status[0] >> 3) & 1);
+
+    qemu_set_irq(s->irq, intr && s->enable);
+}
+
+#define ICCR0	0x00	/* FICP Control register 0 */
+#define ICCR1	0x04	/* FICP Control register 1 */
+#define ICCR2	0x08	/* FICP Control register 2 */
+#define ICDR	0x0c	/* FICP Data register */
+#define ICSR0	0x14	/* FICP Status register 0 */
+#define ICSR1	0x18	/* FICP Status register 1 */
+#define ICFOR	0x1c	/* FICP FIFO Occupancy Status register */
+
+static uint32_t pxa2xx_fir_read(void *opaque, target_phys_addr_t addr)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    uint8_t ret;
+    addr -= s->base;
+
+    switch (addr) {
+    case ICCR0:
+        return s->control[0];
+    case ICCR1:
+        return s->control[1];
+    case ICCR2:
+        return s->control[2];
+    case ICDR:
+        s->status[0] &= ~0x01;
+        s->status[1] &= ~0x72;
+        if (s->rx_len) {
+            s->rx_len --;
+            ret = s->rx_fifo[s->rx_start ++];
+            s->rx_start &= 63;
+            pxa2xx_fir_update(s);
+            return ret;
+        }
+        printf("%s: Rx FIFO underrun.\n", __FUNCTION__);
+        break;
+    case ICSR0:
+        return s->status[0];
+    case ICSR1:
+        return s->status[1] | (1 << 3);			/* TNF */
+    case ICFOR:
+        return s->rx_len;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+        break;
+    }
+    return 0;
+}
+
+static void pxa2xx_fir_write(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    uint8_t ch;
+    addr -= s->base;
+
+    switch (addr) {
+    case ICCR0:
+        s->control[0] = value;
+        if (!(value & (1 << 4)))			/* RXE */
+            s->rx_len = s->rx_start = 0;
+        if (!(value & (1 << 3)))			/* TXE */
+            /* Nop */;
+        s->enable = value & 1;				/* ITR */
+        if (!s->enable)
+            s->status[0] = 0;
+        pxa2xx_fir_update(s);
+        break;
+    case ICCR1:
+        s->control[1] = value;
+        break;
+    case ICCR2:
+        s->control[2] = value & 0x3f;
+        pxa2xx_fir_update(s);
+        break;
+    case ICDR:
+        if (s->control[2] & (1 << 2))			/* TXP */
+            ch = value;
+        else
+            ch = ~value;
+        if (s->chr && s->enable && (s->control[0] & (1 << 3)))	/* TXE */
+            qemu_chr_write(s->chr, &ch, 1);
+        break;
+    case ICSR0:
+        s->status[0] &= ~(value & 0x66);
+        pxa2xx_fir_update(s);
+        break;
+    case ICFOR:
+        break;
+    default:
+        printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr);
+    }
+}
+
+static CPUReadMemoryFunc *pxa2xx_fir_readfn[] = {
+    pxa2xx_fir_read,
+    pxa2xx_fir_read,
+    pxa2xx_fir_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_fir_writefn[] = {
+    pxa2xx_fir_write,
+    pxa2xx_fir_write,
+    pxa2xx_fir_write,
+};
+
+static int pxa2xx_fir_is_empty(void *opaque)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    return (s->rx_len < 64);
+}
+
+static void pxa2xx_fir_rx(void *opaque, const uint8_t *buf, int size)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    if (!(s->control[0] & (1 << 4)))			/* RXE */
+        return;
+
+    while (size --) {
+        s->status[1] |= 1 << 4;				/* EOF */
+        if (s->rx_len >= 64) {
+            s->status[1] |= 1 << 6;			/* ROR */
+            break;
+        }
+
+        if (s->control[2] & (1 << 3))			/* RXP */
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = *(buf ++);
+        else
+            s->rx_fifo[(s->rx_start + s->rx_len ++) & 63] = ~*(buf ++);
+    }
+
+    pxa2xx_fir_update(s);
+}
+
+static void pxa2xx_fir_event(void *opaque, int event)
+{
+}
+
+static struct pxa2xx_fir_s *pxa2xx_fir_init(target_phys_addr_t base,
+                qemu_irq irq, struct pxa2xx_dma_state_s *dma,
+                CharDriverState *chr)
+{
+    int iomemtype;
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *)
+            qemu_mallocz(sizeof(struct pxa2xx_fir_s));
+
+    s->base = base;
+    s->irq = irq;
+    s->dma = dma;
+    s->chr = chr;
+
+    pxa2xx_fir_reset(s);
+
+    iomemtype = cpu_register_io_memory(0, pxa2xx_fir_readfn,
+                    pxa2xx_fir_writefn, s);
+    cpu_register_physical_memory(s->base, 0xfff, iomemtype);
+
+    if (chr)
+        qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
+                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
+
+    return s;
+}
+
+void pxa2xx_reset(int line, int level, void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    if (level && (s->pm_regs[PCFR >> 2] & 0x10)) {	/* GPR_EN */
+        cpu_reset(s->env);
+        /* TODO: reset peripherals */
+    }
+}
+
+/* Initialise a PXA270 integrated chip (ARM based core).  */
+struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size,
+                DisplayState *ds, const char *revision)
+{
+    struct pxa2xx_state_s *s;
+    struct pxa2xx_ssp_s *ssp;
+    int iomemtype, i;
+    s = (struct pxa2xx_state_s *) qemu_mallocz(sizeof(struct pxa2xx_state_s));
+
+    if (revision && strncmp(revision, "pxa27", 5)) {
+        fprintf(stderr, "Machine requires a PXA27x processor.\n");
+        exit(1);
+    }
+
+    s->env = cpu_init();
+    cpu_arm_set_model(s->env, revision ?: "pxa270");
+
+    /* SDRAM & Internal Memory Storage */
+    cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
+                    sdram_size, qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+    cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
+                    0x40000, qemu_ram_alloc(0x40000) | IO_MEM_RAM);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+
+    s->dma = pxa27x_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
+
+    pxa27x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0],
+                    s->pic[PXA27X_PIC_OST_4_11], s->env);
+
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
+
+    s->mmc = pxa2xx_mmci_init(0x41100000, s->pic[PXA2XX_PIC_MMC], s->dma);
+
+    for (i = 0; pxa270_serial[i].io_base; i ++)
+        if (serial_hds[i])
+            serial_mm_init(pxa270_serial[i].io_base, 2,
+                            s->pic[pxa270_serial[i].irqn], serial_hds[i], 1);
+        else
+            break;
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
+                        s->dma, serial_hds[i]);
+
+    if (ds)
+        s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD], ds);
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 4] = 0x02000210;	/* 416.0 MHz */
+    s->clkcfg = 0x00000009;		/* Turbo mode active */
+    iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn,
+                    pxa2xx_cm_writefn, s);
+    cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype);
+
+    cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
+    iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn,
+                    pxa2xx_mm_writefn, s);
+    cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype);
+
+    for (i = 0; pxa27x_ssp[i].io_base; i ++);
+    s->ssp = (struct pxa2xx_ssp_s **)
+            qemu_mallocz(sizeof(struct pxa2xx_ssp_s *) * i);
+    ssp = (struct pxa2xx_ssp_s *)
+            qemu_mallocz(sizeof(struct pxa2xx_ssp_s) * i);
+    for (i = 0; pxa27x_ssp[i].io_base; i ++) {
+        s->ssp[i] = &ssp[i];
+        ssp[i].base = pxa27x_ssp[i].io_base;
+        ssp[i].irq = s->pic[pxa27x_ssp[i].irqn];
+
+        iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn,
+                        pxa2xx_ssp_writefn, &ssp[i]);
+        cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
+    }
+
+    if (usb_enabled) {
+        usb_ohci_init_memio(0x4c000000, 3, -1, s->pic[PXA2XX_PIC_USBH1]);
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+
+    s->rtc_base = 0x40900000;
+    iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
+                    pxa2xx_rtc_writefn, s);
+    cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype);
+    pxa2xx_rtc_reset(s);
+
+    /* Note that PM registers are in the same page with PWRI2C registers.
+     * As a workaround we don't map PWRI2C into memory and we expect
+     * PM handlers to call PWRI2C handlers when appropriate.  */
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 1);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0);
+
+    s->pm_base = 0x40f00000;
+    iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn,
+                    pxa2xx_pm_writefn, s);
+    cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype);
+
+    s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
+
+    /* GPIO1 resets the processor */
+    /* The handler can be overriden by board-specific code */
+    pxa2xx_gpio_handler_set(s->gpio, 1, pxa2xx_reset, s);
+    return s;
+}
+
+/* Initialise a PXA255 integrated chip (ARM based core).  */
+struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size,
+                DisplayState *ds)
+{
+    struct pxa2xx_state_s *s;
+    struct pxa2xx_ssp_s *ssp;
+    int iomemtype, i;
+    s = (struct pxa2xx_state_s *) qemu_mallocz(sizeof(struct pxa2xx_state_s));
+
+    s->env = cpu_init();
+    cpu_arm_set_model(s->env, "pxa255");
+
+    /* SDRAM & Internal Memory Storage */
+    cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
+                    sdram_size, qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+    cpu_register_physical_memory(PXA2XX_INTERNAL_BASE,
+                    0x40000, qemu_ram_alloc(0x40000) | IO_MEM_RAM);
+
+    s->pic = pxa2xx_pic_init(0x40d00000, s->env);
+
+    s->dma = pxa255_dma_init(0x40000000, s->pic[PXA2XX_PIC_DMA]);
+
+    pxa25x_timer_init(0x40a00000, &s->pic[PXA2XX_PIC_OST_0], s->env);
+
+    s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
+
+    s->mmc = pxa2xx_mmci_init(0x41100000, s->pic[PXA2XX_PIC_MMC], s->dma);
+
+    for (i = 0; pxa255_serial[i].io_base; i ++)
+        if (serial_hds[i])
+            serial_mm_init(pxa255_serial[i].io_base, 2,
+                            s->pic[pxa255_serial[i].irqn], serial_hds[i], 1);
+        else
+            break;
+    if (serial_hds[i])
+        s->fir = pxa2xx_fir_init(0x40800000, s->pic[PXA2XX_PIC_ICP],
+                        s->dma, serial_hds[i]);
+
+    if (ds)
+        s->lcd = pxa2xx_lcdc_init(0x44000000, s->pic[PXA2XX_PIC_LCD], ds);
+
+    s->cm_base = 0x41300000;
+    s->cm_regs[CCCR >> 4] = 0x02000210;	/* 416.0 MHz */
+    s->clkcfg = 0x00000009;		/* Turbo mode active */
+    iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn,
+                    pxa2xx_cm_writefn, s);
+    cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype);
+
+    cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
+
+    s->mm_base = 0x48000000;
+    s->mm_regs[MDMRS >> 2] = 0x00020002;
+    s->mm_regs[MDREFR >> 2] = 0x03ca4000;
+    s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
+    iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn,
+                    pxa2xx_mm_writefn, s);
+    cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype);
+
+    for (i = 0; pxa255_ssp[i].io_base; i ++);
+    s->ssp = (struct pxa2xx_ssp_s **)
+            qemu_mallocz(sizeof(struct pxa2xx_ssp_s *) * i);
+    ssp = (struct pxa2xx_ssp_s *)
+            qemu_mallocz(sizeof(struct pxa2xx_ssp_s) * i);
+    for (i = 0; pxa255_ssp[i].io_base; i ++) {
+        s->ssp[i] = &ssp[i];
+        ssp[i].base = pxa255_ssp[i].io_base;
+        ssp[i].irq = s->pic[pxa255_ssp[i].irqn];
+
+        iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn,
+                        pxa2xx_ssp_writefn, &ssp[i]);
+        cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
+    }
+
+    if (usb_enabled) {
+        usb_ohci_init_memio(0x4c000000, 3, -1, s->pic[PXA2XX_PIC_USBH1]);
+    }
+
+    s->pcmcia[0] = pxa2xx_pcmcia_init(0x20000000);
+    s->pcmcia[1] = pxa2xx_pcmcia_init(0x30000000);
+
+    s->rtc_base = 0x40900000;
+    iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
+                    pxa2xx_rtc_writefn, s);
+    cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype);
+    pxa2xx_rtc_reset(s);
+
+    s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 1);
+    s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0);
+
+    s->pm_base = 0x40f00000;
+    iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn,
+                    pxa2xx_pm_writefn, s);
+    cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype);
+
+    s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
+
+    /* GPIO1 resets the processor */
+    /* The handler can be overriden by board-specific code */
+    pxa2xx_gpio_handler_set(s->gpio, 1, pxa2xx_reset, s);
+    return s;
+}

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -19,16 +19,13 @@
     int request;
 };
 
-/* The first element of an individual PIC state structures should
- * be a pointer to the handler routine.  We allow the DMA to be used
- * as a PIC. */
+/* Allow the DMA to be used as a PIC.  */
 typedef void (*pxa2xx_dma_handler_t)(void *opaque, int irq, int level);
 
 struct pxa2xx_dma_state_s {
     pxa2xx_dma_handler_t handler;
     target_phys_addr_t base;
-    void *pic;
-    int irq;
+    qemu_irq irq;
 
     uint32_t stopintr;
     uint32_t eorintr;
@@ -53,19 +50,19 @@
 
 #define PXA2XX_DMA_NUM_REQUESTS	75
 
-#define DCSR0	0x0000	/* DMA Control / Status Register for Channel 0 */
-#define DCSR31	0x007c	/* DMA Control / Status Register for Channel 31 */
-#define DALGN	0x00a0	/* DMA Alignment Register */
-#define DPCSR	0x00a4	/* DMA Programmed I/O Control Status Register */
-#define DRQSR0	0x00e0	/* DMA DREQ<0> Status Register */
-#define DRQSR1	0x00e4	/* DMA DREQ<1> Status Register */
-#define DRQSR2	0x00e8	/* DMA DREQ<2> Status Register */
-#define DINT	0x00f0	/* DMA Interrupt Register */
-#define DRCMR0	0x0100	/* Request to Channel Map Register 0 */
-#define DRCMR63	0x01fc	/* Request to Channel Map Register 63 */
+#define DCSR0	0x0000	/* DMA Control / Status register for Channel 0 */
+#define DCSR31	0x007c	/* DMA Control / Status register for Channel 31 */
+#define DALGN	0x00a0	/* DMA Alignment register */
+#define DPCSR	0x00a4	/* DMA Programmed I/O Control Status register */
+#define DRQSR0	0x00e0	/* DMA DREQ<0> Status register */
+#define DRQSR1	0x00e4	/* DMA DREQ<1> Status register */
+#define DRQSR2	0x00e8	/* DMA DREQ<2> Status register */
+#define DINT	0x00f0	/* DMA Interrupt register */
+#define DRCMR0	0x0100	/* Request to Channel Map register 0 */
+#define DRCMR63	0x01fc	/* Request to Channel Map register 63 */
 #define D_CH0	0x0200	/* Channel 0 Descriptor start */
-#define DRCMR64	0x1100	/* Request to Channel Map Register 64 */
-#define DRCMR74	0x1128	/* Request to Channel Map Register 74 */
+#define DRCMR64	0x1100	/* Request to Channel Map register 64 */
+#define DRCMR74	0x1128	/* Request to Channel Map register 74 */
 
 /* Per-channel register */
 #define DDADR	0x00
@@ -142,9 +139,9 @@
     }
 
     if (s->stopintr | s->eorintr | s->rasintr | s->startintr | s->endintr)
-        pic_set_irq_new(s->pic, s->irq, 1);
+        qemu_irq_raise(s->irq);
     else
-        pic_set_irq_new(s->pic, s->irq, 0);
+        qemu_irq_lower(s->irq);
 }
 
 static inline void pxa2xx_dma_descriptor_fetch(
@@ -305,7 +302,8 @@
         }
     }
 
-    cpu_abort(cpu_single_env, "%s: Bad offset 0x%04x\n", __FUNCTION__, offset);
+    cpu_abort(cpu_single_env,
+                    "%s: Bad offset 0x%04lx\n", __FUNCTION__, offset);
     return 7;
 }
 
@@ -403,7 +401,7 @@
             break;
         }
     fail:
-        cpu_abort(cpu_single_env, "%s: Bad offset 0x%04x\n",
+        cpu_abort(cpu_single_env, "%s: Bad offset 0x%04lx\n",
                 __FUNCTION__, offset);
     }
 }
@@ -433,7 +431,7 @@
 };
 
 static struct pxa2xx_dma_state_s *pxa2xx_dma_init(target_phys_addr_t base,
-                void *pic, int irq, int channels)
+                qemu_irq irq, int channels)
 {
     int i, iomemtype;
     struct pxa2xx_dma_state_s *s;
@@ -443,7 +441,6 @@
     s->channels = channels;
     s->chan = qemu_mallocz(sizeof(struct pxa2xx_dma_channel_s) * s->channels);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     s->handler = (pxa2xx_dma_handler_t) pxa2xx_dma_request;
     s->req = qemu_mallocz(sizeof(int) * PXA2XX_DMA_NUM_REQUESTS);
@@ -462,15 +459,15 @@
 }
 
 struct pxa2xx_dma_state_s *pxa27x_dma_init(target_phys_addr_t base,
-                void *pic, int irq)
+                qemu_irq irq)
 {
-    return pxa2xx_dma_init(base, pic, irq, PXA27X_DMA_NUM_CHANNELS);
+    return pxa2xx_dma_init(base, irq, PXA27X_DMA_NUM_CHANNELS);
 }
 
 struct pxa2xx_dma_state_s *pxa255_dma_init(target_phys_addr_t base,
-                void *pic, int irq)
+                qemu_irq irq)
 {
-    return pxa2xx_dma_init(base, pic, irq, PXA255_DMA_NUM_CHANNELS);
+    return pxa2xx_dma_init(base, irq, PXA255_DMA_NUM_CHANNELS);
 }
 
 void pxa2xx_dma_request(struct pxa2xx_dma_state_s *s, int req_num, int on)

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -13,7 +13,7 @@
 
 struct pxa2xx_gpio_info_s {
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq *pic;
     int lines;
     CPUState *cpu_env;
 
@@ -69,19 +69,19 @@
 static void pxa2xx_gpio_irq_update(struct pxa2xx_gpio_info_s *s)
 {
     if (s->status[0] & (1 << 0))
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_0, 1);
+        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_0]);
     else
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_0, 0);
+        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_0]);
 
     if (s->status[0] & (1 << 1))
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_1, 1);
+        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_1]);
     else
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_1, 0);
+        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_1]);
 
     if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_X, 1);
+        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_X]);
     else
-        pic_set_irq_new(s->pic, PXA2XX_PIC_GPIO_X, 0);
+        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_X]);
 }
 
 /* Bitmap of pins used as standby and sleep wake-up sources.  */
@@ -149,34 +149,34 @@
 
     bank = pxa2xx_gpio_regs[offset].bank;
     switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:		/* GPIO Pin-Direction Registers */
+    case GPDR:		/* GPIO Pin-Direction registers */
         return s->dir[bank];
 
-    case GRER:		/* GPIO Rising-Edge Detect Enable Registers */
+    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
         return s->rising[bank];
 
-    case GFER:		/* GPIO Falling-Edge Detect Enable Registers */
+    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
         return s->falling[bank];
 
-    case GAFR_L:	/* GPIO Alternate Function Registers */
+    case GAFR_L:	/* GPIO Alternate Function registers */
         return s->gafr[bank * 2];
 
-    case GAFR_U:	/* GPIO Alternate Function Registers */
+    case GAFR_U:	/* GPIO Alternate Function registers */
         return s->gafr[bank * 2 + 1];
 
-    case GPLR:		/* GPIO Pin-Level Registers */
+    case GPLR:		/* GPIO Pin-Level registers */
         ret = (s->olevel[bank] & s->dir[bank]) |
                 (s->ilevel[bank] & ~s->dir[bank]);
         if (s->read_notify)
             s->read_notify(s->opaque);
         return ret;
 
-    case GEDR:		/* GPIO Edge Detect Status Registers */
+    case GEDR:		/* GPIO Edge Detect Status registers */
         return s->status[bank];
 
     default:
         cpu_abort(cpu_single_env,
-                "%s: Bad offset %x\n", __FUNCTION__, offset);
+                "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
     }
 
     return 0;
@@ -193,45 +193,45 @@
 
     bank = pxa2xx_gpio_regs[offset].bank;
     switch (pxa2xx_gpio_regs[offset].reg) {
-    case GPDR:		/* GPIO Pin-Direction Registers */
+    case GPDR:		/* GPIO Pin-Direction registers */
         s->dir[bank] = value;
         pxa2xx_gpio_handler_update(s);
         break;
 
-    case GPSR:		/* GPIO Pin-Output Set Registers */
+    case GPSR:		/* GPIO Pin-Output Set registers */
         s->olevel[bank] |= value;
         pxa2xx_gpio_handler_update(s);
         break;
 
-    case GPCR:		/* GPIO Pin-Output Clear Registers */
+    case GPCR:		/* GPIO Pin-Output Clear registers */
         s->olevel[bank] &= ~value;
         pxa2xx_gpio_handler_update(s);
         break;
 
-    case GRER:		/* GPIO Rising-Edge Detect Enable Registers */
+    case GRER:		/* GPIO Rising-Edge Detect Enable registers */
         s->rising[bank] = value;
         break;
 
-    case GFER:		/* GPIO Falling-Edge Detect Enable Registers */
+    case GFER:		/* GPIO Falling-Edge Detect Enable registers */
         s->falling[bank] = value;
         break;
 
-    case GAFR_L:	/* GPIO Alternate Function Registers */
+    case GAFR_L:	/* GPIO Alternate Function registers */
         s->gafr[bank * 2] = value;
         break;
 
-    case GAFR_U:	/* GPIO Alternate Function Registers */
+    case GAFR_U:	/* GPIO Alternate Function registers */
         s->gafr[bank * 2 + 1] = value;
         break;
 
-    case GEDR:		/* GPIO Edge Detect Status Registers */
+    case GEDR:		/* GPIO Edge Detect Status registers */
         s->status[bank] &= ~value;
         pxa2xx_gpio_irq_update(s);
         break;
 
     default:
         cpu_abort(cpu_single_env,
-                "%s: Bad offset %x\n", __FUNCTION__, offset);
+                "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
     }
 }
 
@@ -248,7 +248,7 @@
 };
 
 struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, void *pic, int lines)
+                CPUState *env, qemu_irq *pic, int lines)
 {
     int iomemtype;
     struct pxa2xx_gpio_info_s *s;

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -13,7 +13,7 @@
 
 struct pxa2xx_lcdc_s {
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq irq;
     int irqlevel;
 
     int invalidated;
@@ -73,44 +73,44 @@
     uint32_t ldcmd;
 };
 
-#define LCCR0	0x000	/* LCD Controller Control Register 0 */
-#define LCCR1	0x004	/* LCD Controller Control Register 1 */
-#define LCCR2	0x008	/* LCD Controller Control Register 2 */
-#define LCCR3	0x00c	/* LCD Controller Control Register 3 */
-#define LCCR4	0x010	/* LCD Controller Control Register 4 */
-#define LCCR5	0x014	/* LCD Controller Control Register 5 */
+#define LCCR0	0x000	/* LCD Controller Control register 0 */
+#define LCCR1	0x004	/* LCD Controller Control register 1 */
+#define LCCR2	0x008	/* LCD Controller Control register 2 */
+#define LCCR3	0x00c	/* LCD Controller Control register 3 */
+#define LCCR4	0x010	/* LCD Controller Control register 4 */
+#define LCCR5	0x014	/* LCD Controller Control register 5 */
 
-#define FBR0	0x020	/* DMA Channel 0 Frame Branch Register */
-#define FBR1	0x024	/* DMA Channel 1 Frame Branch Register */
-#define FBR2	0x028	/* DMA Channel 2 Frame Branch Register */
-#define FBR3	0x02c	/* DMA Channel 3 Frame Branch Register */
-#define FBR4	0x030	/* DMA Channel 4 Frame Branch Register */
-#define FBR5	0x110	/* DMA Channel 5 Frame Branch Register */
-#define FBR6	0x114	/* DMA Channel 6 Frame Branch Register */
+#define FBR0	0x020	/* DMA Channel 0 Frame Branch register */
+#define FBR1	0x024	/* DMA Channel 1 Frame Branch register */
+#define FBR2	0x028	/* DMA Channel 2 Frame Branch register */
+#define FBR3	0x02c	/* DMA Channel 3 Frame Branch register */
+#define FBR4	0x030	/* DMA Channel 4 Frame Branch register */
+#define FBR5	0x110	/* DMA Channel 5 Frame Branch register */
+#define FBR6	0x114	/* DMA Channel 6 Frame Branch register */
 
-#define LCSR1	0x034	/* LCD Controller Status Register 1 */
-#define LCSR0	0x038	/* LCD Controller Status Register 0 */
-#define LIIDR	0x03c	/* LCD Controller Interrupt ID Register */
+#define LCSR1	0x034	/* LCD Controller Status register 1 */
+#define LCSR0	0x038	/* LCD Controller Status register 0 */
+#define LIIDR	0x03c	/* LCD Controller Interrupt ID register */
 
-#define TRGBR	0x040	/* TMED RGB Seed Register */
-#define TCR	0x044	/* TMED Control Register */
+#define TRGBR	0x040	/* TMED RGB Seed register */
+#define TCR	0x044	/* TMED Control register */
 
-#define OVL1C1	0x050	/* Overlay 1 Control Register 1 */
-#define OVL1C2	0x060	/* Overlay 1 Control Register 2 */
-#define OVL2C1	0x070	/* Overlay 2 Control Register 1 */
-#define OVL2C2	0x080	/* Overlay 2 Control Register 2 */
-#define CCR	0x090	/* Cursor Control Register */
+#define OVL1C1	0x050	/* Overlay 1 Control register 1 */
+#define OVL1C2	0x060	/* Overlay 1 Control register 2 */
+#define OVL2C1	0x070	/* Overlay 2 Control register 1 */
+#define OVL2C2	0x080	/* Overlay 2 Control register 2 */
+#define CCR	0x090	/* Cursor Control register */
 
-#define CMDCR	0x100	/* Command Control Register */
-#define PRSR	0x104	/* Panel Read Status Register */
+#define CMDCR	0x100	/* Command Control register */
+#define PRSR	0x104	/* Panel Read Status register */
 
 #define PXA_LCDDMA_CHANS	7
-#define DMA_FDADR		0x00	/* Frame Descriptor Address Register */
-#define DMA_FSADR		0x04	/* Frame Source Address Register */
-#define DMA_FIDR		0x08	/* Frame ID Register */
-#define DMA_LDCMD		0x0c	/* Command Register */
+#define DMA_FDADR		0x00	/* Frame Descriptor Address register */
+#define DMA_FSADR		0x04	/* Frame Source Address register */
+#define DMA_FIDR		0x08	/* Frame ID register */
+#define DMA_LDCMD		0x0c	/* Command register */
 
-/* LCD Buffer Strength Control Register */
+/* LCD Buffer Strength Control register */
 #define BSCNTR	0x04000054
 
 /* Bitfield masks */
@@ -190,7 +190,7 @@
     level |= (s->status[0] & LCSR0_CMDINT) && !(s->control[0] & LCCR0_CMDIM);
     level |= (s->status[1] & ~s->control[5]);
 
-    pic_set_irq_new(s->pic, PXA2XX_PIC_LCD, !!level);
+    qemu_set_irq(s->irq, !!level);
     s->irqlevel = level;
 }
 
@@ -300,11 +300,11 @@
         } else
             descptr = s->dma_ch[i].descriptor;
 
-        if (!(descptr >= PXA2XX_RAM_BASE && descptr +
-                    sizeof(*desc[i]) <= PXA2XX_RAM_BASE + phys_ram_size))
+        if (!(descptr >= PXA2XX_SDRAM_BASE && descptr +
+                    sizeof(*desc[i]) <= PXA2XX_SDRAM_BASE + phys_ram_size))
             continue;
 
-        descptr -= PXA2XX_RAM_BASE;
+        descptr -= PXA2XX_SDRAM_BASE;
         desc[i] = (struct pxa_frame_descriptor_s *) (phys_ram_base + descptr);
         s->dma_ch[i].descriptor = desc[i]->fdaddr;
         s->dma_ch[i].source = desc[i]->fsaddr;
@@ -402,7 +402,7 @@
     default:
     fail:
         cpu_abort(cpu_single_env,
-                "%s: Bad offset %x\n", __FUNCTION__, offset);
+                "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
     }
 
     return 0;
@@ -559,7 +559,7 @@
     default:
     fail:
         cpu_abort(cpu_single_env,
-                "%s: Bad offset %x\n", __FUNCTION__, offset);
+                "%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
     }
 }
 
@@ -722,7 +722,7 @@
     dest_width = s->xres * s->dest_width;
 
     addr = (ram_addr_t) (fb - phys_ram_base);
-    start = addr + (s->yres + 1) * src_width;
+    start = addr + s->yres * src_width;
     end = addr;
     dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG);
     for (y = 0; y < s->yres; y ++) {
@@ -750,7 +750,8 @@
         dest += dest_width;
     }
 
-    cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
+    if (end > start)
+        cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
 }
 
 static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s,
@@ -793,8 +794,7 @@
                             dest, src, s->xres, -dest_width);
             if (addr < start)
                 start = addr;
-            if (new_addr > end)
-                end = new_addr;
+            end = new_addr;
             if (y < *miny)
                 *miny = y;
             if (y >= *maxy)
@@ -806,7 +806,8 @@
         dest += s->dest_width;
     }
 
-    cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
+    if (end > start)
+        cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG);
 }
 
 static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s)
@@ -853,12 +854,12 @@
                 continue;
             }
             fbptr = s->dma_ch[ch].source;
-            if (!(fbptr >= PXA2XX_RAM_BASE &&
-                    fbptr <= PXA2XX_RAM_BASE + phys_ram_size)) {
+            if (!(fbptr >= PXA2XX_SDRAM_BASE &&
+                    fbptr <= PXA2XX_SDRAM_BASE + phys_ram_size)) {
                 pxa2xx_dma_ber_set(s, ch);
                 continue;
             }
-            fbptr -= PXA2XX_RAM_BASE;
+            fbptr -= PXA2XX_SDRAM_BASE;
             fb = phys_ram_base + fbptr;
 
             if (s->dma_ch[ch].command & LDCMD_PAL) {
@@ -935,7 +936,7 @@
 #define BITS 32
 #include "pxa2xx_template.h"
 
-struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, void *pic,
+struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq,
                 DisplayState *ds)
 {
     int iomemtype;
@@ -944,7 +945,7 @@
     s = (struct pxa2xx_lcdc_s *) qemu_mallocz(sizeof(struct pxa2xx_lcdc_s));
     s->base = base;
     s->invalidated = 1;
-    s->pic = pic;
+    s->irq = irq;
     s->ds = ds;
 
     pxa2xx_lcdc_orientation(s, graphic_rotate);

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -12,10 +12,10 @@
 
 struct pxa2xx_mmci_s {
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq irq;
     void *dma;
 
-    struct sd_state_s *card;
+    SDState *card;
 
     uint32_t status;
     uint32_t clkrt;
@@ -45,26 +45,26 @@
     int ac_width;
 };
 
-#define MMC_STRPCL	0x00	/* MMC Clock Start/Stop Register */
-#define MMC_STAT	0x04	/* MMC Status Register */
-#define MMC_CLKRT	0x08	/* MMC Clock Rate Register */
-#define MMC_SPI		0x0c	/* MMC SPI Mode Register */
-#define MMC_CMDAT	0x10	/* MMC Command/Data Register */
-#define MMC_RESTO	0x14	/* MMC Response Time-Out Register */
-#define MMC_RDTO	0x18	/* MMC Read Time-Out Register */
-#define MMC_BLKLEN	0x1c	/* MMC Block Length Register */
-#define MMC_NUMBLK	0x20	/* MMC Number of Blocks Register */
-#define MMC_PRTBUF	0x24	/* MMC Buffer Partly Full Register */
-#define MMC_I_MASK	0x28	/* MMC Interrupt Mask Register */
-#define MMC_I_REG	0x2c	/* MMC Interrupt Request Register */
-#define MMC_CMD		0x30	/* MMC Command Register */
-#define MMC_ARGH	0x34	/* MMC Argument High Register */
-#define MMC_ARGL	0x38	/* MMC Argument Low Register */
+#define MMC_STRPCL	0x00	/* MMC Clock Start/Stop register */
+#define MMC_STAT	0x04	/* MMC Status register */
+#define MMC_CLKRT	0x08	/* MMC Clock Rate register */
+#define MMC_SPI		0x0c	/* MMC SPI Mode register */
+#define MMC_CMDAT	0x10	/* MMC Command/Data register */
+#define MMC_RESTO	0x14	/* MMC Response Time-Out register */
+#define MMC_RDTO	0x18	/* MMC Read Time-Out register */
+#define MMC_BLKLEN	0x1c	/* MMC Block Length register */
+#define MMC_NUMBLK	0x20	/* MMC Number of Blocks register */
+#define MMC_PRTBUF	0x24	/* MMC Buffer Partly Full register */
+#define MMC_I_MASK	0x28	/* MMC Interrupt Mask register */
+#define MMC_I_REG	0x2c	/* MMC Interrupt Request register */
+#define MMC_CMD		0x30	/* MMC Command register */
+#define MMC_ARGH	0x34	/* MMC Argument High register */
+#define MMC_ARGL	0x38	/* MMC Argument Low register */
 #define MMC_RES		0x3c	/* MMC Response FIFO */
 #define MMC_RXFIFO	0x40	/* MMC Receive FIFO */
 #define MMC_TXFIFO	0x44	/* MMC Transmit FIFO */
-#define MMC_RDWAIT	0x48	/* MMC RD_WAIT Register */
-#define MMC_BLKS_REM	0x4c	/* MMC Blocks Remaining Register */
+#define MMC_RDWAIT	0x48	/* MMC RD_WAIT register */
+#define MMC_BLKS_REM	0x4c	/* MMC Blocks Remaining register */
 
 /* Bitfield masks */
 #define STRPCL_STOP_CLK	(1 << 0)
@@ -102,13 +102,13 @@
     if (s->cmdat & CMDAT_DMA_EN) {
         mask |= INT_RXFIFO_REQ | INT_TXFIFO_REQ;
 
-        pic_set_irq_new(s->dma, PXA2XX_RX_RQ_MMCI,
-                        !!(s->intreq & INT_RXFIFO_REQ));
-        pic_set_irq_new(s->dma, PXA2XX_TX_RQ_MMCI,
-                        !!(s->intreq & INT_TXFIFO_REQ));
+        pxa2xx_dma_request((struct pxa2xx_dma_state_s *) s->dma,
+                        PXA2XX_RX_RQ_MMCI, !!(s->intreq & INT_RXFIFO_REQ));
+        pxa2xx_dma_request((struct pxa2xx_dma_state_s *) s->dma,
+                        PXA2XX_TX_RQ_MMCI, !!(s->intreq & INT_TXFIFO_REQ));
     }
 
-    pic_set_irq_new(s->pic, PXA2XX_PIC_MMC, !!(s->intreq & ~mask));
+    qemu_set_irq(s->irq, !!(s->intreq & ~mask));
 }
 
 static void pxa2xx_mmci_fifo_update(struct pxa2xx_mmci_s *s)
@@ -118,7 +118,7 @@
 
     if (s->cmdat & CMDAT_WR_RD) {
         while (s->bytesleft && s->tx_len) {
-            sd_write_datline(s->card, s->tx_fifo[s->tx_start ++]);
+            sd_write_data(s->card, s->tx_fifo[s->tx_start ++]);
             s->tx_start &= 0x1f;
             s->tx_len --;
             s->bytesleft --;
@@ -128,7 +128,7 @@
     } else
         while (s->bytesleft && s->rx_len < 32) {
             s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
-                sd_read_datline(s->card);
+                sd_read_data(s->card);
             s->bytesleft --;
             s->intreq |= INT_RXFIFO_REQ;
         }
@@ -149,9 +149,9 @@
 
 static void pxa2xx_mmci_wakequeues(struct pxa2xx_mmci_s *s)
 {
-    int rsplen;
+    int rsplen, i;
     struct sd_request_s request;
-    union sd_response_u response;
+    uint8_t response[16];
 
     s->active = 1;
     s->rx_len = 0;
@@ -162,53 +162,36 @@
     request.arg = s->arg;
     request.crc = 0;	/* FIXME */
 
-    response = sd_write_cmdline(s->card, request, &rsplen);
+    rsplen = sd_do_command(s->card, &request, response);
     s->intreq |= INT_END_CMD;
 
     memset(s->resp_fifo, 0, sizeof(s->resp_fifo));
     switch (s->cmdat & CMDAT_RES_TYPE) {
-#define PXAMMCI_RESP(wd, value)	\
-        s->resp_fifo[(wd) + 0] |= (value) >> 8;	\
-        s->resp_fifo[(wd) + 1] |= (value) << 8;
+#define PXAMMCI_RESP(wd, value0, value1)	\
+        s->resp_fifo[(wd) + 0] |= (value0);	\
+        s->resp_fifo[(wd) + 1] |= (value1) << 8;
     case 0:	/* No response */
         goto complete;
 
     case 1:	/* R1, R4, R5 or R6 */
-        if (rsplen < 48)
+        if (rsplen < 4)
             goto timeout;
-
-        if (request.cmd == 3) {	/* R6 */
-            PXAMMCI_RESP(0, response.r6.arg);
-            PXAMMCI_RESP(1, response.r6.status);
-        } else {
-            PXAMMCI_RESP(0, response.r1.status >> 16);
-            PXAMMCI_RESP(1, response.r1.status & 0x0000ffff);
-        }
         goto complete;
 
     case 2:	/* R2 */
-        if (rsplen < 128)
+        if (rsplen < 16)
             goto timeout;
-
-        PXAMMCI_RESP(0, bswap16(response.r2.reg[0]));
-        PXAMMCI_RESP(1, bswap16(response.r2.reg[1]));
-        PXAMMCI_RESP(2, bswap16(response.r2.reg[2]));
-        PXAMMCI_RESP(3, bswap16(response.r2.reg[3]));
-        PXAMMCI_RESP(4, bswap16(response.r2.reg[4]));
-        PXAMMCI_RESP(5, bswap16(response.r2.reg[5]));
-        PXAMMCI_RESP(6, bswap16(response.r2.reg[6]));
-        PXAMMCI_RESP(7, bswap16(response.r2.reg[7]));
         goto complete;
 
     case 3:	/* R3 */
-        if (rsplen < 32)
+        if (rsplen < 4)
             goto timeout;
-
-        PXAMMCI_RESP(0, response.r3.ocr_reg >> 16);
-        PXAMMCI_RESP(1, response.r3.ocr_reg & 0x0000ffff);
         goto complete;
 
     complete:
+        for (i = 0; rsplen > 0; i ++, rsplen -= 2) {
+            PXAMMCI_RESP(i, response[i * 2], response[i * 2 + 1]);
+        }
         s->status |= STAT_END_CMDRES;
 
         if (!(s->cmdat & CMDAT_DATA_EN))
@@ -284,7 +267,8 @@
     case MMC_BLKS_REM:
         return s->numblk;
     default:
-        cpu_abort(cpu_single_env, "%s: Bad offset %x\n", __FUNCTION__, offset);
+        cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
+                        __FUNCTION__, offset);
     }
 
     return 0;
@@ -397,7 +381,8 @@
         break;
 
     default:
-        cpu_abort(cpu_single_env, "%s: Bad offset %x\n", __FUNCTION__, offset);
+        cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
+                        __FUNCTION__, offset);
     }
 }
 
@@ -459,14 +444,14 @@
 };
 
 struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
-                void *pic, void *dma)
+                qemu_irq irq, void *dma)
 {
     int iomemtype;
     struct pxa2xx_mmci_s *s;
 
     s = (struct pxa2xx_mmci_s *) qemu_mallocz(sizeof(struct pxa2xx_mmci_s));
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
     s->dma = dma;
 
     iomemtype = cpu_register_io_memory(0, pxa2xx_mmci_readfn,
@@ -474,7 +459,7 @@
     cpu_register_physical_memory(base, 0x000fffff, iomemtype);
 
     /* Instantiate the actual storage */
-    s->card = sd_init();
+    s->card = sd_init(sd_bdrv);
 
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -16,10 +16,8 @@
     target_phys_addr_t attr_base;
     target_phys_addr_t io_base;
 
-    void *pic;
-    int irq;
-    int cd_irq;
-    void (*set_irq)(void *opaque, int line, int level);
+    qemu_irq irq;
+    qemu_irq cd_irq;
 };
 
 static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
@@ -133,10 +131,10 @@
 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
 {
     struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
-    if (!s->set_irq)
+    if (!s->irq)
         return;
 
-    s->set_irq(s->pic, s->irq, level);
+    qemu_set_irq(s->irq, level);
 }
 
 struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
@@ -171,8 +169,7 @@
         s->slot.slot_string = "PXA PC Card Socket 1";
     else
         s->slot.slot_string = "PXA PC Card Socket 0";
-    s->slot.opaque = s;
-    s->slot.set_irq = pxa2xx_pcmcia_set_irq;
+    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
     pcmcia_socket_register(&s->slot);
     return s;
 }
@@ -184,8 +181,8 @@
     if (s->slot.attached)
         return -EEXIST;
 
-    if (s->set_irq) {
-        s->set_irq(s->pic, s->cd_irq, 1);
+    if (s->cd_irq) {
+        qemu_irq_raise(s->cd_irq);
     }
 
     s->card = card;
@@ -210,21 +207,18 @@
 
     s->slot.attached = 0;
 
-    if (s->set_irq) {
-        s->set_irq(s->pic, s->irq, 0);
-        s->set_irq(s->pic, s->cd_irq, 0);
-    }
+    if (s->irq)
+        qemu_irq_lower(s->irq);
+    if (s->cd_irq)
+        qemu_irq_lower(s->cd_irq);
 
     return 0;
 }
 
 /* Who to notify on card events */
-void pxa2xx_pcmcia_set_irq_cb(void *opaque, void (*set_irq)(void *opaque,
-                        int line, int level), int irq, int cd_irq, void *pic)
+void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
 {
     struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
-    s->set_irq = set_irq;
-    s->pic = pic;
     s->irq = irq;
     s->cd_irq = cd_irq;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -27,24 +27,16 @@
 #define IPR32	0xb0	/* Interrupt Controller Priority register 32 */
 #define IPR39	0xcc	/* Interrupt Controller Priority register 39 */
 
-/* The first element of an individual PIC state structures should
- * be a pointer to the handler routine.  */
-typedef void (*pxa2xx_pic_handler_t)(void *opaque, int irq, int level);
-
 #define PXA2XX_PIC_SRCS	40
 
 struct pxa2xx_pic_state_s {
-    pxa2xx_pic_handler_t handler;
-    CPUState *cpu_env;
     target_phys_addr_t base;
+    CPUState *cpu_env;
     uint32_t int_enabled[2];
     uint32_t int_pending[2];
     uint32_t is_fiq[2];
     uint32_t int_idle;
     uint32_t priority[PXA2XX_PIC_SRCS];
-    void *parent;
-    int parent_irq;
-    int parent_fiq;
 };
 
 static void pxa2xx_pic_update(void *opaque)
@@ -156,7 +148,7 @@
     case ICHP:	/* Highest Priority register */
         return pxa2xx_pic_highest(s);
     default:
-        printf("%s: Bad register offset 0x%lx\n", __FUNCTION__, offset);
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
         return 0;
     }
 }
@@ -190,7 +182,7 @@
         s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
         break;
     default:
-        printf("%s: Bad register offset 0x%lx\n", __FUNCTION__, offset);
+        printf("%s: Bad register offset " REG_FMT "\n", __FUNCTION__, offset);
         return;
     }
     pxa2xx_pic_update(opaque);
@@ -253,11 +245,11 @@
     pxa2xx_pic_mem_write,
 };
 
-struct pxa2xx_pic_state_s *pxa2xx_pic_init(target_phys_addr_t base,
-                CPUState *env, int parent_irq, int parent_fiq)
+qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 {
     struct pxa2xx_pic_state_s *s;
     int iomemtype;
+    qemu_irq *qi;
 
     s = (struct pxa2xx_pic_state_s *)
             qemu_mallocz(sizeof(struct pxa2xx_pic_state_s));
@@ -273,8 +265,9 @@
     s->int_enabled[1] = 0;
     s->is_fiq[0] = 0;
     s->is_fiq[1] = 0;
-    s->handler = pxa2xx_pic_set_irq;
 
+    qi = qemu_allocate_irqs(pxa2xx_pic_set_irq, s, PXA2XX_PIC_SRCS);
+
     /* Enable IC memory-mapped registers access.  */
     iomemtype = cpu_register_io_memory(0, pxa2xx_pic_readfn,
                     pxa2xx_pic_writefn, s);
@@ -283,5 +276,5 @@
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
-    return s;
+    return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,38 +14,80 @@
 #define OSMR2	0x08
 #define OSMR3	0x0c
 #define OSMR4	0x80
+#define OSMR5	0x84
+#define OSMR6	0x88
+#define OSMR7	0x8c
+#define OSMR8	0x90
+#define OSMR9	0x94
+#define OSMR10	0x98
+#define OSMR11	0x9c
 #define OSCR	0x10	/* OS Timer Count */
 #define OSCR4	0x40
-#define OMCR4	0xc0
+#define OSCR5	0x44
+#define OSCR6	0x48
+#define OSCR7	0x4c
+#define OSCR8	0x50
+#define OSCR9	0x54
+#define OSCR10	0x58
+#define OSCR11	0x5c
 #define OSSR	0x14	/* Timer status register */
 #define OWER	0x18
 #define OIER	0x1c	/* Interrupt enable register  3-0 to E3-E0 */
+#define OMCR4	0xc0	/* OS Match Control registers */
+#define OMCR5	0xc4
+#define OMCR6	0xc8
+#define OMCR7	0xcc
+#define OMCR8	0xd0
+#define OMCR9	0xd4
+#define OMCR10	0xd8
+#define OMCR11	0xdc
+#define OSNR	0x20
 
 #define PXA25X_FREQ	3686400	/* 3.6864 MHz */
 #define PXA27X_FREQ	3250000	/* 3.25 MHz */
 
-typedef struct {
+static int pxa2xx_timer4_freq[8] = {
+    [0] = 0,
+    [1] = 32768,
+    [2] = 1000,
+    [3] = 1,
+    [4] = 1000000,
+    /* [5] is the "Externally supplied clock".  Assign if necessary.  */
+    [5 ... 7] = 0,
+};
+
+struct pxa2xx_timer0_s {
     uint32_t value;
     int level;
-    int irq;
-    void *pic;
+    qemu_irq irq;
     QEMUTimer *qtimer;
     int num;
     void *info;
-} pxa2xx_timer;
+};
 
+struct pxa2xx_timer4_s {
+    struct pxa2xx_timer0_s tm;
+    int32_t oldclock;
+    int32_t clock;
+    uint64_t lastload;
+    uint32_t freq;
+    uint32_t control;
+};
+
 typedef struct {
     uint32_t base;
     int32_t clock;
     int32_t oldclock;
     uint64_t lastload;
     uint32_t freq;
-    pxa2xx_timer timer[4];
+    struct pxa2xx_timer0_s timer[4];
+    struct pxa2xx_timer4_s *tm4;
     uint32_t events;
     uint32_t irq_enabled;
     uint32_t reset3;
     CPUState *cpustate;
     int64_t qemu_ticks;
+    uint32_t snapshot;
 } pxa2xx_timer_info;
 
 static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
@@ -65,28 +107,108 @@
     }
 }
 
+static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
+{
+    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    uint32_t now_vm;
+    uint64_t new_qemu;
+    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
+    int counter;
+
+    if (s->tm4[n].control & (1 << 7))
+        counter = n;
+    else
+        counter = counters[n];
+
+    if (!s->tm4[counter].freq) {
+        qemu_del_timer(s->timer[n].qtimer);
+        return;
+    }
+
+    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
+                    s->tm4[counter].lastload,
+                    s->tm4[counter].freq, ticks_per_sec);
+
+    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
+                    ticks_per_sec, s->tm4[counter].freq);
+    qemu_mod_timer(s->timer[n].qtimer, new_qemu);
+}
+
 static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 {
     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    int tm = 0;
 
     offset -= s->base;
 
     switch (offset) {
+    case OSMR3:  tm ++;
+    case OSMR2:  tm ++;
+    case OSMR1:  tm ++;
     case OSMR0:
-    case OSMR1:
-    case OSMR2:
-    case OSMR3:
-	return s->timer[offset >> 2].value;
+        return s->timer[tm].value;
+    case OSMR11: tm ++;
+    case OSMR10: tm ++;
+    case OSMR9:  tm ++;
+    case OSMR8:  tm ++;
+    case OSMR7:  tm ++;
+    case OSMR6:  tm ++;
+    case OSMR5:  tm ++;
+    case OSMR4:
+        if (!s->tm4)
+            goto badreg;
+        return s->tm4[tm].tm.value;
     case OSCR:
         return s->clock + muldiv64(qemu_get_clock(vm_clock) -
                         s->lastload, s->freq, ticks_per_sec);
+    case OSCR11: tm ++;
+    case OSCR10: tm ++;
+    case OSCR9:  tm ++;
+    case OSCR8:  tm ++;
+    case OSCR7:  tm ++;
+    case OSCR6:  tm ++;
+    case OSCR5:  tm ++;
+    case OSCR4:
+        if (!s->tm4)
+            goto badreg;
+
+        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
+            if (s->tm4[tm - 1].freq)
+                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
+                                qemu_get_clock(vm_clock) -
+                                s->tm4[tm - 1].lastload,
+                                s->tm4[tm - 1].freq, ticks_per_sec);
+            else
+                s->snapshot = s->tm4[tm - 1].clock;
+        }
+
+        if (!s->tm4[tm].freq)
+            return s->tm4[tm].clock;
+        return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
+                        s->tm4[tm].lastload, s->tm4[tm].freq, ticks_per_sec);
     case OIER:
         return s->irq_enabled;
+    case OSSR:	/* Status register */
+        return s->events;
     case OWER:
         return s->reset3;
+    case OMCR11: tm ++;
+    case OMCR10: tm ++;
+    case OMCR9:  tm ++;
+    case OMCR8:  tm ++;
+    case OMCR7:  tm ++;
+    case OMCR6:  tm ++;
+    case OMCR5:  tm ++;
+    case OMCR4:
+        if (!s->tm4)
+            goto badreg;
+        return s->tm4[tm].control;
+    case OSNR:
+        return s->snapshot;
     default:
-        cpu_abort(cpu_single_env,
-                        "pxa2xx_timer_read: Bad offset %x\n", offset);
+    badreg:
+        cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
+                        REG_FMT "\n", offset);
     }
 
     return 0;
@@ -95,43 +217,110 @@
 static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
                 uint32_t value)
 {
-    int i;
+    int i, tm = 0;
     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 
     offset -= s->base;
 
     switch (offset) {
+    case OSMR3:  tm ++;
+    case OSMR2:  tm ++;
+    case OSMR1:  tm ++;
     case OSMR0:
-    case OSMR1:
-    case OSMR2:
-    case OSMR3:
-        s->timer[offset >> 2].value = value;
+        s->timer[tm].value = value;
         pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
         break;
+    case OSMR11: tm ++;
+    case OSMR10: tm ++;
+    case OSMR9:  tm ++;
+    case OSMR8:  tm ++;
+    case OSMR7:  tm ++;
+    case OSMR6:  tm ++;
+    case OSMR5:  tm ++;
+    case OSMR4:
+        if (!s->tm4)
+            goto badreg;
+        s->tm4[tm].tm.value = value;
+        pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+        break;
     case OSCR:
         s->oldclock = s->clock;
         s->lastload = qemu_get_clock(vm_clock);
         s->clock = value;
         pxa2xx_timer_update(s, s->lastload);
         break;
+    case OSCR11: tm ++;
+    case OSCR10: tm ++;
+    case OSCR9:  tm ++;
+    case OSCR8:  tm ++;
+    case OSCR7:  tm ++;
+    case OSCR6:  tm ++;
+    case OSCR5:  tm ++;
+    case OSCR4:
+        if (!s->tm4)
+            goto badreg;
+        s->tm4[tm].oldclock = s->tm4[tm].clock;
+        s->tm4[tm].lastload = qemu_get_clock(vm_clock);
+        s->tm4[tm].clock = value;
+        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
+        break;
     case OIER:
-        s->irq_enabled = value;
+        s->irq_enabled = value & 0xfff;
         break;
     case OSSR:	/* Status register */
         s->events &= ~value;
-        for (i = 0; i < 4; i++) {
-            if (s->timer[i].level && (value & (1 << i))) {
+        for (i = 0; i < 4; i ++, value >>= 1) {
+            if (s->timer[i].level && (value & 1)) {
                 s->timer[i].level = 0;
-                pic_set_irq_new(s->timer[i].pic, s->timer[i].irq, 0);
+                qemu_irq_lower(s->timer[i].irq);
             }
         }
+        if (s->tm4) {
+            for (i = 0; i < 8; i ++, value >>= 1)
+                if (s->tm4[i].tm.level && (value & 1))
+                    s->tm4[i].tm.level = 0;
+            if (!(s->events & 0xff0))
+                qemu_irq_lower(s->tm4->tm.irq);
+        }
         break;
     case OWER:	/* XXX: Reset on OSMR3 match? */
         s->reset3 = value;
         break;
+    case OMCR7:  tm ++;
+    case OMCR6:  tm ++;
+    case OMCR5:  tm ++;
+    case OMCR4:
+        if (!s->tm4)
+            goto badreg;
+        s->tm4[tm].control = value & 0x0ff;
+        /* XXX Stop if running (shouldn't happen) */
+        if ((value & (1 << 7)) || tm == 0)
+            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
+        else {
+            s->tm4[tm].freq = 0;
+            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+        }
+        break;
+    case OMCR11: tm ++;
+    case OMCR10: tm ++;
+    case OMCR9:  tm ++;
+    case OMCR8:  tm += 4;
+        if (!s->tm4)
+            goto badreg;
+        s->tm4[tm].control = value & 0x3ff;
+        /* XXX Stop if running (shouldn't happen) */
+        if ((value & (1 << 7)) || !(tm & 1))
+            s->tm4[tm].freq =
+                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
+        else {
+            s->tm4[tm].freq = 0;
+            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
+        }
+        break;
     default:
-        cpu_abort(cpu_single_env,
-                        "pxa2xx_timer_write: Bad offset %x\n", offset);
+    badreg:
+        cpu_abort(cpu_single_env, "pxa2xx_timer_write: Bad offset "
+                        REG_FMT "\n", offset);
     }
 }
 
@@ -149,12 +338,13 @@
 
 static void pxa2xx_timer_tick(void *opaque)
 {
-    pxa2xx_timer *t = (pxa2xx_timer *) opaque;
+    struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
 
     if (i->irq_enabled & (1 << t->num)) {
         t->level = 1;
-        pic_set_irq_new(t->pic, t->irq, 1);
+        i->events |= 1 << t->num;
+        qemu_irq_raise(t->irq);
     }
 
     if (t->num == 3)
@@ -164,8 +354,20 @@
         }
 }
 
+static void pxa2xx_timer_tick4(void *opaque)
+{
+    struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
+    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
+
+    pxa2xx_timer_tick(&t->tm);
+    if (t->control & (1 << 3))
+        t->clock = 0;
+    if (t->control & (1 << 6))
+        pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
+}
+
 static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
-                void *pic, int irq, CPUState *cpustate)
+                qemu_irq *irqs, CPUState *cpustate)
 {
     int i;
     int iomemtype;
@@ -182,8 +384,7 @@
 
     for (i = 0; i < 4; i ++) {
         s->timer[i].value = 0;
-        s->timer[i].irq = irq + i;
-        s->timer[i].pic = pic;
+        s->timer[i].irq = irqs[i];
         s->timer[i].info = s;
         s->timer[i].num = i;
         s->timer[i].level = 0;
@@ -198,15 +399,30 @@
 }
 
 void pxa25x_timer_init(target_phys_addr_t base,
-                void *pic, int irq, CPUState *cpustate)
+                qemu_irq *irqs, CPUState *cpustate)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic, irq, cpustate);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
     s->freq = PXA25X_FREQ;
+    s->tm4 = 0;
 }
 
 void pxa27x_timer_init(target_phys_addr_t base,
-                void *pic, int irq, CPUState *cpustate)
+                qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic, irq, cpustate);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
+    int i;
     s->freq = PXA27X_FREQ;
+    s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
+                    sizeof(struct pxa2xx_timer4_s));
+    for (i = 0; i < 8; i ++) {
+        s->tm4[i].tm.value = 0;
+        s->tm4[i].tm.irq = irq4;
+        s->tm4[i].tm.info = s;
+        s->tm4[i].tm.num = i + 4;
+        s->tm4[i].tm.level = 0;
+        s->tm4[i].freq = 0;
+        s->tm4[i].control = 0x0;
+        s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
+                        pxa2xx_timer_tick4, &s->tm4[i]);
+    }
 }

Modified: trunk/src/host/qemu-neo1973/hw/realview.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/realview.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/realview.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * ARM RealView Baseboard System emulation.
  *
- * Copyright (c) 2006 CodeSourcery.
+ * Copyright (c) 2006-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL.
@@ -15,10 +15,10 @@
 static void realview_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename)
+                     const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
-    void *pic;
+    qemu_irq *pic;
     void *scsi_hba;
     PCIBus *pci_bus;
     NICInfo *nd;
@@ -26,8 +26,9 @@
     int done_smc = 0;
 
     env = cpu_init();
-    cpu_arm_set_model(env, ARM_CPUID_ARM926);
-    //cpu_arm_set_model(env, ARM_CPUID_ARM11MPCORE);
+    if (!cpu_model)
+        cpu_model = "arm926";
+    cpu_arm_set_model(env, cpu_model);
     /* ??? RAM shoud repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
@@ -37,23 +38,25 @@
     /* ??? The documentation says GIC1 is nFIQ and either GIC2 or GIC3
        is nIRQ (there are inconsistencies).  However Linux 2.6.17 expects
        GIC1 to be nIRQ and ignores all the others, so do that for now.  */
-    pic = arm_gic_init(0x10040000, pic, ARM_PIC_CPU_IRQ);
-    pl050_init(0x10006000, pic, 20, 0);
-    pl050_init(0x10007000, pic, 21, 1);
+    pic = arm_gic_init(0x10040000, pic[ARM_PIC_CPU_IRQ]);
+    pl050_init(0x10006000, pic[20], 0);
+    pl050_init(0x10007000, pic[21], 1);
 
-    pl011_init(0x10009000, pic, 12, serial_hds[0]);
-    pl011_init(0x1000a000, pic, 13, serial_hds[1]);
-    pl011_init(0x1000b000, pic, 14, serial_hds[2]);
-    pl011_init(0x1000c000, pic, 15, serial_hds[3]);
+    pl011_init(0x10009000, pic[12], serial_hds[0]);
+    pl011_init(0x1000a000, pic[13], serial_hds[1]);
+    pl011_init(0x1000b000, pic[14], serial_hds[2]);
+    pl011_init(0x1000c000, pic[15], serial_hds[3]);
 
     /* DMA controller is optional, apparently.  */
-    pl080_init(0x10030000, pic, 24, 2);
+    pl080_init(0x10030000, pic[24], 2);
 
-    sp804_init(0x10011000, pic, 4);
-    sp804_init(0x10012000, pic, 5);
+    sp804_init(0x10011000, pic[4]);
+    sp804_init(0x10012000, pic[5]);
 
-    pl110_init(ds, 0x10020000, pic, 23, 1);
+    pl110_init(ds, 0x10020000, pic[23], 1);
 
+    pl181_init(0x10005000, sd_bdrv, pic[17], pic[18]);
+
     pci_bus = pci_vpb_init(pic, 48, 1);
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, 3, -1);
@@ -69,9 +72,9 @@
         if (!nd->model)
             nd->model = done_smc ? "rtl8139" : "smc91c111";
         if (strcmp(nd->model, "smc91c111") == 0) {
-            smc91c111_init(nd, 0x4e000000, pic, 28);
+            smc91c111_init(nd, 0x4e000000, pic[28]);
         } else {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         }
     }
 
@@ -127,7 +130,7 @@
     /* 0x68000000 PCI mem 1.  */
     /* 0x6c000000 PCI mem 2.  */
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, 0x33b, 0x0);
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/rtl8139.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/rtl8139.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/rtl8139.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -461,7 +461,6 @@
     uint16_t CpCmd;
     uint8_t  TxThresh;
 
-    int irq;
     PCIDevice *pci_dev;
     VLANClientState *vc;
     uint8_t macaddr[6];
@@ -685,16 +684,10 @@
     int isr;
     isr = (s->IntrStatus & s->IntrMask) & 0xffff;
 
-    DEBUG_PRINT(("RTL8139: Set IRQ line %d to %d (%04x %04x)\n",
-       s->irq, isr ? 1 : 0, s->IntrStatus, s->IntrMask));
+    DEBUG_PRINT(("RTL8139: Set IRQ to %d (%04x %04x)\n",
+       isr ? 1 : 0, s->IntrStatus, s->IntrMask));
 
-    if (s->irq == 16) {
-        /* PCI irq */
-        pci_set_irq(s->pci_dev, 0, (isr != 0));
-    } else {
-        /* ISA irq */
-        pic_set_irq(s->irq, (isr != 0));
-    }
+    qemu_set_irq(s->pci_dev->irq[0], (isr != 0));
 }
 
 #define POLYNOMIAL 0x04c11db6
@@ -1192,8 +1185,11 @@
     s->eeprom.contents[1] = 0x10ec;
     s->eeprom.contents[2] = 0x8139;
 #endif
-    memcpy(&s->eeprom.contents[7], s->macaddr, 6);
 
+    s->eeprom.contents[7] = s->macaddr[0] | s->macaddr[1] << 8;
+    s->eeprom.contents[8] = s->macaddr[2] | s->macaddr[3] << 8;
+    s->eeprom.contents[9] = s->macaddr[4] | s->macaddr[5] << 8;
+
     /* mark all status registers as owned by host */
     for (i = 0; i < 4; ++i)
     {
@@ -2455,12 +2451,12 @@
 {
     DEBUG_PRINT(("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val));
 
-    s->TxAddr[txAddrOffset/4] = le32_to_cpu(val);
+    s->TxAddr[txAddrOffset/4] = val;
 }
 
 static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset)
 {
-    uint32_t ret = cpu_to_le32(s->TxAddr[txAddrOffset/4]);
+    uint32_t ret = s->TxAddr[txAddrOffset/4];
 
     DEBUG_PRINT(("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret));
 
@@ -3170,7 +3166,8 @@
     qemu_put_be16s(f, &s->CpCmd);
     qemu_put_8s(f, &s->TxThresh);
 
-    qemu_put_be32s(f, &s->irq);
+    i = 0;
+    qemu_put_be32s(f, &i); /* unused.  */
     qemu_put_buffer(f, s->macaddr, 6);
     qemu_put_be32s(f, &s->rtl8139_mmio_io_addr);
 
@@ -3264,7 +3261,7 @@
     qemu_get_be16s(f, &s->CpCmd);
     qemu_get_8s(f, &s->TxThresh);
 
-    qemu_get_be32s(f, &s->irq);
+    qemu_get_be32s(f, &i); /* unused.  */
     qemu_get_buffer(f, s->macaddr, 6);
     qemu_get_be32s(f, &s->rtl8139_mmio_io_addr);
 
@@ -3409,7 +3406,7 @@
 }
 #endif /* RTL8139_ONBOARD_TIMER */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
+void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCIRTL8139State *d;
     RTL8139State *s;
@@ -3417,7 +3414,7 @@
     
     d = (PCIRTL8139State *)pci_register_device(bus,
                                               "RTL8139", sizeof(PCIRTL8139State),
-                                              -1, 
+                                              devfn, 
                                               NULL, NULL);
     pci_conf = d->dev.config;
     pci_conf[0x00] = 0xec; /* Realtek 8139 */
@@ -3444,7 +3441,6 @@
     pci_register_io_region(&d->dev, 1, 0x100, 
                            PCI_ADDRESS_SPACE_MEM, rtl8139_mmio_map);
 
-    s->irq = 16; /* PCI interrupt */
     s->pci_dev = (PCIDevice *)d;
     memcpy(s->macaddr, nd->macaddr, 6);
     rtl8139_reset(s);

Modified: trunk/src/host/qemu-neo1973/hw/s3c.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -52,6 +52,8 @@
 # define S3C_PICS_ERR2	40
 # define S3C_PICS_TC	41
 # define S3C_PICS_ADC	42
+
+# define S3C_PIC_MAX	43
 /* External interrupt numbers */
 # define S3C_EINT(n)	((n >= 8) ? (6 << 5) | (n - 8) : (5 << 5) | n)
 
@@ -77,6 +79,8 @@
 # define S3C_RQ_USB_EP3	0x24
 # define S3C_RQ_USB_EP4	0x34
 
+# define S3C_RQ_MAX	0x35
+
 /* I/O port numbers */
 # define S3C_GP(b, n)	(((b) << 5) | n)
 # define S3C_GPA(n)	S3C_GP(0, n)
@@ -87,6 +91,7 @@
 # define S3C_GPF(n)	S3C_GP(5, n)
 # define S3C_GPG(n)	S3C_GP(6, n)
 # define S3C_GPH(n)	S3C_GP(7, n)
+# define S3C_GP_MAX	S3C_GP(8, 0)
 
 # define S3C_RAM_BASE	0x30000000
 # define S3C_SRAM_BASE	0x40000000
@@ -97,51 +102,54 @@
 
 /* s3c2410.c */
 struct s3c_pic_state_s;
-struct s3c_pic_state_s *s3c_pic_init(target_phys_addr_t base, CPUState *env);
+struct s3c_pic_state_s *s3c_pic_init(target_phys_addr_t base,
+                qemu_irq *arm_pic);
+qemu_irq *s3c_pic_get(struct s3c_pic_state_s *s);
 
 struct s3c_dma_state_s;
-struct s3c_dma_state_s *s3c_dma_init(target_phys_addr_t base, void *pic);
+struct s3c_dma_state_s *s3c_dma_init(target_phys_addr_t base, qemu_irq *pic);
+qemu_irq *s3c_dma_get(struct s3c_dma_state_s *s);
 
 struct s3c_timers_state_s;
 struct s3c_timers_state_s *s3c_timers_init(target_phys_addr_t base,
-                void *pic, void *dma);
+                qemu_irq *pic, qemu_irq *dma);
 void s3c_timers_cmp_handler_set(void *opaque, int line,
                 gpio_handler_t handler, void *cmp_opaque);
 
 struct s3c_uart_state_s;
 struct s3c_uart_state_s *s3c_uart_init(target_phys_addr_t base,
-                void *pic, void *dma, int irq[], int drq[]);
+                qemu_irq *irqs, qemu_irq *dma);
 void s3c_uart_attach(struct s3c_uart_state_s *s, CharDriverState *chr);
 
 struct s3c_adc_state_s;
-struct s3c_adc_state_s *s3c_adc_init(target_phys_addr_t base, void *pic);
+struct s3c_adc_state_s *s3c_adc_init(target_phys_addr_t base, qemu_irq irq,
+                qemu_irq tcirq);
 
 struct s3c_i2c_state_s;
-struct s3c_i2c_state_s *s3c_i2c_init(target_phys_addr_t base, void *pic);
-struct i2c_master_s *s3c_i2c_master(struct s3c_i2c_state_s *s);
+struct s3c_i2c_state_s *s3c_i2c_init(target_phys_addr_t base, qemu_irq irq);
+i2c_bus *s3c_i2c_bus(struct s3c_i2c_state_s *s);
 
 struct s3c_i2s_state_s;
-struct s3c_i2s_state_s *s3c_i2s_init(target_phys_addr_t base, void *dma);
+struct s3c_i2s_state_s *s3c_i2s_init(target_phys_addr_t base, qemu_irq *dma);
 
 /* s3c24xx_gpio.c */
 struct s3c_gpio_state_s;
-struct s3c_gpio_state_s *s3c_gpio_init(target_phys_addr_t base, void *pic);
-void s3c_gpio_set(void *opaque, int line, int level);
-void s3c_gpio_handler_set(struct s3c_gpio_state_s *s, int line,
-                gpio_handler_t handler, void *opaque);
+struct s3c_gpio_state_s *s3c_gpio_init(target_phys_addr_t base, qemu_irq *pic);
+qemu_irq *s3c_gpio_in_get(struct s3c_gpio_state_s *s);
+void s3c_gpio_out_set(struct s3c_gpio_state_s *s, int line, qemu_irq handler);
 void s3c_gpio_setpwrstat(struct s3c_gpio_state_s *s, int stat);
 void s3c_gpio_reset(struct s3c_gpio_state_s *s);
 
 /* s3c24xx_lcd.c */
 struct s3c_lcd_state_s;
 struct s3c_lcd_state_s *s3c_lcd_init(target_phys_addr_t base, DisplayState *ds,
-                void *pic);
+                qemu_irq irq);
 void s3c_lcd_reset(struct s3c_lcd_state_s *s);
 
 /* s3c24xx_mmci.c */
 struct s3c_mmci_state_s;
 struct s3c_mmci_state_s *s3c_mmci_init(target_phys_addr_t base,
-                void *pic, void *dma);
+                qemu_irq irq, qemu_irq *dma);
 void s3c_mmci_handlers(struct s3c_mmci_state_s *s, void *opaque,
                 void (*readonly_cb)(void *, int),
                 void (*coverswitch_cb)(void *, int));
@@ -149,26 +157,28 @@
 
 /* s3c24xx_rtc.c */
 struct s3c_rtc_state_s;
-struct s3c_rtc_state_s *s3c_rtc_init(target_phys_addr_t base, void *pic);
+struct s3c_rtc_state_s *s3c_rtc_init(target_phys_addr_t base, qemu_irq irq);
 void s3c_rtc_reset(struct s3c_rtc_state_s *s);
 
 /* s3c24xx_udc.c */
 struct s3c_udc_state_s;
-struct s3c_udc_state_s *s3c_udc_init(target_phys_addr_t base, void *pic,
-                void *dma);
+struct s3c_udc_state_s *s3c_udc_init(target_phys_addr_t base, qemu_irq irq,
+                qemu_irq *dma);
 void s3c_udc_reset(struct s3c_udc_state_s *s);
 
 /* s3c2410.c */
 struct s3c_spi_state_s;
-struct s3c_spi_state_s *s3c_spi_init(target_phys_addr_t base, void *pic,
-                void *dma, struct s3c_gpio_state_s *gpio);
+struct s3c_spi_state_s *s3c_spi_init(target_phys_addr_t base,
+                qemu_irq irq0, qemu_irq drq0, qemu_irq irq1, qemu_irq drq1,
+                struct s3c_gpio_state_s *gpio);
 void s3c_spi_attach(struct s3c_spi_state_s *s, int ch,
                 uint8_t (*txrx)(void *opaque, uint8_t value),
                 uint8_t (*btxrx)(void *opaque, uint8_t value), void *opaque);
 
 struct s3c_state_s {
     CPUState *env;
-    uint32_t free_ram_start;/* XXX */
+    qemu_irq *irq;
+    qemu_irq *drq;
     struct s3c_pic_state_s *pic;
     struct s3c_dma_state_s *dma;
     struct s3c_gpio_state_s *io;
@@ -202,14 +212,12 @@
 
 /* s3c2410.c */
 void s3c2410_reset(struct s3c_state_s *s);
-struct s3c_state_s *s3c2410_init(DisplayState *ds);
+struct s3c_state_s *s3c2410_init(unsigned int sdram_size, DisplayState *ds);
 void s3c_nand_register(struct s3c_state_s *s, struct nand_flash_s *chip);
-typedef void (*s3c_pic_handler_t)(void *opaque, int irq, int level);
 
 struct s3c_i2s_state_s { /* XXX move to .c */
     target_phys_addr_t base;
-    void *pic;
-    void *dma;
+    qemu_irq *dma;
     void (*data_req)(void *, int, int);
 
     uint16_t control;

Modified: trunk/src/host/qemu-neo1973/hw/s3c2410.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,9 +10,9 @@
 
 /* Interrupt controller */
 struct s3c_pic_state_s {
-    s3c_pic_handler_t handler;
-    CPUState *cpu;
     target_phys_addr_t base;
+    qemu_irq *parent_pic;
+    qemu_irq *irqs;
 
     uint32_t srcpnd;
     uint32_t intpnd;
@@ -26,15 +26,10 @@
 
 static void s3c_pic_update(struct s3c_pic_state_s *s)
 {
-    if (s->srcpnd & ~s->intmsk & s->intmod)
-        cpu_interrupt(s->cpu, CPU_INTERRUPT_FIQ);
-    else
-        cpu_reset_interrupt(s->cpu, CPU_INTERRUPT_FIQ);
-
-    if (s->intpnd & ~s->intmsk & ~s->intmod)
-        cpu_interrupt(s->cpu, CPU_INTERRUPT_HARD);
-    else
-        cpu_reset_interrupt(s->cpu, CPU_INTERRUPT_HARD);
+    qemu_set_irq(s->parent_pic[ARM_PIC_CPU_FIQ],
+                    s->srcpnd & ~s->intmsk & s->intmod);
+    qemu_set_irq(s->parent_pic[ARM_PIC_CPU_IRQ],
+                    s->intpnd & ~s->intmsk & ~s->intmod);
 }
 
 static const uint32_t s3c_arbmsk[6] = {
@@ -246,15 +241,16 @@
     s3c_pic_write,
 };
 
-struct s3c_pic_state_s *s3c_pic_init(target_phys_addr_t base, CPUState *env)
+struct s3c_pic_state_s *s3c_pic_init(target_phys_addr_t base,
+                qemu_irq *arm_pic)
 {
     int iomemtype;
     struct s3c_pic_state_s *s = (struct s3c_pic_state_s *)
             qemu_mallocz(sizeof(struct s3c_pic_state_s));
 
     s->base = base;
-    s->cpu = env;
-    s->handler = s3c_pic_set_irq;
+    s->parent_pic = arm_pic;
+    s->irqs = qemu_allocate_irqs(s3c_pic_set_irq, s, S3C_PIC_MAX);
 
     s3c_pic_reset(s);
 
@@ -265,6 +261,11 @@
     return s;
 }
 
+qemu_irq *s3c_pic_get(struct s3c_pic_state_s *s)
+{
+    return s->irqs;
+}
+
 /* Memory controller */
 #define S3C_BWSCON	0x00	/* Bus Width & Wait Control register */
 #define S3C_BANKCON0	0x04	/* Bank 0 Control register */
@@ -540,12 +541,11 @@
 #define S3C_DMA_CH_N	4
 
 struct s3c_dma_ch_state_s;
-struct s3c_dma_state_s {
-    s3c_pic_handler_t handler;	/* Modelled as an interrupt controller */
+struct s3c_dma_state_s {	/* Modelled as an interrupt controller */
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq *drqs;
     struct s3c_dma_ch_state_s {
-        int intr;
+        qemu_irq intr;
         int curr_tc;
         int req;
         int running;
@@ -591,7 +591,7 @@
         }
         ch->running = 0;
         if (!ch->curr_tc && (ch->con & (1 << 29)))		/* INT */
-            pic_set_irq_new(s->pic, ch->intr, 1);
+            qemu_irq_raise(ch->intr);
 
         if (ch->con & (1 << 22)) {				/* RELOAD */
             if (!(ch->con & (1 << 23))) {			/* SWHW_SEL */
@@ -741,19 +741,18 @@
     s3c_dma_write,
 };
 
-struct s3c_dma_state_s *s3c_dma_init(target_phys_addr_t base, void *pic)
+struct s3c_dma_state_s *s3c_dma_init(target_phys_addr_t base, qemu_irq *pic)
 {
     int iomemtype;
     struct s3c_dma_state_s *s = (struct s3c_dma_state_s *)
             qemu_mallocz(sizeof(struct s3c_dma_state_s));
 
     s->base = base;
-    s->pic = pic;
-    s->ch[0].intr = S3C_PIC_DMA0;
-    s->ch[1].intr = S3C_PIC_DMA1;
-    s->ch[2].intr = S3C_PIC_DMA2;
-    s->ch[3].intr = S3C_PIC_DMA3;
-    s->handler = s3c_dma_dreq;
+    s->ch[0].intr = pic[0];
+    s->ch[1].intr = pic[1];
+    s->ch[2].intr = pic[2];
+    s->ch[3].intr = pic[3];
+    s->drqs = qemu_allocate_irqs(s3c_dma_dreq, s, S3C_RQ_MAX);
 
     s3c_dma_reset(s);
 
@@ -764,12 +763,16 @@
     return s;
 }
 
+qemu_irq *s3c_dma_get(struct s3c_dma_state_s *s)
+{
+    return s->drqs;
+}
+
 /* PWM timers controller */
 struct s3c_timer_state_s;
 struct s3c_timers_state_s {
     target_phys_addr_t base;
-    void *pic;
-    void *dma;
+    qemu_irq *dma;
     DisplayState *ds;
     struct s3c_timer_state_s {
         QEMUTimer *t;
@@ -779,7 +782,7 @@
         uint32_t divider;
         uint16_t count;
         int64_t reload;
-        int irq;
+        qemu_irq irq;
         gpio_handler_t cmp_cb;
         void *cmp_opaque;
     } timer[5];
@@ -855,11 +858,11 @@
         return;
 
     if (((s->config[1] >> 20) & 0xf) == t->n + 1) {
-        pic_set_irq_new(s->dma, S3C_RQ_TIMER0, 1);	/* TODO */
-        pic_set_irq_new(s->dma, S3C_RQ_TIMER1, 1);
-        pic_set_irq_new(s->dma, S3C_RQ_TIMER2, 1);
+        qemu_irq_raise(s->dma[S3C_RQ_TIMER0]);	/* TODO */
+        qemu_irq_raise(s->dma[S3C_RQ_TIMER1]);
+        qemu_irq_raise(s->dma[S3C_RQ_TIMER2]);
     } else
-        pic_set_irq_new(s->pic, t->irq, 1);
+        qemu_irq_raise(t->irq);
 
     t->running = 0;
     t->count = 0;
@@ -994,14 +997,13 @@
 };
 
 struct s3c_timers_state_s *s3c_timers_init(target_phys_addr_t base,
-                void *pic, void *dma)
+                qemu_irq *pic, qemu_irq *dma)
 {
     int i, iomemtype;
     struct s3c_timers_state_s *s = (struct s3c_timers_state_s *)
             qemu_mallocz(sizeof(struct s3c_timers_state_s));
 
     s->base = base;
-    s->pic = pic;
     s->dma = dma;
 
     s3c_timers_reset(s);
@@ -1012,12 +1014,8 @@
         s->timer[i].s = s;
         s->timer[i].n = i;
         s->timer[i].cmp_cb = 0;
+        s->timer[i].irq = pic[i];
     }
-    s->timer[0].irq = S3C_PIC_TIMER0;
-    s->timer[1].irq = S3C_PIC_TIMER1;
-    s->timer[2].irq = S3C_PIC_TIMER2;
-    s->timer[3].irq = S3C_PIC_TIMER3;
-    s->timer[4].irq = S3C_PIC_TIMER4;
 
     iomemtype = cpu_register_io_memory(0, s3c_timers_readfn,
                     s3c_timers_writefn, s);
@@ -1041,10 +1039,8 @@
 /* UART */
 struct s3c_uart_state_s {
     target_phys_addr_t base;
-    void *pic;
-    void *dma;
-    int *irq;
-    int *drq;
+    qemu_irq *irq;
+    qemu_irq *dma;
     uint8_t data;
     uint8_t rxfifo[16];
     int rxstart;
@@ -1108,7 +1104,7 @@
 {
     s->errstat |= err;
     if (s->control & (1 << 6))
-        pic_set_irq_new(s->pic, s->irq[2], 1);
+        qemu_irq_raise(s->irq[2]);
 }
 
 static void s3c_uart_full(struct s3c_uart_state_s *s)
@@ -1119,11 +1115,11 @@
 
     switch ((s->control >> 0) & 3) {		/* ReceiveMode */
     case 1:
-        pic_set_irq_new(s->pic, s->irq[0], 1);
+        qemu_irq_raise(s->irq[0]);
         break;
     case 2:
     case 3:
-        pic_set_irq_new(s->dma, s->drq[0], 1);
+        qemu_irq_raise(s->dma[0]);
         break;
     }
 }
@@ -1132,11 +1128,11 @@
 {
     switch ((s->control >> 2) & 3) {		/* TransmitMode */
     case 1:
-        pic_set_irq_new(s->pic, s->irq[1], 1);
+        qemu_irq_raise(s->irq[1]);
         break;
     case 2:
     case 3:
-        pic_set_irq_new(s->dma, s->drq[0], 1);
+        qemu_irq_raise(s->dma[0]);
         break;
     }
 }
@@ -1176,6 +1172,11 @@
     s3c_uart_full(s);
 }
 
+/* S3C2410 UART doesn't seem to understand break conditions.  */
+static void s3c_uart_event(void *opaque, int event)
+{
+}
+
 #define S3C_ULCON	0x00	/* UART Line Control register */
 #define S3C_UCON	0x04	/* UART Control register */
 #define S3C_UFCON	0x08	/* UART FIFO Control register */
@@ -1296,17 +1297,15 @@
 };
 
 struct s3c_uart_state_s *s3c_uart_init(target_phys_addr_t base,
-                void *pic, void *dma, int irq[], int drq[])
+                qemu_irq *irqs, qemu_irq *dma)
 {
     int iomemtype;
     struct s3c_uart_state_s *s = (struct s3c_uart_state_s *)
             qemu_mallocz(sizeof(struct s3c_uart_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irqs;
     s->dma = dma;
-    s->irq = irq;
-    s->drq = drq;
 
     s3c_uart_reset(s);
 
@@ -1323,14 +1322,15 @@
         cpu_abort(cpu_single_env, "%s: Too many devices\n", __FUNCTION__);
     s->chr[s->chr_num ++] = chr;
 
-    qemu_chr_add_read_handler(chr, s3c_uart_is_empty, s3c_uart_rx, s);
-    /* S3C2410 UART doesn't seem to understand break conditions.  */
+    qemu_chr_add_handlers(chr, s3c_uart_is_empty,
+                    s3c_uart_rx, s3c_uart_event, s);
 }
 
 /* ADC & Touchscreen interface */
 struct s3c_adc_state_s {
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq irq;
+    qemu_irq tcirq;
     QEMUTimer *convt;
     QEMUTimer *tst;
     int x;
@@ -1371,7 +1371,7 @@
     struct s3c_adc_state_s *s = (struct s3c_adc_state_s *) opaque;
     s->xdata = s->input[s->in_idx] & 0x3ff;
     s->control |= 1 << 15;
-    pic_set_irq_new(s->pic, S3C_PICS_ADC, 1);
+    qemu_irq_raise(s->irq);
 }
 
 static void s3c_adc_tick(void *opaque)
@@ -1379,13 +1379,13 @@
     struct s3c_adc_state_s *s = (struct s3c_adc_state_s *) opaque;
     if (s->down) {
         if ((s->ts & 3) == 3 && s->enable)
-            pic_set_irq_new(s->pic, S3C_PICS_TC, 1);
+            qemu_irq_raise(s->tcirq);
         else if (s->enable && ((s->ts & (1 << 2)) || (s->ts & 3))) {
             s->xdata = (s->x >> 5) | (1 << 14) | ((s->ts & 3) << 12);
             s->ydata = (s->y >> 5) | (1 << 14) | ((s->ts & 3) << 12);
             s->xdata ^= s->noise >> 1;
             s->ydata ^= s->noise >> 2;
-            pic_set_irq_new(s->pic, S3C_PICS_ADC, 1);
+            qemu_irq_raise(s->irq);
             s->noise ++;
             s->noise &= 7;
         }
@@ -1476,14 +1476,16 @@
     s3c_adc_write,
 };
 
-struct s3c_adc_state_s *s3c_adc_init(target_phys_addr_t base, void *pic)
+struct s3c_adc_state_s *s3c_adc_init(target_phys_addr_t base, qemu_irq irq,
+                qemu_irq tcirq)
 {
     int iomemtype;
     struct s3c_adc_state_s *s = (struct s3c_adc_state_s *)
             qemu_mallocz(sizeof(struct s3c_adc_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
+    s->tcirq = tcirq;
     s->convt = qemu_new_timer(vm_clock, s3c_adc_done, s);
     s->tst = qemu_new_timer(vm_clock, s3c_adc_tick, s);
 
@@ -1502,15 +1504,15 @@
 
 /* IIC-bus serial interface */
 struct s3c_i2c_state_s {
+    i2c_slave slave;
+    i2c_bus *bus;
     target_phys_addr_t base;
-    void *pic;
-    struct i2c_master_s master;
-    struct i2c_slave_s slave;
+    qemu_irq irq;
 
     uint8_t control;
     uint8_t status;
     uint8_t data;
-    uint8_t address;
+    uint8_t addy;
     int busy;
     int newstart;
 };
@@ -1519,7 +1521,7 @@
 {
     s->control |= 1 << 4;
     if (s->control & (1 << 5))
-        pic_set_irq_new(s->pic, S3C_PIC_IIC, 1);
+        qemu_irq_raise(s->irq);
 }
 
 static void s3c_i2c_reset(struct s3c_i2c_state_s *s)
@@ -1530,64 +1532,95 @@
     s->newstart = 0;
 }
 
-static void s3c_i2c_start(void *opaque, int dir)
+static void s3c_i2c_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) opaque;
+    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) i2c;
     if (!(s->status & (1 << 4)))
         return;
 
-    s->status &= ~(1 << 2);
-    s3c_i2c_irq(s);
+    switch (event) {
+    case I2C_START_RECV:
+    case I2C_START_SEND:
+        s->status |= 1 << 2;
+        s3c_i2c_irq(s);
+        break;
+    case I2C_FINISH:
+        s->status &= ~6;
+        break;
+    case I2C_NACK:
+        s->status |= 1 << 0;
+        break;
+    default:
+        break;
+    }
 }
 
-static void s3c_i2c_stop(void *opaque)
+static int s3c_i2c_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) opaque;
-    s->status &= ~(1 << 2);
+    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) i2c;
+    if (!(s->status & (1 << 4)))
+        return 1;
+
+    if ((s->status >> 6) == 0)
+        s->data = data;						/* TODO */
+    s->status &= ~(1 << 0);
+    s3c_i2c_irq(s);
+
+    return !(s->control & (1 << 7));
 }
 
-static int s3c_i2c_tx(void *opaque, uint8_t *message, int len)
+static int s3c_i2c_rx(i2c_slave *i2c)
 {
-    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) opaque;
+    struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) i2c;
     if (!(s->status & (1 << 4)))
         return 1;
 
-    if (len) {
-        if ((s->status >> 6) == 0)
-            s->master.data = message[0];		/* TODO */
-        else if ((s->status >> 6) == 1)
-            message[0] = s->master.data;		/* TODO */
+    if ((s->status >> 6) == 1) {
+        s->status &= ~(1 << 0);
+        s3c_i2c_irq(s);
+        return s->data;
     }
-    s3c_i2c_irq(s);
 
-    return !(s->control & (1 << 7));
+    return 0x00;
 }
 
 static void s3c_master_work(void *opaque)
 {
     struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *) opaque;
-    int start = 0;
+    int start = 0, stop = 0, ack = 1;
     if (s->control & (1 << 4))				/* Interrupt pending */
         return;
     if ((s->status & 0x90) != 0x90)			/* Master */
         return;
+    stop = ~s->status & (1 << 5);
     if (s->newstart && s->status & (1 << 5)) {		/* START */
         s->busy = 1;
         start = 1;
-        s->master.data |= (~s->status >> 6) & 1;
     }
     s->newstart = 0;
     if (!s->busy)
         return;
 
-    i2c_master_submit(&s->master, start, (~s->status >> 4) & 2);
+    if (start)
+        ack = !i2c_start_transfer(s->bus, s->data >> 1, (~s->status >> 6) & 1);
+    else if (stop)
+        i2c_end_transfer(s->bus);
+    else if (s->status & (1 << 6))
+        ack = !i2c_send(s->bus, s->data);
+    else {
+        s->data = i2c_recv(s->bus);
+
+        if (!(s->control & (1 << 7)))			/* ACK */
+            i2c_nack(s->bus);
+    }
+
     if (!(s->status & (1 << 5))) {
         s->busy = 0;
         return;
     }
     s->status &= ~1;
-    s->status |= !s->master.ack;
-    if (!s->master.ack)
+    s->status |= !ack;
+    if (!ack)
         s->busy = 0;
     s3c_i2c_irq(s);
 }
@@ -1608,9 +1641,9 @@
     case S3C_IICSTAT:
         return s->status & ~(1 << 5);			/* Busy signal */
     case S3C_IICADD:
-        return s->slave.address;
+        return s->addy;
     case S3C_IICDS:
-        return s->master.data;
+        return s->data;
     default:
         printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
         break;
@@ -1640,12 +1673,12 @@
         break;
 
     case S3C_IICADD:
-        if (s->master.bus)
-            i2c_slave_attach(s->master.bus, value & 0x7f, &s->slave);
+        s->addy = value & 0x7f;
+        i2c_set_slave_address(&s->slave, s->addy);
         break;
 
     case S3C_IICDS:
-        s->master.data = value & 0xff;
+        s->data = value & 0xff;
         break;
 
     default:
@@ -1665,18 +1698,18 @@
     s3c_i2c_write,
 };
 
-struct s3c_i2c_state_s *s3c_i2c_init(target_phys_addr_t base, void *pic)
+struct s3c_i2c_state_s *s3c_i2c_init(target_phys_addr_t base, qemu_irq irq)
 {
     int iomemtype;
     struct s3c_i2c_state_s *s = (struct s3c_i2c_state_s *)
             qemu_mallocz(sizeof(struct s3c_i2c_state_s));
 
     s->base = base;
-    s->pic = pic;
-    s->slave.tx = s3c_i2c_tx;
-    s->slave.start = s3c_i2c_start;
-    s->slave.stop = s3c_i2c_stop;
-    s->slave.opaque = s;
+    s->irq = irq;
+    s->slave.event = s3c_i2c_event;
+    s->slave.send = s3c_i2c_tx;
+    s->slave.recv = s3c_i2c_rx;
+    s->bus = i2c_init_bus();
 
     s3c_i2c_reset(s);
 
@@ -1687,19 +1720,20 @@
     return s;
 }
 
-struct i2c_master_s *s3c_i2c_master(struct s3c_i2c_state_s *s)
+i2c_bus *s3c_i2c_bus(struct s3c_i2c_state_s *s)
 {
-    return &s->master;
+    return s->bus;
 }
 
 /* Serial Peripheral Interface */
 struct s3c_spi_state_s {
     target_phys_addr_t base;
-    void *pic;
-    void *dma;
-    struct s3c_gpio_state_s *gpio;
 
     struct {
+        qemu_irq irq;
+        qemu_irq drq;
+        qemu_irq miso;
+
         uint8_t control;
         uint8_t pin;
         uint8_t pre;
@@ -1719,23 +1753,17 @@
 
 static void s3c_spi_update(struct s3c_spi_state_s *s)
 {
-    switch ((s->chan[0].control >> 5) & 3) {			/* SMOD */
-    case 1:
-        pic_set_irq_new(s->pic, S3C_PIC_SPI0, 1);
-        break;
-    case 2:
-        pic_set_irq_new(s->dma, S3C_RQ_SPI0, 1);
-        break;
+    int i;
+    for (i = 0; i < 2; i ++) {
+        switch ((s->chan[i].control >> 5) & 3) {		/* SMOD */
+        case 1:
+            qemu_irq_raise(s->chan[i].irq);
+            break;
+        case 2:
+            qemu_irq_raise(s->chan[i].drq);
+            break;
+        }
     }
-
-    switch ((s->chan[1].control >> 5) & 3) {			/* SMOD */
-    case 1:
-        pic_set_irq_new(s->pic, S3C_PIC_SPI1, 1);
-        break;
-    case 2:
-        pic_set_irq_new(s->dma, S3C_RQ_SPI1, 1);
-        break;
-    }
 }
 
 static void s3c_spi_reset(struct s3c_spi_state_s *s)
@@ -1851,17 +1879,10 @@
     s3c_spi_write,
 };
 
-static const struct {
-    int cs, clk, miso, mosi;
-} s3c_spi_pins[2] = {
-    { S3C_GPG(2), S3C_GPE(13), S3C_GPE(11), S3C_GPE(12) },
-    { S3C_GPG(3), S3C_GPG(7),  S3C_GPG(5),  S3C_GPG(6)  },
-};
-
-static void s3c_spi_bitbang_cs(int line, int level, void *opaque)
+static void s3c_spi_bitbang_cs(void *opaque, int line, int level)
 {
     struct s3c_spi_state_s *s = (struct s3c_spi_state_s *) opaque;
-    int ch = (line == s3c_spi_pins[1].cs);
+    int ch = line;
     if (s->chan[ch].cs_pin || level) {
         if (s->chan[ch].bit && s->txrx[ch] && !s->btxrx[ch]) {
             s->chan[ch].txbuf <<= 8 - s->chan[ch].bit;
@@ -1874,10 +1895,10 @@
     s->chan[ch].cs_pin = !level;
 }
 
-static void s3c_spi_bitbang_clk(int line, int level, void *opaque)
+static void s3c_spi_bitbang_clk(void *opaque, int line, int level)
 {
     struct s3c_spi_state_s *s = (struct s3c_spi_state_s *) opaque;
-    int ch = (line == s3c_spi_pins[1].clk);
+    int ch = line;
     if (!s->chan[ch].cs_pin)
         goto done;
 
@@ -1886,7 +1907,7 @@
         goto done;
 
     if (s->btxrx[ch]) {
-        s3c_gpio_set(s->gpio, s3c_spi_pins[ch].miso,
+        qemu_set_irq(s->chan[ch].miso,
                         s->btxrx[ch](s->opaque[ch], s->chan[ch].mosi_pin));
         goto done;
     }
@@ -1894,7 +1915,7 @@
     s->chan[ch].txbuf <<= 1;
     s->chan[ch].txbuf |= s->chan[ch].mosi_pin;
 
-    s3c_gpio_set(s->gpio, s3c_spi_pins[ch].miso, (s->chan[ch].rxbuf >> 7) & 1);
+    qemu_set_irq(s->chan[ch].miso, (s->chan[ch].rxbuf >> 7) & 1);
     s->chan[ch].rxbuf <<= 1;
 
     if (++ s->chan[ch].bit == 8) {
@@ -1907,39 +1928,49 @@
     s->chan[ch].clk_pin = level;
 }
 
-static void s3c_spi_bitbang_mosi(int line, int level, void *opaque)
+static void s3c_spi_bitbang_mosi(void *opaque, int line, int level)
 {
     struct s3c_spi_state_s *s = (struct s3c_spi_state_s *) opaque;
-    int ch = (line == s3c_spi_pins[1].mosi);
+    int ch = line;
     s->chan[ch].mosi_pin = level;
 }
 
+static const struct {
+    int cs, clk, miso, mosi;
+} s3c_spi_pins[2] = {
+    { S3C_GPG(2), S3C_GPE(13), S3C_GPE(11), S3C_GPE(12) },
+    { S3C_GPG(3), S3C_GPG(7),  S3C_GPG(5),  S3C_GPG(6)  },
+};
+
 static void s3c_spi_bitbang_init(struct s3c_spi_state_s *s,
                 struct s3c_gpio_state_s *gpio)
 {
     int i;
+    qemu_irq *cs = qemu_allocate_irqs(s3c_spi_bitbang_cs, s, 2);
+    qemu_irq *clk = qemu_allocate_irqs(s3c_spi_bitbang_clk, s, 2);
+    qemu_irq *mosi = qemu_allocate_irqs(s3c_spi_bitbang_mosi, s, 2);
+
     for (i = 0; i < 2; i ++) {
-        s3c_gpio_handler_set(gpio, s3c_spi_pins[i].cs,
-                        s3c_spi_bitbang_cs, s);
-        s3c_gpio_handler_set(gpio, s3c_spi_pins[i].clk,
-                        s3c_spi_bitbang_clk, s);
-        s3c_gpio_handler_set(gpio, s3c_spi_pins[i].mosi,
-                        s3c_spi_bitbang_mosi, s);
+        s3c_gpio_out_set(gpio, s3c_spi_pins[i].cs, cs[i]);
+        s3c_gpio_out_set(gpio, s3c_spi_pins[i].clk, clk[i]);
+        s->chan[i].miso = s3c_gpio_in_get(gpio)[s3c_spi_pins[i].miso];
+        s3c_gpio_out_set(gpio, s3c_spi_pins[i].mosi, mosi[i]);
     }
-
-    s->gpio = gpio;
 }
 
 struct s3c_spi_state_s *s3c_spi_init(target_phys_addr_t base,
-                void *pic, void *dma, struct s3c_gpio_state_s *gpio)
+                qemu_irq irq0, qemu_irq drq0, qemu_irq irq1, qemu_irq drq1,
+                struct s3c_gpio_state_s *gpio)
 {
     int iomemtype;
     struct s3c_spi_state_s *s = (struct s3c_spi_state_s *)
             qemu_mallocz(sizeof(struct s3c_spi_state_s));
 
     s->base = base;
-    s->pic = pic;
-    s->dma = dma;
+    s->chan[0].irq = irq0;
+    s->chan[0].drq = drq0;
+    s->chan[1].irq = irq1;
+    s->chan[1].drq = drq1;
 
     s3c_spi_reset(s);
 
@@ -1980,11 +2011,11 @@
     if (s->rx_en && s->rx_len)
         s->control |= (1 << 6);
 
-    pic_set_irq_new(s->dma, S3C_RQ_I2SSDO, (s->control >> 5) &
+    qemu_set_irq(s->dma[S3C_RQ_I2SSDO], (s->control >> 5) &
                     (s->control >> 7) & (s->fcontrol >> 15) & 1);
-    pic_set_irq_new(s->dma, S3C_RQ_I2SSDI0, (s->control >> 4) &
+    qemu_set_irq(s->dma[S3C_RQ_I2SSDI0], (s->control >> 4) &
                     (s->control >> 6) & (s->fcontrol >> 14) & 1);
-    pic_set_irq_new(s->dma, S3C_RQ_I2SSDI1, (s->control >> 4) &
+    qemu_set_irq(s->dma[S3C_RQ_I2SSDI1], (s->control >> 4) &
                     (s->control >> 6) & (s->fcontrol >> 14) & 1);
 }
 
@@ -2098,7 +2129,7 @@
     s3c_i2s_update(s);
 }
 
-struct s3c_i2s_state_s *s3c_i2s_init(target_phys_addr_t base, void *dma)
+struct s3c_i2s_state_s *s3c_i2s_init(target_phys_addr_t base, qemu_irq *dma)
 {
     int iomemtype;
     struct s3c_i2s_state_s *s = (struct s3c_i2s_state_s *)
@@ -2166,29 +2197,32 @@
 }
 
 /* Initialise an S3C2410A microprocessor.  */
-struct s3c_state_s *s3c2410_init(DisplayState *ds)
+struct s3c_state_s *s3c2410_init(unsigned int sdram_size, DisplayState *ds)
 {
     struct s3c_state_s *s;
     int iomemtype, i;
     s = (struct s3c_state_s *) qemu_mallocz(sizeof(struct s3c_state_s));
 
-    s->free_ram_start = 0;
     s->env = cpu_init();
-    cpu_arm_set_model(s->env, ARM_CPUID_ARM920T);
+    cpu_arm_set_model(s->env, "arm920t");
 
+    cpu_register_physical_memory(S3C_RAM_BASE, sdram_size,
+                    qemu_ram_alloc(sdram_size) | IO_MEM_RAM);
+
     /* If OM pins are 00, SRAM is mapped at 0x0 instead.  */
     cpu_register_physical_memory(S3C_SRAM_BASE, S3C_SRAM_SIZE,
-                    s->free_ram_start | IO_MEM_RAM);
-    s->free_ram_start += S3C_SRAM_SIZE;
+                    qemu_ram_alloc(S3C_SRAM_SIZE) | IO_MEM_RAM);
 
     s->mc_base = 0x48000000;
     s3c_mc_reset(s);
     iomemtype = cpu_register_io_memory(0, s3c_mc_readfn, s3c_mc_writefn, s);
     cpu_register_physical_memory(s->mc_base, 0xffffff, iomemtype);
 
-    s->pic = s3c_pic_init(0x4a000000, s->env);
+    s->pic = s3c_pic_init(0x4a000000, arm_pic_init_cpu(s->env));
+    s->irq = s3c_pic_get(s->pic);
 
-    s->dma = s3c_dma_init(0x4b000000, s->pic);
+    s->dma = s3c_dma_init(0x4b000000, &s->irq[S3C_PIC_DMA0]);
+    s->drq = s3c_dma_get(s->dma);
 
     s->clkpwr_base = 0x4c000000;
     s3c_clkpwr_reset(s);
@@ -2196,7 +2230,7 @@
                     s3c_clkpwr_writefn, s);
     cpu_register_physical_memory(s->clkpwr_base, 0xffffff, iomemtype);
 
-    s->lcd = s3c_lcd_init(0x4d000000, ds, s->pic);
+    s->lcd = s3c_lcd_init(0x4d000000, ds, s->irq[S3C_PIC_LCD]);
 
     s->nand_base = 0x4e000000;
     s3c_nand_reset(s);
@@ -2205,34 +2239,38 @@
     cpu_register_physical_memory(s->nand_base, 0xffffff, iomemtype);
 
     for (i = 0; s3c2410_uart[i].base; i ++) {
-        s->uart[i] = s3c_uart_init(s3c2410_uart[i].base, s->pic, s->dma,
-                        s3c2410_uart[i].irq, s3c2410_uart[i].dma);
+        s->uart[i] = s3c_uart_init(s3c2410_uart[i].base,
+                        &s->irq[s3c2410_uart[i].irq[0]],
+                        &s->drq[s3c2410_uart[i].dma[0]]);
         if (serial_hds[i])
             s3c_uart_attach(s->uart[i], serial_hds[i]);
     }
 
-    s->timers = s3c_timers_init(0x51000000, s->pic, s->dma);
+    s->timers = s3c_timers_init(0x51000000, &s->irq[S3C_PIC_TIMER0], s->drq);
 
-    s->udc = s3c_udc_init(0x52000000, s->pic, s->dma);
+    s->udc = s3c_udc_init(0x52000000, s->irq[S3C_PIC_USBD], s->drq);
 
     /* Watchdog at 0x53000000 */
 
-    s->i2c = s3c_i2c_init(0x54000000, s->pic);
+    s->i2c = s3c_i2c_init(0x54000000, s->irq[S3C_PIC_IIC]);
 
-    s->i2s = s3c_i2s_init(0x55000000, s->dma);
+    s->i2s = s3c_i2s_init(0x55000000, s->drq);
 
-    s->io = s3c_gpio_init(0x56000000, s->pic);
+    s->io = s3c_gpio_init(0x56000000, s->irq);
 
-    s->rtc = s3c_rtc_init(0x57000000, s->pic);
+    s->rtc = s3c_rtc_init(0x57000000, s->irq[S3C_PIC_RTC]);
 
-    s->adc = s3c_adc_init(0x58000000, s->pic);
+    s->adc = s3c_adc_init(0x58000000, s->irq[S3C_PICS_ADC],
+                    s->irq[S3C_PICS_TC]);
 
-    s->spi = s3c_spi_init(0x59000000, s->pic, s->dma, s->io);
+    s->spi = s3c_spi_init(0x59000000,
+                    s->irq[S3C_PIC_SPI0], s->drq[S3C_RQ_SPI0],
+                    s->irq[S3C_PIC_SPI1], s->drq[S3C_RQ_SPI1], s->io);
 
-    s->mmci = s3c_mmci_init(0x5a000000, s->pic, s->dma);
+    s->mmci = s3c_mmci_init(0x5a000000, s->irq[S3C_PIC_SDI], s->drq);
 
     if (usb_enabled) {
-        usb_ohci_init_memio(0x49000000, 3, -1, s->pic, S3C_PIC_USBH);
+        usb_ohci_init_memio(0x49000000, 3, -1, s->irq[S3C_PIC_USBH]);
     }
 
     /* Power on reset */

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_gpio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_gpio.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_gpio.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,10 +10,10 @@
 
 #define S3C_IO_BANKS	8
 
-struct s3c_gpio_state_s {
-    s3c_pic_handler_t handler;	/* Modelled as an interrupt controller */
+struct s3c_gpio_state_s {	/* Modelled as an interrupt controller */
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq *pic;
+    qemu_irq *in;
 
     struct {
         int n;
@@ -21,10 +21,7 @@
         uint32_t dat;
         uint32_t up;
         uint32_t mask;
-        struct {
-            gpio_handler_t fn;
-            void *opaque;
-        } handler[32];
+        qemu_irq handler[32];
     } bank[S3C_IO_BANKS];
 
     uint32_t inform[2];
@@ -44,18 +41,18 @@
     s->eintpend |= (1 << irq) & 0x00fffff0;
     switch (irq) {
     case 0 ... 3:
-        pic_set_irq_new(s->pic, S3C_PIC_EINT0 + irq, 1);
+        qemu_irq_raise(s->pic[S3C_PIC_EINT0 + irq]);
         break;
     case 4 ... 7:
-        pic_set_irq_new(s->pic, S3C_PIC_EINT4, 1);
+        qemu_irq_raise(s->pic[S3C_PIC_EINT4]);
         break;
     case 8 ... 23:
-        pic_set_irq_new(s->pic, S3C_PIC_EINT8, 1);
+        qemu_irq_raise(s->pic[S3C_PIC_EINT8]);
         break;
     }
 }
 
-void s3c_gpio_set(void *opaque, int line, int level)
+static void s3c_gpio_set(void *opaque, int line, int level)
 {
     struct s3c_gpio_state_s *s = (struct s3c_gpio_state_s *) opaque;
     int e, eint, bank = line >> 5;
@@ -106,15 +103,18 @@
     }
 }
 
-void s3c_gpio_handler_set(struct s3c_gpio_state_s *s, int line,
-                gpio_handler_t handler, void *opaque)
+qemu_irq *s3c_gpio_in_get(struct s3c_gpio_state_s *s)
 {
+    return s->in;
+}
+
+void s3c_gpio_out_set(struct s3c_gpio_state_s *s, int line, qemu_irq handler)
+{
     int bank = line >> 5;
     line &= 0x1f;
     if (bank >= S3C_IO_BANKS || line >= s->bank[bank].n)
         cpu_abort(cpu_single_env, "%s: No I/O port %i\n", __FUNCTION__, line);
-    s->bank[bank].handler[line].fn = handler;
-    s->bank[bank].handler[line].opaque = opaque;
+    s->bank[bank].handler[line] = handler;
 }
 
 void s3c_gpio_reset(struct s3c_gpio_state_s *s)
@@ -281,17 +281,11 @@
         s->bank[bank].dat = value;
         while ((ln = ffs(diff))) {
             ln --;
-            if (s->bank[bank].handler[ln].fn) {
+            if (s->bank[bank].handler[ln]) {
                 if (bank && ((s->bank[bank].con >> (2 * ln)) & 3) == 1)
-                    s->bank[bank].handler[ln].fn(
-                                    (bank << 5) | ln,
-                                    (value >> ln) & 1,
-                                    s->bank[bank].handler[ln].opaque);
+                    qemu_set_irq(s->bank[bank].handler[ln], (value >> ln) & 1);
                 else if (!bank && ((s->bank[bank].con >> ln) & 1) == 0)
-                    s->bank[bank].handler[ln].fn(
-                                    (bank << 5) | ln,
-                                    (value >> ln) & 1,
-                                    s->bank[bank].handler[ln].opaque);
+                    qemu_set_irq(s->bank[bank].handler[ln], (value >> ln) & 1);
             }
             diff &= ~(1 << ln);
         }
@@ -316,7 +310,7 @@
     s3c_gpio_write,
 };
 
-struct s3c_gpio_state_s *s3c_gpio_init(target_phys_addr_t base, void *pic)
+struct s3c_gpio_state_s *s3c_gpio_init(target_phys_addr_t base, qemu_irq *pic)
 {
     int iomemtype;
     struct s3c_gpio_state_s *s = (struct s3c_gpio_state_s *)
@@ -324,7 +318,7 @@
 
     s->base = base;
     s->pic = pic;
-    s->handler = s3c_gpio_set;
+    s->in = qemu_allocate_irqs(s3c_gpio_set, s, S3C_GP_MAX);
 
     s->bank[0].n = 23;
     s->bank[1].n = 11;

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_lcd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_lcd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_lcd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -12,7 +12,7 @@
 
 struct s3c_lcd_state_s {
     target_phys_addr_t base;
-    void *pic;
+    void *irq;
     DisplayState *ds;
     s3c_drawfn_t *line_fn;
 
@@ -48,7 +48,7 @@
 static void s3c_lcd_update(struct s3c_lcd_state_s *s)
 {
     s->intpnd |= s->srcpnd & ~s->intmsk;
-    pic_set_irq_new(s->pic, S3C_PIC_LCD, !!s->intpnd);
+    qemu_set_irq(s->irq, !!s->intpnd);
 }
 
 void s3c_lcd_reset(struct s3c_lcd_state_s *s)
@@ -184,7 +184,7 @@
         break;
     case S3C_LCDSADDR1:
         s->saddr[0] = value;
-        s->fb = phys_ram_base + S3C_SRAM_SIZE +
+        s->fb = phys_ram_base +
                 (((s->saddr[0] << 1) & 0x7ffffffe) - S3C_RAM_BASE);
         s->invalidate = 1;
         break;
@@ -428,10 +428,8 @@
         }
         if (dirty[0] || s->invalidate) {
             s->fn(s->palette, dest, src, s->width, s->dest_width);
-            if (y > maxy) {
-                maxy = y;
-                end = new_addr;
-            }
+            maxy = y;
+            end = new_addr;
             if (y < miny) {
                 miny = y;
                 start = addr;
@@ -474,14 +472,14 @@
 #include "s3c24xx_template.h"
 
 struct s3c_lcd_state_s *s3c_lcd_init(target_phys_addr_t base, DisplayState *ds,
-                void *pic)
+                qemu_irq irq)
 {
     int iomemtype;
     struct s3c_lcd_state_s *s = (struct s3c_lcd_state_s *)
             qemu_mallocz(sizeof(struct s3c_lcd_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
     s->ds = ds;
 
     s3c_lcd_reset(s);

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_mmci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -11,10 +11,10 @@
 
 struct s3c_mmci_state_s {
     target_phys_addr_t base;
-    void *pic;
-    void *dma;
+    qemu_irq irq;
+    qemu_irq *dma;
 
-    struct sd_state_s *card;
+    SDState *card;
 
     int blklen;
     int blknum;
@@ -72,25 +72,25 @@
         s->dstatus |= 1 << 0;					/* RxDatOn */
         while (s->fifolen < 64 && s->blklen_cnt) {
             s->fifo[(s->fifostart + s->fifolen ++) & 63] =
-                    sd_read_datline(s->card);
+                    sd_read_data(s->card);
             if (!(-- s->blklen_cnt))
                 if (-- s->blknum_cnt)
                     s->blklen_cnt = s->blklen;
         }
         if ((s->mask & (1 << 0)) &&				/* RFHalf */
                         s->fifolen > 31 && len < 32)
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
         if ((s->mask & (1 << 1)) &&				/* RFFull */
                         s->fifolen > 63 && len < 64)
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
         if ((s->mask & (1 << 2)) && !s->blklen_cnt)		/* RFLast */
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
         dmalevel = !!s->fifolen;
     } else if (((s->dcontrol >> 12) & 3) == 3) {		/* DatMode */
         s->dstatus &= ~3;
         s->dstatus |= 1 << 0;					/* TxDatOn */
         while (s->fifolen && s->blklen_cnt) {
-            sd_write_datline(s->card, s->fifo[s->fifostart ++]);
+            sd_write_data(s->card, s->fifo[s->fifostart ++]);
             s->fifostart &= 63;
             s->fifolen --;
             if (!(-- s->blklen_cnt))
@@ -98,10 +98,10 @@
                     s->blklen_cnt = s->blklen;
         }
         if ((s->mask & (1 << 3)) && !s->fifolen && len)		/* TFEmpty */
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
         if ((s->mask & (1 << 4)) &&				/* TFHalf */
                         s->fifolen < 33 && len > 32)
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
         dmalevel = (s->fifolen < 64) && (s->blklen_cnt > 0);
     } else
         return;
@@ -111,31 +111,31 @@
         s->dstatus &= ~3;
         s->dstatus |= 1 << 4;					/* DatFin */
         if (s->mask & (1 << 7))					/* DatFin */
-            pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+            qemu_irq_raise(s->irq);
     }
 dmaupdate:
     if (s->dcontrol & (1 << 15)) {				/* EnDMA */
-        pic_set_irq_new(s->dma, S3C_RQ_SDI0, dmalevel);
-        pic_set_irq_new(s->dma, S3C_RQ_SDI1, dmalevel);
-        pic_set_irq_new(s->dma, S3C_RQ_SDI2, dmalevel);
+        qemu_set_irq(s->dma[S3C_RQ_SDI0], dmalevel);
+        qemu_set_irq(s->dma[S3C_RQ_SDI1], dmalevel);
+        qemu_set_irq(s->dma[S3C_RQ_SDI2], dmalevel);
     }
 }
 
 static void s3c_mmci_cmd_submit(struct s3c_mmci_state_s *s)
 {
-    int rsplen;
+    int rsplen, i;
     struct sd_request_s request;
-    union sd_response_u response;
+    char response[16];
 
     request.cmd = s->ccontrol & 0x3f;
     request.arg = s->arg;
     request.crc = 0;	/* FIXME */
 
-    response = sd_write_cmdline(s->card, request, &rsplen);
+    rsplen = sd_do_command(s->card, &request, response);
     s->cstatus = (s->cstatus & ~0x11ff) | request.cmd;		/* RspIndex */
     s->cstatus |= 1 << 11;					/* CmdSent */
     if (s->mask & (1 << 16))					/* CmdSent */
-        pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+        qemu_irq_raise(s->irq);
 
     memset(s->resp, 0, sizeof(s->resp));
     if (!(s->ccontrol & (1 << 9)))				/* WaitRsp */
@@ -143,42 +143,20 @@
 
     if (s->ccontrol & (1 << 10)) {				/* LongRsp */
         /* R2 */
-        if (rsplen < 128)
+        if (rsplen < 16)
             goto timeout;
-
-        s->resp[0] = bswap16(response.r2.reg[1]) |
-                (bswap16(response.r2.reg[0]) << 16);
-        s->resp[1] = bswap16(response.r2.reg[3]) |
-                (bswap16(response.r2.reg[2]) << 16);
-        s->resp[2] = bswap16(response.r2.reg[5]) |
-                (bswap16(response.r2.reg[4]) << 16);
-        s->resp[3] = bswap16(response.r2.reg[7]) |
-                (bswap16(response.r2.reg[6]) << 16);
     } else {
         /* R1, R3, R4, R5 or R6 */
-        if (request.cmd == 3) {		/* R6 */
-            if (rsplen < 48)
-                goto timeout;
-
-            s->resp[0] = response.r6.status | (response.r6.arg << 16);
-            s->resp[1] = response.r6.crc << 24;
-        } else if (request.cmd == 41) {	/* R3 */
-            if (rsplen < 32)
-                goto timeout;
-
-            s->resp[0] = response.r3.ocr_reg;
-        } else {
-            if (rsplen < 48)
-                goto timeout;
-
-            s->resp[0] = response.r1.status;
-            s->resp[1] = response.r1.crc << 24;
-        }
+        if (rsplen < 4)
+            goto timeout;
     }
 
+    for (i = 0; i < rsplen; i ++)
+        s->resp[i >> 2] |= response[i] << ((i & 3) << 3);
+
     s->cstatus |= 1 << 9;					/* RspFin */
     if (s->mask & (1 << 14))					/* RspEnd */
-        pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+        qemu_irq_raise(s->irq);
 
 complete:
     s->blklen_cnt = s->blklen;
@@ -198,7 +176,7 @@
 timeout:
     s->cstatus |= 1 << 10;					/* CmdTout */
     if (s->mask & (1 << 15))					/* CmdTout */
-        pic_set_irq_new(s->pic, S3C_PIC_SDI, 1);
+        qemu_irq_raise(s->irq);
 }
 
 #define S3C_SDICON	0x00	/* SDI Control register */
@@ -378,14 +356,14 @@
 };
 
 struct s3c_mmci_state_s *s3c_mmci_init(target_phys_addr_t base,
-                void *pic, void *dma)
+                qemu_irq irq, qemu_irq *dma)
 {
     int iomemtype;
     struct s3c_mmci_state_s *s = (struct s3c_mmci_state_s *)
             qemu_mallocz(sizeof(struct s3c_mmci_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
     s->dma = dma;
 
     s3c_mmci_reset(s);
@@ -395,7 +373,7 @@
     cpu_register_physical_memory(s->base, 0xffffff, iomemtype);
 
     /* Instantiate the actual storage */
-    s->card = sd_init();
+    s->card = sd_init(sd_bdrv);
 
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_rtc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_rtc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_rtc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -10,7 +10,7 @@
 
 struct s3c_rtc_state_s {
     target_phys_addr_t base;
-    void *pic;
+    qemu_irq irq;
     int enable;
     QEMUTimer *timer;
     QEMUTimer *hz;
@@ -60,7 +60,7 @@
     struct s3c_rtc_state_s *s = (struct s3c_rtc_state_s *) opaque;
     if (!(s->tick & (1 << 7)))
         return;
-    pic_set_irq_new(s->pic, S3C_PIC_RTC, 1);
+    qemu_irq_raise(s->irq);
 
     s3c_rtc_tick_mod(s);
 }
@@ -268,14 +268,14 @@
     s3c_rtc_write,
 };
 
-struct s3c_rtc_state_s *s3c_rtc_init(target_phys_addr_t base, void *pic)
+struct s3c_rtc_state_s *s3c_rtc_init(target_phys_addr_t base, qemu_irq irq)
 {
     int iomemtype;
     struct s3c_rtc_state_s *s = (struct s3c_rtc_state_s *)
             qemu_mallocz(sizeof(struct s3c_rtc_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
     s->timer = qemu_new_timer(vm_clock, s3c_rtc_tick, s);
     s->hz = qemu_new_timer(rt_clock, s3c_rtc_hz, s);
 

Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -13,8 +13,8 @@
 struct s3c_udc_state_s {
     target_phys_addr_t base;
     USBDevice dev;
-    void *pic;
-    void *dma;
+    qemu_irq irq;
+    qemu_irq *dma;
 
     /* Use FIFOs big enough to hold entire packets, just don't report
      * lengths greater than 16 and 64 bytes for EP0 and EP1-4 respectively.  */
@@ -90,7 +90,7 @@
         s->ep_intr |= 1 << ep;
     s->ep_intr &= s->ep_mask;
     s->usb_intr &= s->usb_mask;
-    pic_set_irq_new(s->pic, S3C_PIC_USBD, s->ep_intr | s->usb_intr);
+    qemu_set_irq(s->irq, s->ep_intr | s->usb_intr);
 }
 
 static void s3c_udc_queue_packet(uint8_t *dst, uint8_t *src,
@@ -669,14 +669,14 @@
 }
 
 struct s3c_udc_state_s *s3c_udc_init(target_phys_addr_t base,
-                void *pic, void *dma)
+                qemu_irq irq, qemu_irq *dma)
 {
     int iomemtype;
     struct s3c_udc_state_s *s = (struct s3c_udc_state_s *)
             qemu_mallocz(sizeof(struct s3c_udc_state_s));
 
     s->base = base;
-    s->pic = pic;
+    s->irq = irq;
     s->dma = dma;
 
     s->dev.speed = USB_SPEED_FULL;

Modified: trunk/src/host/qemu-neo1973/hw/sb16.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sb16.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sb16.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,6 +54,7 @@
 
 typedef struct SB16State {
     QEMUSoundCard card;
+    qemu_irq *pic;
     int irq;
     int dma;
     int hdma;
@@ -187,7 +188,7 @@
 {
     SB16State *s = opaque;
     s->can_write = 1;
-    pic_set_irq (s->irq, 1);
+    qemu_irq_raise (s->pic[s->irq]);
 }
 
 #define DMA8_AUTO 1
@@ -595,7 +596,7 @@
         case 0xf3:
             dsp_out_data (s, 0xaa);
             s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
-            pic_set_irq (s->irq, 1);
+            qemu_irq_raise (s->pic[s->irq]);
             break;
 
         case 0xf9:
@@ -763,7 +764,7 @@
                 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
                 ticks = (bytes * ticks_per_sec) / freq;
                 if (ticks < ticks_per_sec / 1024) {
-                    pic_set_irq (s->irq, 1);
+                    qemu_irq_raise (s->pic[s->irq]);
                 }
                 else {
                     if (s->aux_ts) {
@@ -855,10 +856,10 @@
 
 static void reset (SB16State *s)
 {
-    pic_set_irq (s->irq, 0);
+    qemu_irq_lower (s->pic[s->irq]);
     if (s->dma_auto) {
-        pic_set_irq (s->irq, 1);
-        pic_set_irq (s->irq, 0);
+        qemu_irq_raise (s->pic[s->irq]);
+        qemu_irq_lower (s->pic[s->irq]);
     }
 
     s->mixer_regs[0x82] = 0;
@@ -894,7 +895,7 @@
             if (s->v2x6 == 1) {
                 if (0 && s->highspeed) {
                     s->highspeed = 0;
-                    pic_set_irq (s->irq, 0);
+                    qemu_irq_lower (s->pic[s->irq]);
                     control (s, 0);
                 }
                 else {
@@ -1005,7 +1006,7 @@
         if (s->mixer_regs[0x82] & 1) {
             ack = 1;
             s->mixer_regs[0x82] &= 1;
-            pic_set_irq (s->irq, 0);
+            qemu_irq_lower (s->pic[s->irq]);
         }
         break;
 
@@ -1014,7 +1015,7 @@
         if (s->mixer_regs[0x82] & 2) {
             ack = 1;
             s->mixer_regs[0x82] &= 2;
-            pic_set_irq (s->irq, 0);
+            qemu_irq_lower (s->pic[s->irq]);
         }
         break;
 
@@ -1222,7 +1223,7 @@
 
     if (s->left_till_irq <= 0) {
         s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
-        pic_set_irq (s->irq, 1);
+        qemu_irq_raise (s->pic[s->irq]);
         if (0 == s->dma_auto) {
             control (s, 0);
             speaker (s, 0);
@@ -1389,7 +1390,7 @@
     return 0;
 }
 
-int SB16_init (AudioState *audio)
+int SB16_init (AudioState *audio, qemu_irq *pic)
 {
     SB16State *s;
     int i;
@@ -1409,6 +1410,7 @@
     }
 
     s->cmd = -1;
+    s->pic = pic;
     s->irq = conf.irq;
     s->dma = conf.dma;
     s->hdma = conf.hdma;

Modified: trunk/src/host/qemu-neo1973/hw/scsi-disk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-disk.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/scsi-disk.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -345,7 +345,7 @@
         DPRINTF("Request Sense (len %d)\n", len);
         if (len < 4)
             goto fail;
-        memset(buf, 0, 4);
+        memset(outbuf, 0, 4);
         outbuf[0] = 0xf0;
         outbuf[1] = 0;
         outbuf[2] = s->sense;
@@ -371,7 +371,7 @@
            Some later commands are also implemented. */
 	outbuf[2] = 3;
 	outbuf[3] = 2; /* Format 2 */
-	outbuf[4] = 32;
+	outbuf[4] = 31;
         /* Sync data transfer and TCQ.  */
         outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0);
 	r->buf_len = 36;
@@ -404,10 +404,11 @@
             p += 4;
             if ((page == 8 || page == 0x3f)) {
                 /* Caching page.  */
+                memset(p,0,20);
                 p[0] = 8;
                 p[1] = 0x12;
                 p[2] = 4; /* WCE */
-                p += 19;
+                p += 20;
             }
             if ((page == 0x3f || page == 0x2a)
                     && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
@@ -437,7 +438,7 @@
                 p[19] = (16 * 176) & 0xff;
                 p[20] = (16 * 176) >> 8; // 16x write speed current
                 p[21] = (16 * 176) & 0xff;
-                p += 21;
+                p += 22;
             }
             r->buf_len = p - outbuf;
             outbuf[0] = r->buf_len - 4;

Modified: trunk/src/host/qemu-neo1973/hw/sd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -3,6 +3,7 @@
  * layer specification, Version 1.10."
  *
  * Copyright (c) 2006 Andrzej Zaborowski  <balrog at zabor.org>
+ * Copyright (c) 2007 CodeSourcery
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,173 +31,175 @@
 
 #include "sd.h"
 
-struct sd_state_s {
-	enum {
-		sd_inactive,
-		sd_card_identification_mode,
-		sd_data_transfer_mode,
-	} mode;
-	enum {
-		sd_inactive_state = -1,
-		sd_idle_state = 0,
-		sd_ready_state,
-		sd_identification_state,
-		sd_standby_state,
-		sd_transfer_state,
-		sd_sendingdata_state,
-		sd_receivingdata_state,
-		sd_programming_state,
-		sd_disconnect_state,
-	} state;
-	uint32_t ocr;
-	uint8_t scr[8];
-	uint8_t cid[16];
-	uint8_t csd[16];
-	uint16_t rca;
-	uint32_t card_status;
-	uint8_t sd_status[64];
-	int wp_switch;
-	int *wp_groups;
-	uint32_t size;
-	int blk_len;
-	uint32_t erase_start;
-	uint32_t erase_end;
-	uint8_t pwd[16];
-	int pwd_len;
-	int function_group[6];
+//#define DEBUG_SD 1
 
-	int current_cmd;
-	int blk_written;
-	uint32_t data_start;
-	uint32_t data_offset;
-	uint8_t data[512];
-	void (*readonly_cb)(void *, int);
-	void (*inserted_cb)(void *, int);
-	void *opaque;
-	BlockDriverState *bdrv;
+#ifdef DEBUG_SD
+#define DPRINTF(fmt, args...) \
+do { printf("SD: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+typedef enum {
+    sd_r0 = 0,    /* no response */
+    sd_r1,        /* normal response command */
+    sd_r2_i,      /* CID register */
+    sd_r2_s,      /* CSD register */
+    sd_r3,        /* OCR register */
+    sd_r6 = 6,    /* Published RCA response */
+    sd_r1b = -1,
+} sd_rsp_type_t;
+
+struct SDState {
+    enum {
+        sd_inactive,
+        sd_card_identification_mode,
+        sd_data_transfer_mode,
+    } mode;
+    enum {
+        sd_inactive_state = -1,
+        sd_idle_state = 0,
+        sd_ready_state,
+        sd_identification_state,
+        sd_standby_state,
+        sd_transfer_state,
+        sd_sendingdata_state,
+        sd_receivingdata_state,
+        sd_programming_state,
+        sd_disconnect_state,
+    } state;
+    uint32_t ocr;
+    uint8_t scr[8];
+    uint8_t cid[16];
+    uint8_t csd[16];
+    uint16_t rca;
+    uint32_t card_status;
+    uint8_t sd_status[64];
+    int wp_switch;
+    int *wp_groups;
+    uint32_t size;
+    int blk_len;
+    uint32_t erase_start;
+    uint32_t erase_end;
+    uint8_t pwd[16];
+    int pwd_len;
+    int function_group[6];
+
+    int current_cmd;
+    int blk_written;
+    uint32_t data_start;
+    uint32_t data_offset;
+    uint8_t data[512];
+    void (*readonly_cb)(void *, int);
+    void (*inserted_cb)(void *, int);
+    void *opaque;
+    BlockDriverState *bdrv;
 };
 
-static void sd_set_status(struct sd_state_s *sd) {
-	switch (sd->state) {
-	case sd_inactive_state:
-		sd->mode = sd_inactive;
-		break;
+static void sd_set_status(SDState *sd)
+{
+    switch (sd->state) {
+    case sd_inactive_state:
+        sd->mode = sd_inactive;
+        break;
 
-	case sd_idle_state:
-	case sd_ready_state:
-	case sd_identification_state:
-		sd->mode = sd_card_identification_mode;
-		break;
+    case sd_idle_state:
+    case sd_ready_state:
+    case sd_identification_state:
+        sd->mode = sd_card_identification_mode;
+        break;
 
-	case sd_standby_state:
-	case sd_transfer_state:
-	case sd_sendingdata_state:
-	case sd_receivingdata_state:
-	case sd_programming_state:
-	case sd_disconnect_state:
-		sd->mode = sd_data_transfer_mode;
-		break;
-	}
+    case sd_standby_state:
+    case sd_transfer_state:
+    case sd_sendingdata_state:
+    case sd_receivingdata_state:
+    case sd_programming_state:
+    case sd_disconnect_state:
+        sd->mode = sd_data_transfer_mode;
+        break;
+    }
 
-	sd->card_status &= ~CURRENT_STATE;
-	sd->card_status |= sd->state << 9;
+    sd->card_status &= ~CURRENT_STATE;
+    sd->card_status |= sd->state << 9;
 }
 
 const sd_cmd_type_t sd_cmd_type[64] = {
-	sd_bc,   sd_none, sd_bcr,  sd_bcr,  sd_none, sd_none, sd_none, sd_ac,
-	sd_none, sd_ac,   sd_ac,   sd_adtc, sd_ac,   sd_ac,   sd_none, sd_ac,
-	sd_ac,   sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none,
-	sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac,   sd_ac,   sd_adtc, sd_none,
-	sd_ac,   sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
-	sd_none, sd_none, sd_bc,   sd_none, sd_none, sd_none, sd_none, sd_none,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,
-	sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_bc,   sd_none, sd_bcr,  sd_bcr,  sd_none, sd_none, sd_none, sd_ac,
+    sd_none, sd_ac,   sd_ac,   sd_adtc, sd_ac,   sd_ac,   sd_none, sd_ac,
+    sd_ac,   sd_adtc, sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_adtc, sd_adtc, sd_adtc, sd_adtc, sd_ac,   sd_ac,   sd_adtc, sd_none,
+    sd_ac,   sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
+    sd_none, sd_none, sd_bc,   sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,
+    sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 };
 
 const sd_cmd_type_t sd_acmd_type[64] = {
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
-	sd_none, sd_bcr,  sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_none,
-	sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, sd_none, sd_none,
-	sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac,   sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_bcr,  sd_ac,   sd_none, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, sd_none, sd_none,
+    sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
 };
 
 static const int sd_cmd_class[64] = {
-	0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-	2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
-	5,  5, 10, 10, 10, 10,  5,  9,  9,  9,  7,  7,  7,  7,  7,  7,
-	7,  7, 10,  7,  9,  9,  9,  8,  8, 10,  8,  8,  8,  8,  8,  8,
+    0,  0,  0,  0,  0,  9, 10,  0,  0,  0,  0,  1,  0,  0,  0,  0,
+    2,  2,  2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  6,  6,  6,  6,
+    5,  5, 10, 10, 10, 10,  5,  9,  9,  9,  7,  7,  7,  7,  7,  7,
+    7,  7, 10,  7,  9,  9,  9,  8,  8, 10,  8,  8,  8,  8,  8,  8,
 };
 
-static const sd_rsp_type_t sd_cmd_response[64] = {
-	sd_nore, sd_nore, sd_r2,   sd_r6,   sd_nore, sd_nore, sd_r1,   sd_r1b,
-	sd_nore, sd_r2,   sd_r2,   sd_nore, sd_r1b,  sd_r1,   sd_nore, sd_nore,
-	sd_r1,   sd_r1,   sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_r1,   sd_r1,   sd_r1,   sd_r1,   sd_r1b,  sd_r1b,  sd_r1,   sd_nore,
-	sd_r1,   sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore, sd_r1b,  sd_nore,
-	sd_nore, sd_nore, sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_r1,
-	sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-};
+static uint8_t sd_crc7(void *message, size_t width)
+{
+    int i, bit;
+    uint8_t shift_reg = 0x00;
+    uint8_t *msg = (uint8_t *) message;
 
-static const sd_rsp_type_t sd_acmd_response[64] = {
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_r1,   sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_r1,   sd_nore, sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_r1,   sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_nore, sd_r3,   sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_r1,   sd_nore, sd_nore, sd_nore, sd_nore,
-	sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore, sd_nore,
-};
+    for (i = 0; i < width; i ++, msg ++)
+        for (bit = 7; bit >= 0; bit --) {
+            shift_reg <<= 1;
+            if ((shift_reg >> 7) ^ ((*msg >> bit) & 1))
+                shift_reg ^= 0x89;
+        }
 
-static uint8_t sd_crc7(void *message, size_t width) {
-	int i, bit;
-	uint8_t shift_reg = 0x00;
-	uint8_t *msg = (uint8_t *) message;
-
-	for (i = 0; i < width; i ++, msg ++)
-		for (bit = 7; bit >= 0; bit --) {
-			shift_reg <<= 1;
-			if ((shift_reg >> 7) ^ ((*msg >> bit) & 1))
-				shift_reg ^= 0x89;
-		}
-
-	return shift_reg;
+    return shift_reg;
 }
 
-static uint16_t sd_crc16(void *message, size_t width) {
-	int i, bit;
-	uint16_t shift_reg = 0x0000;
-	uint16_t *msg = (uint16_t *) message;
-	width <<= 1;
+static uint16_t sd_crc16(void *message, size_t width)
+{
+    int i, bit;
+    uint16_t shift_reg = 0x0000;
+    uint16_t *msg = (uint16_t *) message;
+    width <<= 1;
 
-	for (i = 0; i < width; i ++, msg ++)
-		for (bit = 15; bit >= 0; bit --) {
-			shift_reg <<= 1;
-			if ((shift_reg >> 15) ^ ((*msg >> bit) & 1))
-				shift_reg ^= 0x1011;
-		}
+    for (i = 0; i < width; i ++, msg ++)
+        for (bit = 15; bit >= 0; bit --) {
+            shift_reg <<= 1;
+            if ((shift_reg >> 15) ^ ((*msg >> bit) & 1))
+                shift_reg ^= 0x1011;
+        }
 
-	return shift_reg;
+    return shift_reg;
 }
 
-static void sd_set_ocr(struct sd_state_s *sd) {
-	sd->ocr = 0x80fffff0;
+static void sd_set_ocr(SDState *sd)
+{
+    sd->ocr = 0x80fffff0;
 }
 
-static void sd_set_scr(struct sd_state_s *sd) {
-	sd->scr[0] = 0x00;	/* SCR Structure */
-	sd->scr[1] = 0x2f;	/* SD Security Support */
-	sd->scr[2] = 0x00;
-	sd->scr[3] = 0x00;
-	sd->scr[4] = 0x00;
-	sd->scr[5] = 0x00;
-	sd->scr[6] = 0x00;
-	sd->scr[7] = 0x00;
+static void sd_set_scr(SDState *sd)
+{
+    sd->scr[0] = 0x00;		/* SCR Structure */
+    sd->scr[1] = 0x2f;		/* SD Security Support */
+    sd->scr[2] = 0x00;
+    sd->scr[3] = 0x00;
+    sd->scr[4] = 0x00;
+    sd->scr[5] = 0x00;
+    sd->scr[6] = 0x00;
+    sd->scr[7] = 0x00;
 }
 
 #define MID	0xaa
@@ -206,24 +209,25 @@
 #define MDT_YR	2006
 #define MDT_MON	2
 
-static void sd_set_cid(struct sd_state_s *sd) {
-	sd->cid[0] = MID;	/* Fake card manufacturer ID (MID) */
-	sd->cid[1] = OID[0];	/* OEM/Application ID (OID) */
-	sd->cid[2] = OID[1];
-	sd->cid[3] = PNM[0];	/* Fake product name (PNM) */
-	sd->cid[4] = PNM[1];
-	sd->cid[5] = PNM[2];
-	sd->cid[6] = PNM[3];
-	sd->cid[7] = PNM[4];
-	sd->cid[8] = PRV;	/* Fake product revision (PRV) */
-	sd->cid[9] = 0xde;	/* Fake serial number (PSN) */
-	sd->cid[10] = 0xad;
-	sd->cid[11] = 0xbe;
-	sd->cid[12] = 0xef;
-	sd->cid[13] = 0x00 |	/* Manufacture date (MDT) */
-		((MDT_YR - 2000) / 10);
-	sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON;
-	sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1;
+static void sd_set_cid(SDState *sd)
+{
+    sd->cid[0] = MID;		/* Fake card manufacturer ID (MID) */
+    sd->cid[1] = OID[0];	/* OEM/Application ID (OID) */
+    sd->cid[2] = OID[1];
+    sd->cid[3] = PNM[0];	/* Fake product name (PNM) */
+    sd->cid[4] = PNM[1];
+    sd->cid[5] = PNM[2];
+    sd->cid[6] = PNM[3];
+    sd->cid[7] = PNM[4];
+    sd->cid[8] = PRV;		/* Fake product revision (PRV) */
+    sd->cid[9] = 0xde;		/* Fake serial number (PSN) */
+    sd->cid[10] = 0xad;
+    sd->cid[11] = 0xbe;
+    sd->cid[12] = 0xef;
+    sd->cid[13] = 0x00 |	/* Manufacture date (MDT) */
+        ((MDT_YR - 2000) / 10);
+    sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON;
+    sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1;
 }
 
 #define HWBLOCK_SHIFT	9			/* 512 bytes */
@@ -235,1031 +239,1033 @@
 #define WPGROUP_SIZE	(1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT))
 
 static const uint8_t sd_csd_rw_mask[16] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfe,
 };
 
-static void sd_set_csd(struct sd_state_s *sd, uint32_t size) {
-	uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1;
-	uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
-	uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
+static void sd_set_csd(SDState *sd, uint32_t size)
+{
+    uint32_t csize = (size >> (CMULT_SHIFT + HWBLOCK_SHIFT)) - 1;
+    uint32_t sectsize = (1 << (SECTOR_SHIFT + 1)) - 1;
+    uint32_t wpsize = (1 << (WPGROUP_SHIFT + 1)) - 1;
 
-	sd->csd[0] = 0x00;	/* CSD structure */
-	sd->csd[1] = 0x26;	/* Data read access-time-1 */
-	sd->csd[2] = 0x00;	/* Data read access-time-2 */
-	sd->csd[3] = 0x5a;	/* Max. data transfer rate */
-	sd->csd[4] = 0x5f;	/* Card Command Classes */
-	sd->csd[5] = 0x50 |	/* Max. read data block length */
-		HWBLOCK_SHIFT;
-	sd->csd[6] = 0xe0 |	/* Partial block for read allowed */
-		((csize >> 10) & 0x03);
-	sd->csd[7] = 0x00 |	/* Device size */
-		((csize >> 2) & 0xff);
-	sd->csd[8] = 0x3f |	/* Max. read current */
-		((csize << 6) & 0xc0);
-	sd->csd[9] = 0xfc |	/* Max. write current */
-		((CMULT_SHIFT - 2) >> 1);
-	sd->csd[10] = 0x40 |	/* Erase sector size */
-		(((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
-	sd->csd[11] = 0x00 |	/* Write protect group size */
-		((sectsize << 7) & 0x80) | wpsize;
-	sd->csd[12] = 0x90 |	/* Write speed factor */
-		(HWBLOCK_SHIFT >> 2);
-	sd->csd[13] = 0x20 |	/* Max. write data block length */
-		((HWBLOCK_SHIFT << 6) & 0xc0);
-	sd->csd[14] = 0x00;	/* File format group */
-	sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
+    sd->csd[0] = 0x00;		/* CSD structure */
+    sd->csd[1] = 0x26;		/* Data read access-time-1 */
+    sd->csd[2] = 0x00;		/* Data read access-time-2 */
+    sd->csd[3] = 0x5a;		/* Max. data transfer rate */
+    sd->csd[4] = 0x5f;		/* Card Command Classes */
+    sd->csd[5] = 0x50 |		/* Max. read data block length */
+        HWBLOCK_SHIFT;
+    sd->csd[6] = 0xe0 |		/* Partial block for read allowed */
+        ((csize >> 10) & 0x03);
+    sd->csd[7] = 0x00 |		/* Device size */
+        ((csize >> 2) & 0xff);
+    sd->csd[8] = 0x3f |		/* Max. read current */
+        ((csize << 6) & 0xc0);
+    sd->csd[9] = 0xfc |		/* Max. write current */
+        ((CMULT_SHIFT - 2) >> 1);
+    sd->csd[10] = 0x40 |	/* Erase sector size */
+        (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
+    sd->csd[11] = 0x00 |	/* Write protect group size */
+        ((sectsize << 7) & 0x80) | wpsize;
+    sd->csd[12] = 0x90 |	/* Write speed factor */
+        (HWBLOCK_SHIFT >> 2);
+    sd->csd[13] = 0x20 |	/* Max. write data block length */
+        ((HWBLOCK_SHIFT << 6) & 0xc0);
+    sd->csd[14] = 0x00;		/* File format group */
+    sd->csd[15] = (sd_crc7(sd->csd, 15) << 1) | 1;
 }
 
-static void sd_set_rca(struct sd_state_s *sd) {
-	sd->rca += 0x4567;
+static void sd_set_rca(SDState *sd)
+{
+    sd->rca += 0x4567;
 }
 
 #define CARD_STATUS_A	0x02004100
 #define CARD_STATUS_B	0x00c01e00
 #define CARD_STATUS_C	0xfd39a028
 
-static void sd_set_cardstatus(struct sd_state_s *sd) {
-	sd->card_status = 0x00000100;
+static void sd_set_cardstatus(SDState *sd)
+{
+    sd->card_status = 0x00000100;
 }
 
-static void sd_set_sdstatus(struct sd_state_s *sd) {
-	memset(sd->sd_status, 0, 64);
+static void sd_set_sdstatus(SDState *sd)
+{
+    memset(sd->sd_status, 0, 64);
 }
 
-static int sd_req_crc_validate(struct sd_request_s *req) {
-	uint8_t buffer[5];
-	buffer[0] = 0x40 | req->cmd;
-	buffer[1] = (req->arg >> 24) & 0xff;
-	buffer[2] = (req->arg >> 16) & 0xff;
-	buffer[3] = (req->arg >> 8) & 0xff;
-	buffer[4] = (req->arg >> 0) & 0xff;
-	return 0;
-	return sd_crc7(buffer, 5) != req->crc;	/* TODO */
+static int sd_req_crc_validate(struct sd_request_s *req)
+{
+    uint8_t buffer[5];
+    buffer[0] = 0x40 | req->cmd;
+    buffer[1] = (req->arg >> 24) & 0xff;
+    buffer[2] = (req->arg >> 16) & 0xff;
+    buffer[3] = (req->arg >> 8) & 0xff;
+    buffer[4] = (req->arg >> 0) & 0xff;
+    return 0;
+    return sd_crc7(buffer, 5) != req->crc;	/* TODO */
 }
 
-void sd_response_r1_make(struct sd_state_s *sd,
-		union sd_response_u *response, uint32_t last_status) {
-	int buffer[5];
-	uint32_t mask = CARD_STATUS_B ^ ILLEGAL_COMMAND;
+void sd_response_r1_make(SDState *sd,
+                         uint8_t *response, uint32_t last_status)
+{
+    uint32_t mask = CARD_STATUS_B ^ ILLEGAL_COMMAND;
+    uint32_t status;
 
-	response->r1.cmd = sd->current_cmd;
-	response->r1.status = (sd->card_status & ~mask) | (last_status & mask);
-	sd->card_status &= ~CARD_STATUS_C | APP_CMD;
+    status = (sd->card_status & ~mask) | (last_status & mask);
+    sd->card_status &= ~CARD_STATUS_C | APP_CMD;
 
-	buffer[0] = 0x00 | response->r1.cmd;
-	buffer[1] = (response->r1.status >> 24) & 0xff;
-	buffer[2] = (response->r1.status >> 16) & 0xff;
-	buffer[3] = (response->r1.status >> 8) & 0xff;
-	buffer[4] = (response->r1.status >> 0) & 0xff;
-	response->r1.crc = sd_crc7(buffer, 5);
+    response[0] = (status >> 24) & 0xff;
+    response[1] = (status >> 16) & 0xff;
+    response[2] = (status >> 8) & 0xff;
+    response[3] = (status >> 0) & 0xff;
 }
 
-void sd_response_r2_make(struct sd_state_s *sd,
-		union sd_response_u *response) {
-	response->r2.reg[7] |= 0x01;
+void sd_response_r3_make(SDState *sd, uint8_t *response)
+{
+    response[0] = (sd->ocr >> 24) & 0xff;
+    response[1] = (sd->ocr >> 16) & 0xff;
+    response[2] = (sd->ocr >> 8) & 0xff;
+    response[3] = (sd->ocr >> 0) & 0xff;
 }
 
-void sd_response_r3_make(struct sd_state_s *sd,
-		union sd_response_u *response) {
-	response->r3.ocr_reg = sd->ocr;
-}
+void sd_response_r6_make(SDState *sd, uint8_t *response)
+{
+    uint16_t arg;
+    uint16_t status;
 
-void sd_response_r6_make(struct sd_state_s *sd,
-		union sd_response_u *response) {
-	int buffer[5];
+    arg = sd->rca;
+    status = ((sd->card_status >> 8) & 0xc000) |
+             ((sd->card_status >> 6) & 0x2000) |
+              (sd->card_status & 0x1fff);
 
-	response->r6.cmd = sd->current_cmd;
-	response->r6.arg = sd->rca;
-	response->r6.status =
-		((sd->card_status >> 8) & 0xc000) |
-		((sd->card_status >> 6) & 0x2000) |
-		(sd->card_status & 0x1fff);
-
-	buffer[0] = 0x00 | response->r6.cmd;
-	buffer[1] = (response->r6.arg >> 8) & 0xff;
-	buffer[2] = (response->r6.arg >> 0) & 0xff;
-	buffer[3] = (response->r6.status >> 8) & 0xff;
-	buffer[4] = (response->r6.status >> 0) & 0xff;
-	response->r6.crc = sd_crc7(buffer, 5);
+    response[0] = (arg >> 8) & 0xff;
+    response[1] = arg & 0xff;
+    response[2] = (status >> 8) & 0xff;
+    response[3] = status & 0xff;
 }
 
-static void sd_reset(struct sd_state_s *sd, BlockDriverState *bdrv) {
-	uint32_t size;
-	uint64_t sect;
+static void sd_reset(SDState *sd, BlockDriverState *bdrv)
+{
+    uint32_t size;
+    uint64_t sect;
 
-	bdrv_get_geometry(bdrv, &sect);
-	sect <<= 9;
+    bdrv_get_geometry(bdrv, &sect);
+    sect <<= 9;
 
-	if (sect > 0x40000000)
-		size = 0x40000000;	/* 1 gig */
-	else
-		size = sect + 1;
+    if (sect > 0x40000000)
+        size = 0x40000000;	/* 1 gig */
+    else
+        size = sect + 1;
 
-	sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
+    sect = (size >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) + 1;
 
-	sd->state = sd_idle_state;
-	sd->rca = 0x0000;
-	sd_set_ocr(sd);
-	sd_set_scr(sd);
-	sd_set_cid(sd);
-	sd_set_csd(sd, size);
-	sd_set_cardstatus(sd);
-	sd_set_sdstatus(sd);
+    sd->state = sd_idle_state;
+    sd->rca = 0x0000;
+    sd_set_ocr(sd);
+    sd_set_scr(sd);
+    sd_set_cid(sd);
+    sd_set_csd(sd, size);
+    sd_set_cardstatus(sd);
+    sd_set_sdstatus(sd);
 
-	sd->bdrv = bdrv;
+    sd->bdrv = bdrv;
 
-	sd->wp_switch = bdrv_is_read_only(bdrv);
-	sd->wp_groups = (int *) qemu_mallocz(sizeof(int) * sect);
-	memset(sd->wp_groups, 0, sizeof(int) * sect);
-	memset(sd->function_group, 0, sizeof(int) * 6);
-	sd->erase_start = 0;
-	sd->erase_end = 0;
-	sd->size = size;
-	sd->blk_len = 0x200;
-	sd->pwd_len = 0;
+    sd->wp_switch = bdrv_is_read_only(bdrv);
+    sd->wp_groups = (int *) qemu_mallocz(sizeof(int) * sect);
+    memset(sd->wp_groups, 0, sizeof(int) * sect);
+    memset(sd->function_group, 0, sizeof(int) * 6);
+    sd->erase_start = 0;
+    sd->erase_end = 0;
+    sd->size = size;
+    sd->blk_len = 0x200;
+    sd->pwd_len = 0;
 }
 
-static void sd_cardchange(void *opaque) {
-	struct sd_state_s *sd = opaque;
-	if (sd->inserted_cb)
-		sd->inserted_cb(sd->opaque, bdrv_is_inserted(sd->bdrv));
-	if (bdrv_is_inserted(sd->bdrv)) {
-		sd_reset(sd, sd->bdrv);
-		if (sd->readonly_cb)
-			sd->readonly_cb(sd->opaque, sd->wp_switch);
-	}
+static void sd_cardchange(void *opaque)
+{
+    SDState *sd = opaque;
+    if (sd->inserted_cb)
+        sd->inserted_cb(sd->opaque, bdrv_is_inserted(sd->bdrv));
+    if (bdrv_is_inserted(sd->bdrv)) {
+        sd_reset(sd, sd->bdrv);
+        if (sd->readonly_cb)
+            sd->readonly_cb(sd->opaque, sd->wp_switch);
+    }
 }
 
-struct sd_state_s *sd_init() {
-	struct sd_state_s *sd;
-	BlockDriverState *bs = bdrv_new("sd");
-	bdrv_set_type_hint(bs, BDRV_TYPE_FLOPPY);
+SDState *sd_init(BlockDriverState *bs)
+{
+    SDState *sd;
 
-	if (sd_filename) {
-		if (bdrv_open(bs, sd_filename,
-					snapshot ? BDRV_O_SNAPSHOT : 0) < 0)
-			fprintf(stderr, "%s: Couldn't open %s\n",
-					__FUNCTION__, sd_filename);
-		else
-			qemu_key_check(bs, sd_filename);
-	}
-
-	sd = (struct sd_state_s *) qemu_mallocz(sizeof(struct sd_state_s));
-	sd_reset(sd, bs);
-	return sd;
+    sd = (SDState *) qemu_mallocz(sizeof(SDState));
+    sd_reset(sd, bs);
+    return sd;
 }
 
-void sd_set_cb(struct sd_state_s *sd, void *opaque,
-		void (*readonly_cb)(void *, int),
-		void (*inserted_cb)(void *, int)) {
-	sd->opaque = opaque;
-	sd->readonly_cb = readonly_cb;
-	sd->inserted_cb = inserted_cb;
-	if (sd->readonly_cb)
-		sd->readonly_cb(sd->opaque, bdrv_is_read_only(sd->bdrv));
-	if (sd->inserted_cb)
-		sd->inserted_cb(sd->opaque, bdrv_is_inserted(sd->bdrv));
-	bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
+void sd_set_cb(SDState *sd, void *opaque,
+                void (*readonly_cb)(void *, int),
+                void (*inserted_cb)(void *, int))
+{
+    sd->opaque = opaque;
+    sd->readonly_cb = readonly_cb;
+    sd->inserted_cb = inserted_cb;
+    if (sd->readonly_cb)
+        sd->readonly_cb(sd->opaque, bdrv_is_read_only(sd->bdrv));
+    if (sd->inserted_cb)
+        sd->inserted_cb(sd->opaque, bdrv_is_inserted(sd->bdrv));
+    bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
 }
 
-static void sd_erase(struct sd_state_s *sd) {
-	int i, start, end;
-	if (!sd->erase_start || !sd->erase_end) {
-		sd->card_status |= ERASE_SEQ_ERROR;
-		return;
-	}
+static void sd_erase(SDState *sd)
+{
+    int i, start, end;
+    if (!sd->erase_start || !sd->erase_end) {
+        sd->card_status |= ERASE_SEQ_ERROR;
+        return;
+    }
 
-	start = sd->erase_start >>
-		(HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
-	end = sd->erase_end >>
-		(HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
-	sd->erase_start = 0;
-	sd->erase_end = 0;
-	sd->csd[14] |= 0x40;
+    start = sd->erase_start >>
+            (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
+    end = sd->erase_end >>
+            (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
+    sd->erase_start = 0;
+    sd->erase_end = 0;
+    sd->csd[14] |= 0x40;
 
-	for (i = start; i <= end; i ++)
-		if (sd->wp_groups[i])
-			sd->card_status |= WP_ERASE_SKIP;
+    for (i = start; i <= end; i ++)
+        if (sd->wp_groups[i])
+            sd->card_status |= WP_ERASE_SKIP;
 }
 
-static uint32_t sd_wpbits(struct sd_state_s *sd, uint32_t addr) {
-	uint32_t i, wpnum;
-	uint32_t ret = 0;
+static uint32_t sd_wpbits(SDState *sd, uint32_t addr)
+{
+    uint32_t i, wpnum;
+    uint32_t ret = 0;
 
-	wpnum = addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
+    wpnum = addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
 
-	for (i = 0; i < 32; i ++, wpnum ++, addr += WPGROUP_SIZE)
-		if (addr < sd->size && sd->wp_groups[wpnum])
-			ret |= (1 << i);
+    for (i = 0; i < 32; i ++, wpnum ++, addr += WPGROUP_SIZE)
+        if (addr < sd->size && sd->wp_groups[wpnum])
+            ret |= (1 << i);
 
-	return ret;
+    return ret;
 }
 
-static void sd_function_switch(struct sd_state_s *sd, uint32_t arg) {
-	int i, mode, new_func, crc;
-	mode = !!(arg & 0x80000000);
+static void sd_function_switch(SDState *sd, uint32_t arg)
+{
+    int i, mode, new_func, crc;
+    mode = !!(arg & 0x80000000);
 
-	sd->data[0] = 0x00;	/* Maximum current consumption */
-	sd->data[1] = 0x01;
-	sd->data[2] = 0x80;	/* Supported group 6 functions */
-	sd->data[3] = 0x01;
-	sd->data[4] = 0x80;	/* Supported group 5 functions */
-	sd->data[5] = 0x01;
-	sd->data[6] = 0x80;	/* Supported group 4 functions */
-	sd->data[7] = 0x01;
-	sd->data[8] = 0x80;	/* Supported group 3 functions */
-	sd->data[9] = 0x01;
-	sd->data[10] = 0x80;	/* Supported group 2 functions */
-	sd->data[11] = 0x43;
-	sd->data[12] = 0x80;	/* Supported group 1 functions */
-	sd->data[13] = 0x03;
-	for (i = 0; i < 6; i ++) {
-		new_func = (arg >> (i * 4)) & 0x0f;
-		if (mode && new_func != 0x0f)
-			sd->function_group[i] = new_func;
-		sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
-	}
-	memset(&sd->data[17], 0, 47);
-	crc = sd_crc16(sd->data, 64);
-	sd->data[65] = crc >> 8;
-	sd->data[66] = crc & 0xff;
+    sd->data[0] = 0x00;		/* Maximum current consumption */
+    sd->data[1] = 0x01;
+    sd->data[2] = 0x80;		/* Supported group 6 functions */
+    sd->data[3] = 0x01;
+    sd->data[4] = 0x80;		/* Supported group 5 functions */
+    sd->data[5] = 0x01;
+    sd->data[6] = 0x80;		/* Supported group 4 functions */
+    sd->data[7] = 0x01;
+    sd->data[8] = 0x80;		/* Supported group 3 functions */
+    sd->data[9] = 0x01;
+    sd->data[10] = 0x80;	/* Supported group 2 functions */
+    sd->data[11] = 0x43;
+    sd->data[12] = 0x80;	/* Supported group 1 functions */
+    sd->data[13] = 0x03;
+    for (i = 0; i < 6; i ++) {
+        new_func = (arg >> (i * 4)) & 0x0f;
+        if (mode && new_func != 0x0f)
+            sd->function_group[i] = new_func;
+        sd->data[14 + (i >> 1)] = new_func << ((i * 4) & 4);
+    }
+    memset(&sd->data[17], 0, 47);
+    crc = sd_crc16(sd->data, 64);
+    sd->data[65] = crc >> 8;
+    sd->data[66] = crc & 0xff;
 }
 
-static inline int sd_wp_addr(struct sd_state_s *sd, uint32_t addr) {
-	return sd->wp_groups[addr >>
-		(HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)];
+static inline int sd_wp_addr(SDState *sd, uint32_t addr)
+{
+    return sd->wp_groups[addr >>
+            (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)];
 }
 
-static void sd_lock_command(struct sd_state_s *sd) {
-	int erase, lock, clr_pwd, set_pwd, pwd_len;
-	erase = !!(sd->data[0] & 0x08);
-	lock = sd->data[0] & 0x04;
-	clr_pwd = sd->data[0] & 0x02;
-	set_pwd = sd->data[0] & 0x01;
+static void sd_lock_command(SDState *sd)
+{
+    int erase, lock, clr_pwd, set_pwd, pwd_len;
+    erase = !!(sd->data[0] & 0x08);
+    lock = sd->data[0] & 0x04;
+    clr_pwd = sd->data[0] & 0x02;
+    set_pwd = sd->data[0] & 0x01;
 
-	if (sd->blk_len > 1)
-		pwd_len = sd->data[1];
-	else
-		pwd_len = 0;
+    if (sd->blk_len > 1)
+        pwd_len = sd->data[1];
+    else
+        pwd_len = 0;
 
-	if (erase) {
-		if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
-				set_pwd || clr_pwd || lock || sd->wp_switch ||
-				(sd->csd[14] & 0x20)) {
-			sd->card_status |= LOCK_UNLOCK_FAILED;
-			return;
-		}
-		memset(sd->wp_groups, 0, sizeof(int) * (sd->size >>
-			(HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)));
-		sd->csd[14] &= ~0x10;
-		sd->card_status &= ~CARD_IS_LOCKED;
-		sd->pwd_len = 0;
-		/* Erasing the entire card here! */
-		printf("SD: Card force-erased by CMD42\n");
-		return;
-	}
+    if (erase) {
+        if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
+                        set_pwd || clr_pwd || lock || sd->wp_switch ||
+                        (sd->csd[14] & 0x20)) {
+            sd->card_status |= LOCK_UNLOCK_FAILED;
+            return;
+        }
+        memset(sd->wp_groups, 0, sizeof(int) * (sd->size >>
+                        (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)));
+        sd->csd[14] &= ~0x10;
+        sd->card_status &= ~CARD_IS_LOCKED;
+        sd->pwd_len = 0;
+        /* Erasing the entire card here! */
+        printf("SD: Card force-erased by CMD42\n");
+        return;
+    }
 
-	if (sd->blk_len < 2 + pwd_len ||
-			pwd_len <= sd->pwd_len ||
-			pwd_len > sd->pwd_len + 16) {
-		sd->card_status |= LOCK_UNLOCK_FAILED;
-		return;
-	}
+    if (sd->blk_len < 2 + pwd_len ||
+                    pwd_len <= sd->pwd_len ||
+                    pwd_len > sd->pwd_len + 16) {
+        sd->card_status |= LOCK_UNLOCK_FAILED;
+        return;
+    }
 
-	if (sd->pwd_len && memcmp(sd->pwd, sd->data + 2, sd->pwd_len)) {
-		sd->card_status |= LOCK_UNLOCK_FAILED;
-		return;
-	}
+    if (sd->pwd_len && memcmp(sd->pwd, sd->data + 2, sd->pwd_len)) {
+        sd->card_status |= LOCK_UNLOCK_FAILED;
+        return;
+    }
 
-	pwd_len -= sd->pwd_len;
-	if ((pwd_len && !set_pwd) ||
-			(clr_pwd && (set_pwd || lock)) ||
-			(lock && !sd->pwd_len && !set_pwd) ||
-			(!set_pwd && !clr_pwd &&
-			 (((sd->card_status & CARD_IS_LOCKED) && lock) ||
-			  (!(sd->card_status & CARD_IS_LOCKED) && !lock)))) {
-		sd->card_status |= LOCK_UNLOCK_FAILED;
-		return;
-	}
+    pwd_len -= sd->pwd_len;
+    if ((pwd_len && !set_pwd) ||
+                    (clr_pwd && (set_pwd || lock)) ||
+                    (lock && !sd->pwd_len && !set_pwd) ||
+                    (!set_pwd && !clr_pwd &&
+                     (((sd->card_status & CARD_IS_LOCKED) && lock) ||
+                      (!(sd->card_status & CARD_IS_LOCKED) && !lock)))) {
+        sd->card_status |= LOCK_UNLOCK_FAILED;
+        return;
+    }
 
-	if (set_pwd) {
-		memcpy(sd->pwd, sd->data + 2 + sd->pwd_len, pwd_len);
-		sd->pwd_len = pwd_len;
-	}
+    if (set_pwd) {
+        memcpy(sd->pwd, sd->data + 2 + sd->pwd_len, pwd_len);
+        sd->pwd_len = pwd_len;
+    }
 
-	if (clr_pwd) {
-		sd->pwd_len = 0;
-	}
+    if (clr_pwd) {
+        sd->pwd_len = 0;
+    }
 
-	if (lock)
-		sd->card_status |= CARD_IS_LOCKED;
-	else
-		sd->card_status &= ~CARD_IS_LOCKED;
+    if (lock)
+        sd->card_status |= CARD_IS_LOCKED;
+    else
+        sd->card_status &= ~CARD_IS_LOCKED;
 }
 
-static union sd_response_u sd_normal_command(struct sd_state_s *sd,
-		struct sd_request_s req) {
-	uint32_t rca = 0x0000;
-	union sd_response_u response;
+static sd_rsp_type_t sd_normal_command(SDState *sd,
+                                       struct sd_request_s req)
+{
+    uint32_t rca = 0x0000;
 
-	if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
-		rca = req.arg >> 16;
+    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
+        rca = req.arg >> 16;
 
-	switch (req.cmd) {
-	/* Basic commands (Class 0 and Class 1) */
-	case 0:		/* CMD0:   GO_IDLE_STATE */
-		switch (sd->state) {
-		case sd_inactive_state:
-			return response;
+    DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
+    switch (req.cmd) {
+    /* Basic commands (Class 0 and Class 1) */
+    case 0:	/* CMD0:   GO_IDLE_STATE */
+        switch (sd->state) {
+        case sd_inactive_state:
+            return sd_r0;
 
-		default:
-			sd->state = sd_idle_state;
-			sd_reset(sd, sd->bdrv);
-			return response;
-		}
-		break;
+        default:
+            sd->state = sd_idle_state;
+            sd_reset(sd, sd->bdrv);
+            return sd_r0;
+        }
+        break;
 
-	case 2:		/* CMD2:   ALL_SEND_CID */
-		switch (sd->state) {
-		case sd_ready_state:
-			sd->state = sd_identification_state;
-			memcpy(response.r2.reg, sd->cid, 16);
-			return response;
+    case 2:	/* CMD2:   ALL_SEND_CID */
+        switch (sd->state) {
+        case sd_ready_state:
+            sd->state = sd_identification_state;
+            return sd_r2_i;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 3:		/* CMD3:   SEND_RELATIVE_ADDR */
-		switch (sd->state) {
-		case sd_identification_state:
-		case sd_standby_state:
-			sd->state = sd_standby_state;
-			sd_set_rca(sd);
-			return response;
+    case 3:	/* CMD3:   SEND_RELATIVE_ADDR */
+        switch (sd->state) {
+        case sd_identification_state:
+        case sd_standby_state:
+            sd->state = sd_standby_state;
+            sd_set_rca(sd);
+            return sd_r6;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 4:		/* CMD4:   SEND_DSR */
-		switch (sd->state) {
-		case sd_standby_state:
-			break;
+    case 4:	/* CMD4:   SEND_DSR */
+        switch (sd->state) {
+        case sd_standby_state:
+            break;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 6:		/* CMD6:   SWITCH_FUNCTION */
-		switch (sd->mode) {
-		case sd_data_transfer_mode:
-			sd_function_switch(sd, req.arg);
-			sd->state = sd_sendingdata_state;
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    case 6:	/* CMD6:   SWITCH_FUNCTION */
+        switch (sd->mode) {
+        case sd_data_transfer_mode:
+            sd_function_switch(sd, req.arg);
+            sd->state = sd_sendingdata_state;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 7:		/* CMD7:   SELECT/DESELECT_CARD */
-		switch (sd->state) {
-		case sd_standby_state:
-			if (sd->rca != rca)
-				return response;
+    case 7:	/* CMD7:   SELECT/DESELECT_CARD */
+        switch (sd->state) {
+        case sd_standby_state:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			sd->state = sd_transfer_state;
-			return response;
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		case sd_transfer_state:
-		case sd_sendingdata_state:
-			if (sd->rca == rca)
-				break;
+        case sd_transfer_state:
+        case sd_sendingdata_state:
+            if (sd->rca == rca)
+                break;
 
-			sd->state = sd_standby_state;
-			return response;
+            sd->state = sd_standby_state;
+            return sd_r1b;
 
-		case sd_disconnect_state:
-			if (sd->rca != rca)
-				return response;
+        case sd_disconnect_state:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			sd->state = sd_programming_state;
-			return response;
+            sd->state = sd_programming_state;
+            return sd_r1b;
 
-		case sd_programming_state:
-			if (sd->rca == rca)
-				break;
+        case sd_programming_state:
+            if (sd->rca == rca)
+                break;
 
-			sd->state = sd_disconnect_state;
-			return response;
+            sd->state = sd_disconnect_state;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 9:		/* CMD9:   SEND_CSD */
-		switch (sd->state) {
-		case sd_standby_state:
-			if (sd->rca != rca)
-				return response;
+    case 9:	/* CMD9:   SEND_CSD */
+        switch (sd->state) {
+        case sd_standby_state:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			memcpy(response.r2.reg, sd->csd, sizeof(sd->csd));
-			return response;
+            return sd_r2_s;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 10:	/* CMD10:  SEND_CID */
-		switch (sd->state) {
-		case sd_standby_state:
-			if (sd->rca != rca)
-				return response;
+    case 10:	/* CMD10:  SEND_CID */
+        switch (sd->state) {
+        case sd_standby_state:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			memcpy(response.r2.reg, sd->cid, sizeof(sd->cid));
-			return response;
+            return sd_r2_i;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_sendingdata_state;
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
+    case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
 
-			if (sd->data_start + sd->blk_len > sd->size)
-				sd->card_status |= ADDRESS_ERROR;
-			return response;
+            if (sd->data_start + sd->blk_len > sd->size)
+                sd->card_status |= ADDRESS_ERROR;
+            return sd_r0;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 12:	/* CMD12:  STOP_TRANSMISSION */
-		switch (sd->state) {
-		case sd_sendingdata_state:
-			sd->state = sd_transfer_state;
-			return response;
+    case 12:	/* CMD12:  STOP_TRANSMISSION */
+        switch (sd->state) {
+        case sd_sendingdata_state:
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		case sd_receivingdata_state:
-			sd->state = sd_programming_state;
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-			return response;
+        case sd_receivingdata_state:
+            sd->state = sd_programming_state;
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 13:	/* CMD13:  SEND_STATUS */
-		switch (sd->mode) {
-		case sd_data_transfer_mode:
-			if (sd->rca != rca)
-				return response;
+    case 13:	/* CMD13:  SEND_STATUS */
+        switch (sd->mode) {
+        case sd_data_transfer_mode:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			return response;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 15:	/* CMD15:  GO_INACTIVE_STATE */
-		switch (sd->mode) {
-		case sd_data_transfer_mode:
-			if (sd->rca != rca)
-				return response;
+    case 15:	/* CMD15:  GO_INACTIVE_STATE */
+        switch (sd->mode) {
+        case sd_data_transfer_mode:
+            if (sd->rca != rca)
+                return sd_r0;
 
-			sd->state = sd_inactive_state;
-			return response;
+            sd->state = sd_inactive_state;
+            return sd_r0;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Block read commands (Classs 2) */
-	case 16:	/* CMD16:  SET_BLOCKLEN */
-		switch (sd->state) {
-		case sd_transfer_state:
-			if (req.arg > (1 << HWBLOCK_SHIFT))
-				sd->card_status |= BLOCK_LEN_ERROR;
-			else
-				sd->blk_len = req.arg;
+    /* Block read commands (Classs 2) */
+    case 16:	/* CMD16:  SET_BLOCKLEN */
+        switch (sd->state) {
+        case sd_transfer_state:
+            if (req.arg > (1 << HWBLOCK_SHIFT))
+                sd->card_status |= BLOCK_LEN_ERROR;
+            else
+                sd->blk_len = req.arg;
 
-			return response;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 17:	/* CMD17:  READ_SINGLE_BLOCK */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_sendingdata_state;
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
+    case 17:	/* CMD17:  READ_SINGLE_BLOCK */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
 
-			if (sd->data_start + sd->blk_len > sd->size)
-				sd->card_status |= ADDRESS_ERROR;
-			return response;
+            if (sd->data_start + sd->blk_len > sd->size)
+                sd->card_status |= ADDRESS_ERROR;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_sendingdata_state;
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
+    case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
 
-			if (sd->data_start + sd->blk_len > sd->size)
-				sd->card_status |= ADDRESS_ERROR;
-			return response;
+            if (sd->data_start + sd->blk_len > sd->size)
+                sd->card_status |= ADDRESS_ERROR;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Block write commands (Class 4) */
-	case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_receivingdata_state;
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
-			sd->blk_written = 0;
+    /* Block write commands (Class 4) */
+    case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_receivingdata_state;
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
+            sd->blk_written = 0;
 
-			if (sd->data_start + sd->blk_len > sd->size)
-				sd->card_status |= ADDRESS_ERROR;
-			if (sd_wp_addr(sd, sd->data_start))
-				sd->card_status |= WP_VIOLATION;
-			if (sd->csd[14] & 0x30)
-				sd->card_status |= WP_VIOLATION;
-			return response;
+            if (sd->data_start + sd->blk_len > sd->size)
+                sd->card_status |= ADDRESS_ERROR;
+            if (sd_wp_addr(sd, sd->data_start))
+                sd->card_status |= WP_VIOLATION;
+            if (sd->csd[14] & 0x30)
+                sd->card_status |= WP_VIOLATION;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_receivingdata_state;
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
-			sd->blk_written = 0;
+    case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_receivingdata_state;
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
+            sd->blk_written = 0;
 
-			if (sd->data_start + sd->blk_len > sd->size)
-				sd->card_status |= ADDRESS_ERROR;
-			if (sd_wp_addr(sd, sd->data_start))
-				sd->card_status |= WP_VIOLATION;
-			if (sd->csd[14] & 0x30)
-				sd->card_status |= WP_VIOLATION;
-			return response;
+            if (sd->data_start + sd->blk_len > sd->size)
+                sd->card_status |= ADDRESS_ERROR;
+            if (sd_wp_addr(sd, sd->data_start))
+                sd->card_status |= WP_VIOLATION;
+            if (sd->csd[14] & 0x30)
+                sd->card_status |= WP_VIOLATION;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 26:	/* CMD26:  PROGRAM_CID */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_receivingdata_state;
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    case 26:	/* CMD26:  PROGRAM_CID */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_receivingdata_state;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 27:	/* CMD27:  PROGRAM_CSD */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_receivingdata_state;
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    case 27:	/* CMD27:  PROGRAM_CSD */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_receivingdata_state;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Write protection (Class 6) */
-	case 28:	/* CMD28:  SET_WRITE_PROT */
-		switch (sd->state) {
-		case sd_transfer_state:
-			if (req.arg >= sd->size) {
-				sd->card_status = ADDRESS_ERROR;
-				return response;
-			}
+    /* Write protection (Class 6) */
+    case 28:	/* CMD28:  SET_WRITE_PROT */
+        switch (sd->state) {
+        case sd_transfer_state:
+            if (req.arg >= sd->size) {
+                sd->card_status = ADDRESS_ERROR;
+                return sd_r1b;
+            }
 
-			sd->state = sd_programming_state;
-			sd->wp_groups[req.arg >> (HWBLOCK_SHIFT +
-					SECTOR_SHIFT + WPGROUP_SHIFT)] = 1;
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-			return response;
+            sd->state = sd_programming_state;
+            sd->wp_groups[req.arg >> (HWBLOCK_SHIFT +
+                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 1;
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 29:	/* CMD29:  CLR_WRITE_PROT */
-		switch (sd->state) {
-		case sd_transfer_state:
-			if (req.arg >= sd->size) {
-				sd->card_status = ADDRESS_ERROR;
-				return response;
-			}
+    case 29:	/* CMD29:  CLR_WRITE_PROT */
+        switch (sd->state) {
+        case sd_transfer_state:
+            if (req.arg >= sd->size) {
+                sd->card_status = ADDRESS_ERROR;
+                return sd_r1b;
+            }
 
-			sd->state = sd_programming_state;
-			sd->wp_groups[req.arg >> (HWBLOCK_SHIFT +
-					SECTOR_SHIFT + WPGROUP_SHIFT)] = 0;
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-			return response;
+            sd->state = sd_programming_state;
+            sd->wp_groups[req.arg >> (HWBLOCK_SHIFT +
+                            SECTOR_SHIFT + WPGROUP_SHIFT)] = 0;
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 30:	/* CMD30:  SEND_WRITE_PROT */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_sendingdata_state;
-			*(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
-			sd->data_start = req.arg;
-			sd->data_offset = 0;
-			return response;
+    case 30:	/* CMD30:  SEND_WRITE_PROT */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
+            *(uint32_t *) sd->data = sd_wpbits(sd, req.arg);
+            sd->data_start = req.arg;
+            sd->data_offset = 0;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Erase commands (Class 5) */
-	case 32:	/* CMD32:  ERASE_WR_BLK_START */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->erase_start = req.arg;
-			return response;
+    /* Erase commands (Class 5) */
+    case 32:	/* CMD32:  ERASE_WR_BLK_START */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->erase_start = req.arg;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 33:	/* CMD33:  ERASE_WR_BLK_END */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->erase_end = req.arg;
-			return response;
+    case 33:	/* CMD33:  ERASE_WR_BLK_END */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->erase_end = req.arg;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 38:	/* CMD38:  ERASE */
-		switch (sd->state) {
-		case sd_transfer_state:
-			if (sd->csd[14] & 0x30) {
-				sd->card_status |= WP_VIOLATION;
-				return response;
-			}
+    case 38:	/* CMD38:  ERASE */
+        switch (sd->state) {
+        case sd_transfer_state:
+            if (sd->csd[14] & 0x30) {
+                sd->card_status |= WP_VIOLATION;
+                return sd_r1b;
+            }
 
-			sd->state = sd_programming_state;
-			sd_erase(sd);
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-			return response;
+            sd->state = sd_programming_state;
+            sd_erase(sd);
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+            return sd_r1b;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Lock card commands (Class 7) */
-	case 42:	/* CMD42:  LOCK_UNLOCK */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_receivingdata_state;
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    /* Lock card commands (Class 7) */
+    case 42:	/* CMD42:  LOCK_UNLOCK */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_receivingdata_state;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	/* Application specific commands (Class 8) */
-	case 55:	/* CMD55:  APP_CMD */
-		if (sd->rca != rca)
-			return response;
+    /* Application specific commands (Class 8) */
+    case 55:	/* CMD55:  APP_CMD */
+        if (sd->rca != rca)
+            return sd_r0;
 
-		sd->card_status |= APP_CMD;
-		return response;
+        sd->card_status |= APP_CMD;
+        return sd_r1;
 
-	case 56:	/* CMD56:  GEN_CMD */
-		printf("SD: GEN_CMD 0x%08x\n", req.arg);
+    case 56:	/* CMD56:  GEN_CMD */
+        printf("SD: GEN_CMD 0x%08x\n", req.arg);
 
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->data_offset = 0;
-			if (req.arg & 1)
-				sd->state = sd_sendingdata_state;
-			else
-				sd->state = sd_receivingdata_state;
-			return response;
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->data_offset = 0;
+            if (req.arg & 1)
+                sd->state = sd_sendingdata_state;
+            else
+                sd->state = sd_receivingdata_state;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	default:
-		sd->card_status |= ILLEGAL_COMMAND;
+    default:
+        sd->card_status |= ILLEGAL_COMMAND;
 
-		printf("SD: Unknown CMD%i\n", req.cmd);
-		return response;
-	}
+        printf("SD: Unknown CMD%i\n", req.cmd);
+        return sd_r0;
+    }
 
-	sd->card_status |= ILLEGAL_COMMAND;
-	printf("SD: CMD%i in a wrong state\n", req.cmd);
-	return response;
+    sd->card_status |= ILLEGAL_COMMAND;
+    printf("SD: CMD%i in a wrong state\n", req.cmd);
+    return sd_r0;
 }
 
-static union sd_response_u sd_app_command(struct sd_state_s *sd,
-		struct sd_request_s req) {
-	uint32_t rca;
-	union sd_response_u response;
+static sd_rsp_type_t sd_app_command(SDState *sd,
+                                    struct sd_request_s req) {
+    uint32_t rca;
 
-	if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
-		rca = req.arg >> 16;
+    if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
+        rca = req.arg >> 16;
 
-	switch (req.cmd) {
-	case 6:		/* ACMD6:  SET_BUS_WIDTH */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->sd_status[0] &= 0x3f;
-			sd->sd_status[0] |= (req.arg & 0x03) << 6;
-			return response;
+    DPRINTF("ACMD%d 0x%08x\n", req.cmd, req.arg);
+    switch (req.cmd) {
+    case 6:	/* ACMD6:  SET_BUS_WIDTH */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->sd_status[0] &= 0x3f;
+            sd->sd_status[0] |= (req.arg & 0x03) << 6;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 13:	/* ACMD13: SD_STATUS */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    case 13:	/* ACMD13: SD_STATUS */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */
-		switch (sd->state) {
-		case sd_transfer_state:
-			*(uint32_t *) sd->data = sd->blk_written;
+    case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */
+        switch (sd->state) {
+        case sd_transfer_state:
+            *(uint32_t *) sd->data = sd->blk_written;
 
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 23:	/* ACMD23: SET_WR_BLK_ERASE_COUNT */
-		switch (sd->state) {
-		case sd_transfer_state:
-			return response;
+    case 23:	/* ACMD23: SET_WR_BLK_ERASE_COUNT */
+        switch (sd->state) {
+        case sd_transfer_state:
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 41:	/* ACMD41: SD_APP_OP_COND */
-		switch (sd->state) {
-		case sd_idle_state:
-			/* We accept any voltage.  10000 V is nothing.  */
-			if (req.arg)
-				sd->state = sd_ready_state;
+    case 41:	/* ACMD41: SD_APP_OP_COND */
+        switch (sd->state) {
+        case sd_idle_state:
+            /* We accept any voltage.  10000 V is nothing.  */
+            if (req.arg)
+                sd->state = sd_ready_state;
 
-			return response;
+            return sd_r3;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 42:	/* ACMD42: SET_CLR_CARD_DETECT */
-		switch (sd->state) {
-		case sd_transfer_state:
-			/* Bringing in the 50KOhm pull-up resistor... Done.  */
-			return response;
+    case 42:	/* ACMD42: SET_CLR_CARD_DETECT */
+        switch (sd->state) {
+        case sd_transfer_state:
+            /* Bringing in the 50KOhm pull-up resistor... Done.  */
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	case 51:	/* ACMD51: SEND_SCR */
-		switch (sd->state) {
-		case sd_transfer_state:
-			sd->state = sd_sendingdata_state;
-			sd->data_start = 0;
-			sd->data_offset = 0;
-			return response;
+    case 51:	/* ACMD51: SEND_SCR */
+        switch (sd->state) {
+        case sd_transfer_state:
+            sd->state = sd_sendingdata_state;
+            sd->data_start = 0;
+            sd->data_offset = 0;
+            return sd_r1;
 
-		default:
-			break;
-		}
-		break;
+        default:
+            break;
+        }
+        break;
 
-	default:
-		/* Fall back to standard commands.  */
-		sd->card_status &= ~APP_CMD;
-		return sd_normal_command(sd, req);
-	}
+    default:
+        /* Fall back to standard commands.  */
+        sd->card_status &= ~APP_CMD;
+        return sd_normal_command(sd, req);
+    }
 
-	printf("SD: ACMD%i in a wrong state\n", req.cmd);
-	return response;
+    printf("SD: ACMD%i in a wrong state\n", req.cmd);
+    return sd_r0;
 }
 
-union sd_response_u sd_write_cmdline(struct sd_state_s *sd,
-		struct sd_request_s req, int *rsplen) {
-	uint32_t last_status = sd->card_status;
-	union sd_response_u response;
-	sd_rsp_type_t rtype;
+int sd_do_command(SDState *sd, struct sd_request_s *req,
+                  uint8_t *response) {
+    uint32_t last_status = sd->card_status;
+    sd_rsp_type_t rtype;
+    int rsplen;
 
-	if (!bdrv_is_inserted(sd->bdrv)) {
-		*rsplen = 0;
-		return response;
-	}
+    if (!bdrv_is_inserted(sd->bdrv)) {
+        return 0;
+    }
 
-	if (sd_req_crc_validate(&req)) {
-		sd->card_status &= ~COM_CRC_ERROR;
-		*rsplen = 0;
-		return response;
-	}
+    if (sd_req_crc_validate(req)) {
+        sd->card_status &= ~COM_CRC_ERROR;
+        return 0;
+    }
 
-	sd->card_status &= ~CARD_STATUS_B;
-	sd_set_status(sd);
+    sd->card_status &= ~CARD_STATUS_B;
+    sd_set_status(sd);
 
-	if (last_status & CARD_IS_LOCKED)
-		if (((last_status & APP_CMD) &&
-				(sd_acmd_type[req.cmd] == 0 ||
-				 sd_acmd_type[req.cmd] == 7 ||
-				 req.cmd == 41)) ||
-				(!(last_status & APP_CMD) &&
-				 (sd_cmd_type[req.cmd] == 0 ||
-				  sd_cmd_type[req.cmd] == 7 ||
-				  req.cmd == 16 || req.cmd == 55))) {
-			sd->card_status |= ILLEGAL_COMMAND;
-			printf("SD: Card is locked\n");
-			return response;
-		}
+    if (last_status & CARD_IS_LOCKED)
+        if (((last_status & APP_CMD) &&
+                                 req->cmd == 41) ||
+                        (!(last_status & APP_CMD) &&
+                         (sd_cmd_class[req->cmd] == 0 ||
+                          sd_cmd_class[req->cmd] == 7 ||
+                          req->cmd == 16 || req->cmd == 55))) {
+            sd->card_status |= ILLEGAL_COMMAND;
+            printf("SD: Card is locked\n");
+            return 0;
+        }
 
-	if (last_status & APP_CMD)
-		response = sd_app_command(sd, req);
-	else
-		response = sd_normal_command(sd, req);
+    if (last_status & APP_CMD)
+        rtype = sd_app_command(sd, *req);
+    else
+        rtype = sd_normal_command(sd, *req);
 
-	if (last_status & APP_CMD) {
-		if (sd->card_status & APP_CMD) {
-			rtype = sd_acmd_response[req.cmd];
-			sd->card_status &= ~APP_CMD;
-		} else
-			rtype = sd_cmd_response[req.cmd];
-	} else
-		rtype = sd_cmd_response[req.cmd];
+    sd->current_cmd = req->cmd;
 
-	sd->current_cmd = req.cmd;
+    switch (rtype) {
+    case sd_r1:
+    case sd_r1b:
+        sd_response_r1_make(sd, response, last_status);
+        rsplen = 4;
+        break;
 
-	switch (rtype) {
-	case sd_r1:
-	case sd_r1b:
-		sd_response_r1_make(sd, &response, last_status);
-		*rsplen = 48;
-		break;
+    case sd_r2_i:
+        memcpy(response, sd->cid, sizeof(sd->cid));
+        response[7] |= 1;
+        rsplen = 16;
+        break;
 
-	case sd_r2:
-		sd_response_r2_make(sd, &response);
-		*rsplen = 128;
-		break;
+    case sd_r2_s:
+        memcpy(response, sd->csd, sizeof(sd->csd));
+        response[7] |= 1;
+        rsplen = 16;
+        break;
 
-	case sd_r3:
-		sd_response_r3_make(sd, &response);
-		*rsplen = 48;
-		break;
+    case sd_r3:
+        sd_response_r3_make(sd, response);
+        rsplen = 4;
+        break;
 
-	case sd_r6:
-		sd_response_r6_make(sd, &response);
-		*rsplen = 48;
-		break;
+    case sd_r6:
+        sd_response_r6_make(sd, response);
+        rsplen = 4;
+        break;
 
-	case sd_nore:
-	default:
-		*rsplen = 0;
-		break;
-	}
+    case sd_r0:
+    default:
+        rsplen = 0;
+        break;
+    }
 
-	if (sd->card_status & ILLEGAL_COMMAND)
-		*rsplen = 0;
+    if (sd->card_status & ILLEGAL_COMMAND)
+        rsplen = 0;
 
-	return response;
+#ifdef DEBUG_SD
+    if (rsplen) {
+        int i;
+        DPRINTF("Response:");
+        for (i = 0; i < rsplen; i++)
+            printf(" %02x", response[i]);
+        printf(" state %d\n", sd->state);
+    } else {
+        DPRINTF("No response %d\n", sd->state);
+    }
+#endif
+
+    return rsplen;
 }
 
 /* No real need for 64 bit addresses here */
 static void sd_blk_read(BlockDriverState *bdrv,
-		void *data, uint32_t addr, uint32_t len) {
-	uint8_t buf[512];
-	uint32_t end = addr + len;
+                void *data, uint32_t addr, uint32_t len)
+{
+    uint8_t buf[512];
+    uint32_t end = addr + len;
 
-	if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
-		printf("sd_blk_read: read error on host side\n");
-		return;
-	}
+    if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
+        printf("sd_blk_read: read error on host side\n");
+        return;
+    }
 
-	if (end > (addr & ~511) + 512) {
-		memcpy(data, buf + (addr & 511), 512 - (addr & 511));
+    if (end > (addr & ~511) + 512) {
+        memcpy(data, buf + (addr & 511), 512 - (addr & 511));
 
-		if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
-			printf("sd_blk_read: read error on host side\n");
-			return;
-		}
-		memcpy(data + 512 - (addr & 511), buf, end & 511);
-	} else
-		memcpy(data, buf + (addr & 511), len);
+        if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
+            printf("sd_blk_read: read error on host side\n");
+            return;
+        }
+        memcpy(data + 512 - (addr & 511), buf, end & 511);
+    } else
+        memcpy(data, buf + (addr & 511), len);
 }
 
 static void sd_blk_write(BlockDriverState *bdrv,
-		void *data, uint32_t addr, uint32_t len) {
-	uint8_t buf[512];
-	uint32_t end = addr + len;
+                void *data, uint32_t addr, uint32_t len)
+{
+    uint8_t buf[512];
+    uint32_t end = addr + len;
 
-	if ((addr & 511) || len < 512)
-		if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
-			printf("sd_blk_write: read error on host side\n");
-			return;
-		}
+    if ((addr & 511) || len < 512)
+        if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
+            printf("sd_blk_write: read error on host side\n");
+            return;
+        }
 
-	if (end > (addr & ~511) + 512) {
-		memcpy(buf + (addr & 511), data, 512 - (addr & 511));
-		if (bdrv_write(bdrv, addr >> 9, buf, 1) == -1) {
-			printf("sd_blk_write: write error on host side\n");
-			return;
-		}
+    if (end > (addr & ~511) + 512) {
+        memcpy(buf + (addr & 511), data, 512 - (addr & 511));
+        if (bdrv_write(bdrv, addr >> 9, buf, 1) == -1) {
+            printf("sd_blk_write: write error on host side\n");
+            return;
+        }
 
-		if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
-			printf("sd_blk_write: read error on host side\n");
-			return;
-		}
-		memcpy(buf, data + 512 - (addr & 511), end & 511);
-		if (bdrv_write(bdrv, end >> 9, buf, 1) == -1)
-			printf("sd_blk_write: write error on host side\n");
-	} else {
-		memcpy(buf + (addr & 511), data, len);
-		if (!bdrv || bdrv_write(bdrv, addr >> 9, buf, 1) == -1)
-			printf("sd_blk_write: write error on host side\n");
-	}
+        if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
+            printf("sd_blk_write: read error on host side\n");
+            return;
+        }
+        memcpy(buf, data + 512 - (addr & 511), end & 511);
+        if (bdrv_write(bdrv, end >> 9, buf, 1) == -1)
+            printf("sd_blk_write: write error on host side\n");
+    } else {
+        memcpy(buf + (addr & 511), data, len);
+        if (!bdrv || bdrv_write(bdrv, addr >> 9, buf, 1) == -1)
+            printf("sd_blk_write: write error on host side\n");
+    }
 }
 
 #define BLK_READ_BLOCK(a, len)	sd_blk_read(sd->bdrv, sd->data, a, len)
@@ -1267,229 +1273,236 @@
 #define APP_READ_BLOCK(a, len)	memset(sd->data, 0xec, len)
 #define APP_WRITE_BLOCK(a, len)
 
-void sd_write_datline(struct sd_state_s *sd, uint8_t value) {
-	int i;
+void sd_write_data(SDState *sd, uint8_t value)
+{
+    int i;
 
-	if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
-		return;
+    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
+        return;
 
-	if (sd->state != sd_receivingdata_state) {
-		printf("sd_write_datline: not in Receiving-Data state\n");
-		return;
-	}
+    if (sd->state != sd_receivingdata_state) {
+        printf("sd_write_data: not in Receiving-Data state\n");
+        return;
+    }
 
-	if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
-		return;
+    if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
+        return;
 
-	switch (sd->current_cmd) {
-	case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sd->blk_len) {
-			/* TODO: Check CRC before committing */
-			sd->state = sd_programming_state;
-			BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
-			sd->blk_written ++;
-			sd->csd[14] |= 0x40;
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-		}
-		break;
+    switch (sd->current_cmd) {
+    case 24:	/* CMD24:  WRITE_SINGLE_BLOCK */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->blk_written ++;
+            sd->csd[14] |= 0x40;
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+        }
+        break;
 
-	case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sd->blk_len) {
-			/* TODO: Check CRC before committing */
-			sd->state = sd_programming_state;
-			BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
-			sd->blk_written ++;
-			sd->data_start += sd->blk_len;
-			sd->data_offset = 0;
-			if (sd->data_start + sd->blk_len > sd->size) {
-				sd->card_status |= ADDRESS_ERROR;
-				break;
-			}
-			if (sd_wp_addr(sd, sd->data_start)) {
-				sd->card_status |= WP_VIOLATION;
-				break;
-			}
-			sd->csd[14] |= 0x40;
+    case 25:	/* CMD25:  WRITE_MULTIPLE_BLOCK */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            BLK_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->blk_written ++;
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
+            if (sd->data_start + sd->blk_len > sd->size) {
+                sd->card_status |= ADDRESS_ERROR;
+                break;
+            }
+            if (sd_wp_addr(sd, sd->data_start)) {
+                sd->card_status |= WP_VIOLATION;
+                break;
+            }
+            sd->csd[14] |= 0x40;
 
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_receivingdata_state;
-		}
-		break;
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_receivingdata_state;
+        }
+        break;
 
-	case 26:	/* CMD26:  PROGRAM_CID */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sizeof(sd->cid)) {
-			/* TODO: Check CRC before committing */
-			sd->state = sd_programming_state;
-			for (i = 0; i < sizeof(sd->cid); i ++)
-				if ((sd->cid[i] | 0x00) != sd->data[i])
-					sd->card_status |= CID_CSD_OVERWRITE;
+    case 26:	/* CMD26:  PROGRAM_CID */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sizeof(sd->cid)) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            for (i = 0; i < sizeof(sd->cid); i ++)
+                if ((sd->cid[i] | 0x00) != sd->data[i])
+                    sd->card_status |= CID_CSD_OVERWRITE;
 
-			if (!(sd->card_status & CID_CSD_OVERWRITE))
-				for (i = 0; i < sizeof(sd->cid); i ++) {
-					sd->cid[i] |= 0x00;
-					sd->cid[i] &= sd->data[i];
-				}
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-		}
-		break;
+            if (!(sd->card_status & CID_CSD_OVERWRITE))
+                for (i = 0; i < sizeof(sd->cid); i ++) {
+                    sd->cid[i] |= 0x00;
+                    sd->cid[i] &= sd->data[i];
+                }
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+        }
+        break;
 
-	case 27:	/* CMD27:  PROGRAM_CSD */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sizeof(sd->csd)) {
-			/* TODO: Check CRC before committing */
-			sd->state = sd_programming_state;
-			for (i = 0; i < sizeof(sd->csd); i ++)
-				if ((sd->csd[i] | sd_csd_rw_mask[i]) !=
-					(sd->data[i] | sd_csd_rw_mask[i]))
-					sd->card_status |= CID_CSD_OVERWRITE;
+    case 27:	/* CMD27:  PROGRAM_CSD */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sizeof(sd->csd)) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            for (i = 0; i < sizeof(sd->csd); i ++)
+                if ((sd->csd[i] | sd_csd_rw_mask[i]) !=
+                    (sd->data[i] | sd_csd_rw_mask[i]))
+                    sd->card_status |= CID_CSD_OVERWRITE;
 
-			/* Copy flag (OTP) & Permanent write protect */
-			if (sd->csd[14] & ~sd->data[14] & 0x60)
-				sd->card_status |= CID_CSD_OVERWRITE;
+            /* Copy flag (OTP) & Permanent write protect */
+            if (sd->csd[14] & ~sd->data[14] & 0x60)
+                sd->card_status |= CID_CSD_OVERWRITE;
 
-			if (!(sd->card_status & CID_CSD_OVERWRITE))
-				for (i = 0; i < sizeof(sd->csd); i ++) {
-					sd->csd[i] |= sd_csd_rw_mask[i];
-					sd->csd[i] &= sd->data[i];
-				}
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-		}
-		break;
+            if (!(sd->card_status & CID_CSD_OVERWRITE))
+                for (i = 0; i < sizeof(sd->csd); i ++) {
+                    sd->csd[i] |= sd_csd_rw_mask[i];
+                    sd->csd[i] &= sd->data[i];
+                }
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+        }
+        break;
 
-	case 42:	/* CMD42:  LOCK_UNLOCK */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sd->blk_len) {
-			/* TODO: Check CRC before committing */
-			sd->state = sd_programming_state;
-			sd_lock_command(sd);
-			/* Bzzzzzzztt .... Operation complete.  */
-			sd->state = sd_transfer_state;
-		}
-		break;
+    case 42:	/* CMD42:  LOCK_UNLOCK */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            /* TODO: Check CRC before committing */
+            sd->state = sd_programming_state;
+            sd_lock_command(sd);
+            /* Bzzzzzzztt .... Operation complete.  */
+            sd->state = sd_transfer_state;
+        }
+        break;
 
-	case 56:	/* CMD56:  GEN_CMD */
-		sd->data[sd->data_offset ++] = value;
-		if (sd->data_offset >= sd->blk_len) {
-			APP_WRITE_BLOCK(sd->data_start, sd->data_offset);
-			sd->state = sd_transfer_state;
-		}
-		break;
+    case 56:	/* CMD56:  GEN_CMD */
+        sd->data[sd->data_offset ++] = value;
+        if (sd->data_offset >= sd->blk_len) {
+            APP_WRITE_BLOCK(sd->data_start, sd->data_offset);
+            sd->state = sd_transfer_state;
+        }
+        break;
 
-	default:
-		printf("sd_write_datline: unknown command\n");
-		break;
-	}
+    default:
+        printf("sd_write_data: unknown command\n");
+        break;
+    }
 }
 
-uint8_t sd_read_datline(struct sd_state_s *sd) {
-	/* TODO: Append CRCs */
-	uint8_t ret;
+uint8_t sd_read_data(SDState *sd)
+{
+    /* TODO: Append CRCs */
+    uint8_t ret;
 
-	if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
-		return 0x00;
+    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv))
+        return 0x00;
 
-	if (sd->state != sd_sendingdata_state) {
-		printf("sd_read_datline: not in Sending-Data state\n");
-		return 0x00;
-	}
+    if (sd->state != sd_sendingdata_state) {
+        printf("sd_read_data: not in Sending-Data state\n");
+        return 0x00;
+    }
 
-	if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
-		return 0x00;
+    if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
+        return 0x00;
 
-	switch (sd->current_cmd) {
-	case 6:		/* CMD6:   SWITCH_FUNCTION */
-		ret = sd->data[sd->data_offset ++];
+    switch (sd->current_cmd) {
+    case 6:	/* CMD6:   SWITCH_FUNCTION */
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= 64)
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= 64)
+            sd->state = sd_transfer_state;
+        break;
 
-	case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
-		if (sd->data_offset == 0)
-			BLK_READ_BLOCK(sd->data_start, sd->blk_len);
-		ret = sd->data[sd->data_offset ++];
+    case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
+        if (sd->data_offset == 0)
+            BLK_READ_BLOCK(sd->data_start, sd->blk_len);
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= sd->blk_len) {
-			sd->data_start += sd->blk_len;
-			sd->data_offset = 0;
-			if (sd->data_start + sd->blk_len > sd->size) {
-				sd->card_status |= ADDRESS_ERROR;
-				break;
-			}
-		}
-		break;
+        if (sd->data_offset >= sd->blk_len) {
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
+            if (sd->data_start + sd->blk_len > sd->size) {
+                sd->card_status |= ADDRESS_ERROR;
+                break;
+            }
+        }
+        break;
 
-	case 13:	/* ACMD13: SD_STATUS */
-		ret = sd->sd_status[sd->data_offset ++];
+    case 13:	/* ACMD13: SD_STATUS */
+        ret = sd->sd_status[sd->data_offset ++];
 
-		if (sd->data_offset >= sizeof(sd->sd_status))
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= sizeof(sd->sd_status))
+            sd->state = sd_transfer_state;
+        break;
 
-	case 17:	/* CMD17:  READ_SINGLE_BLOCK */
-		if (sd->data_offset == 0)
-			BLK_READ_BLOCK(sd->data_start, sd->blk_len);
-		ret = sd->data[sd->data_offset ++];
+    case 17:	/* CMD17:  READ_SINGLE_BLOCK */
+        if (sd->data_offset == 0)
+            BLK_READ_BLOCK(sd->data_start, sd->blk_len);
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= sd->blk_len)
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= sd->blk_len)
+            sd->state = sd_transfer_state;
+        break;
 
-	case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
-		if (sd->data_offset == 0)
-			BLK_READ_BLOCK(sd->data_start, sd->blk_len);
-		ret = sd->data[sd->data_offset ++];
+    case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
+        if (sd->data_offset == 0)
+            BLK_READ_BLOCK(sd->data_start, sd->blk_len);
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= sd->blk_len) {
-			sd->data_start += sd->blk_len;
-			sd->data_offset = 0;
-			if (sd->data_start + sd->blk_len > sd->size) {
-				sd->card_status |= ADDRESS_ERROR;
-				break;
-			}
-		}
-		break;
+        if (sd->data_offset >= sd->blk_len) {
+            sd->data_start += sd->blk_len;
+            sd->data_offset = 0;
+            if (sd->data_start + sd->blk_len > sd->size) {
+                sd->card_status |= ADDRESS_ERROR;
+                break;
+            }
+        }
+        break;
 
-	case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */
-		ret = sd->data[sd->data_offset ++];
+    case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= 4)
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= 4)
+            sd->state = sd_transfer_state;
+        break;
 
-	case 30:	/* CMD30:  SEND_WRITE_PROT */
-		ret = sd->data[sd->data_offset ++];
+    case 30:	/* CMD30:  SEND_WRITE_PROT */
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= 4)
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= 4)
+            sd->state = sd_transfer_state;
+        break;
 
-	case 51:	/* ACMD51: SEND_SCR */
-		ret = sd->scr[sd->data_offset ++];
+    case 51:	/* ACMD51: SEND_SCR */
+        ret = sd->scr[sd->data_offset ++];
 
-		if (sd->data_offset >= sizeof(sd->scr))
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= sizeof(sd->scr))
+            sd->state = sd_transfer_state;
+        break;
 
-	case 56:	/* CMD56:  GEN_CMD */
-		if (sd->data_offset == 0)
-			APP_READ_BLOCK(sd->data_start, sd->blk_len);
-		ret = sd->data[sd->data_offset ++];
+    case 56:	/* CMD56:  GEN_CMD */
+        if (sd->data_offset == 0)
+            APP_READ_BLOCK(sd->data_start, sd->blk_len);
+        ret = sd->data[sd->data_offset ++];
 
-		if (sd->data_offset >= sd->blk_len)
-			sd->state = sd_transfer_state;
-		break;
+        if (sd->data_offset >= sd->blk_len)
+            sd->state = sd_transfer_state;
+        break;
 
-	default:
-		printf("sd_read_datline: unknown command\n");
-		return 0x00;
-	}
+    default:
+        printf("sd_read_data: unknown command\n");
+        return 0x00;
+    }
 
-	return ret;
+    return ret;
 }
+
+int sd_data_ready(SDState *sd)
+{
+    return sd->state == sd_sendingdata_state;
+}

Modified: trunk/src/host/qemu-neo1973/hw/sd.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sd.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sd.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,76 +54,29 @@
 #define AKE_SEQ_ERROR		(1 << 3)
 
 typedef enum {
-	sd_none = -1,
-	sd_bc = 0,	/* broadcast -- no response */
-	sd_bcr,		/* broadcast with response */
-	sd_ac,		/* addressed -- no data transfer */
-	sd_adtc,	/* addressed with data transfer */
+    sd_none = -1,
+    sd_bc = 0,	/* broadcast -- no response */
+    sd_bcr,		/* broadcast with response */
+    sd_ac,		/* addressed -- no data transfer */
+    sd_adtc,	/* addressed with data transfer */
 } sd_cmd_type_t;
 
-typedef enum {
-	sd_nore = 0,	/* no response */
-	sd_r1,		/* normal response command */
-	sd_r2,		/* CID, CSD registers */
-	sd_r3,		/* OCR register */
-	sd_r6 = 6,	/* Published RCA response */
-	sd_r1b = -1,
-} sd_rsp_type_t;
-
 struct sd_request_s {
-	uint8_t cmd;
-	uint32_t arg;
-	uint8_t crc;
+    uint8_t cmd;
+    uint32_t arg;
+    uint8_t crc;
 };
 
-struct sd_response_none_s {
-};
+typedef struct SDState SDState;
 
-struct sd_response_r1_s {
-	uint8_t cmd;
-	uint32_t status;
-	uint8_t crc;
-};
+SDState *sd_init(BlockDriverState *bs);
+int sd_do_command(SDState *sd, struct sd_request_s *req,
+                  uint8_t *response);
+void sd_write_data(SDState *sd, uint8_t value);
+uint8_t sd_read_data(SDState *sd);
+void sd_set_cb(SDState *sd, void *opaque,
+               void (*readonly_cb)(void *, int),
+               void (*inserted_cb)(void *, int));
+int sd_data_ready(SDState *sd);
 
-struct sd_response_r1b_s {
-	uint8_t cmd;
-	uint32_t status;
-	uint8_t crc;
-};
-
-struct sd_response_r2_s {
-	uint16_t reg[8];
-};
-
-struct sd_response_r3_s {
-	uint32_t ocr_reg;
-};
-
-struct sd_response_r6_s {
-	uint8_t cmd;
-	uint16_t arg;
-	uint16_t status;
-	uint8_t crc;
-};
-
-union sd_response_u {
-	struct sd_response_none_s none;
-	struct sd_response_r1_s r1;
-	struct sd_response_r1b_s r1b;
-	struct sd_response_r2_s r2;
-	struct sd_response_r3_s r3;
-	struct sd_response_r6_s r6;
-};
-
-struct sd_state_s;
-
-struct sd_state_s *sd_init(void);
-union sd_response_u sd_write_cmdline(struct sd_state_s *sd,
-		struct sd_request_s req, int *rsplen);
-void sd_write_datline(struct sd_state_s *sd, uint8_t value);
-uint8_t sd_read_datline(struct sd_state_s *sd);
-void sd_set_cb(struct sd_state_s *sd, void *opaque,
-		void (*readonly_cb)(void *, int),
-		void (*inserted_cb)(void *, int));
-
 #endif	/* __hw_sd_h */

Modified: trunk/src/host/qemu-neo1973/hw/serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/serial.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/serial.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -83,9 +83,7 @@
     /* NOTE: this hidden state is necessary for tx irq generation as
        it can be reset while reading iir */
     int thr_ipending;
-    SetIRQFunc *set_irq;
-    void *irq_opaque;
-    int irq;
+    qemu_irq irq;
     CharDriverState *chr;
     int last_break_enable;
     target_ulong base;
@@ -102,9 +100,9 @@
         s->iir = UART_IIR_NO_INT;
     }
     if (s->iir != UART_IIR_NO_INT) {
-        s->set_irq(s->irq_opaque, s->irq, 1);
+        qemu_irq_raise(s->irq);
     } else {
-        s->set_irq(s->irq_opaque, s->irq, 0);
+        qemu_irq_lower(s->irq);
     }
 }
 
@@ -345,16 +343,13 @@
 }
 
 /* If fd is zero, it means that the serial device uses the console */
-SerialState *serial_init(SetIRQFunc *set_irq, void *opaque,
-                         int base, int irq, CharDriverState *chr)
+SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr)
 {
     SerialState *s;
 
     s = qemu_mallocz(sizeof(SerialState));
     if (!s)
         return NULL;
-    s->set_irq = set_irq;
-    s->irq_opaque = opaque;
     s->irq = irq;
     s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
     s->iir = UART_IIR_NO_INT;
@@ -365,51 +360,51 @@
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
     s->chr = chr;
-    qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
-    qemu_chr_add_event_handler(chr, serial_event);
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
     return s;
 }
 
 /* Memory mapped interface */
-static uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
+uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
 {
     SerialState *s = opaque;
 
     return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
 }
 
-static void serial_mm_writeb (void *opaque,
-                              target_phys_addr_t addr, uint32_t value)
+void serial_mm_writeb (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
 {
     SerialState *s = opaque;
 
     serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
 }
 
-static uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
+uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
 {
     SerialState *s = opaque;
 
     return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
 }
 
-static void serial_mm_writew (void *opaque,
-                              target_phys_addr_t addr, uint32_t value)
+void serial_mm_writew (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
 {
     SerialState *s = opaque;
 
     serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
 }
 
-static uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
+uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
 {
     SerialState *s = opaque;
 
     return serial_ioport_read(s, (addr - s->base) >> s->it_shift);
 }
 
-static void serial_mm_writel (void *opaque,
-                              target_phys_addr_t addr, uint32_t value)
+void serial_mm_writel (void *opaque,
+                       target_phys_addr_t addr, uint32_t value)
 {
     SerialState *s = opaque;
 
@@ -428,9 +423,9 @@
     &serial_mm_writel,
 };
 
-SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque,
-                             target_ulong base, int it_shift,
-                             int irq, CharDriverState *chr)
+SerialState *serial_mm_init (target_ulong base, int it_shift,
+                             qemu_irq irq, CharDriverState *chr,
+                             int ioregister)
 {
     SerialState *s;
     int s_io_memory;
@@ -438,8 +433,6 @@
     s = qemu_mallocz(sizeof(SerialState));
     if (!s)
         return NULL;
-    s->set_irq = set_irq;
-    s->irq_opaque = opaque;
     s->irq = irq;
     s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
     s->iir = UART_IIR_NO_INT;
@@ -449,11 +442,13 @@
 
     register_savevm("serial", base, 2, serial_save, serial_load, s);
 
-    s_io_memory = cpu_register_io_memory(0, serial_mm_read,
-                                         serial_mm_write, s);
-    cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
+    if (ioregister) {
+        s_io_memory = cpu_register_io_memory(0, serial_mm_read,
+                                             serial_mm_write, s);
+        cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
+    }
     s->chr = chr;
-    qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
-    qemu_chr_add_event_handler(chr, serial_event);
+    qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
+                          serial_event, s);
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/sh7750.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sh7750.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sh7750.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -299,9 +299,8 @@
     }
 
     s->serial1 = chr;
-    qemu_chr_add_read_handler(chr, serial1_can_receive,
-			      serial1_receive, s);
-    qemu_chr_add_event_handler(chr, serial1_event);
+    qemu_chr_add_handlers(chr, serial1_can_receive,
+			  serial1_receive, serial1_event, s);
 }
 
 /**********************************************************************
@@ -415,9 +414,8 @@
     }
 
     s->serial2 = chr;
-    qemu_chr_add_read_handler(chr, serial2_can_receive,
-			      serial2_receive, s);
-    qemu_chr_add_event_handler(chr, serial2_event);
+    qemu_chr_add_handlers(chr, serial2_can_receive,
+			  serial2_receive, serial1_event, s);
 }
 
 static void init_serial_ports(SH7750State * s)

Modified: trunk/src/host/qemu-neo1973/hw/shix.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/shix.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/shix.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -42,11 +42,6 @@
     /* XXXXX */
 }
 
-void pic_set_irq(int irq, int level)
-{
-    /* XXXXX */
-}
-
 void pic_info()
 {
     /* XXXXX */
@@ -70,7 +65,7 @@
 void shix_init(int ram_size, int vga_ram_size, int boot_device,
 	       DisplayState * ds, const char **fd_filename, int snapshot,
 	       const char *kernel_filename, const char *kernel_cmdline,
-	       const char *initrd_filename)
+	       const char *initrd_filename, const char *cpu_model)
 {
     int ret;
     CPUState *env;

Modified: trunk/src/host/qemu-neo1973/hw/slavio_intctl.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_intctl.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/slavio_intctl.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,6 +54,7 @@
     uint64_t irq_count[32];
 #endif
     CPUState *cpu_envs[MAX_CPUS];
+    const uint32_t *intbit_to_level;
 } SLAVIO_INTCTLState;
 
 #define INTCTL_MAXADDR 0xf
@@ -208,11 +209,6 @@
 #endif
 }
 
-static const uint32_t intbit_to_level[32] = {
-    2, 3, 5, 7, 9, 11, 0, 14,	3, 5, 7, 9, 11, 13, 12, 12,
-    6, 0, 4, 10, 8, 0, 11, 0,	0, 0, 0, 0, 15, 0, 15, 0,
-};
-
 static void slavio_check_interrupts(void *opaque)
 {
     CPUState *env;
@@ -225,8 +221,8 @@
     if (pending && !(s->intregm_disabled & 0x80000000)) {
 	for (i = 0; i < 32; i++) {
 	    if (pending & (1 << i)) {
-		if (max < intbit_to_level[i])
-		    max = intbit_to_level[i];
+		if (max < s->intbit_to_level[i])
+		    max = s->intbit_to_level[i];
 	    }
 	}
         env = s->cpu_envs[s->target_cpu];
@@ -281,18 +277,19 @@
  * "irq" here is the bit number in the system interrupt register to
  * separate serial and keyboard interrupts sharing a level.
  */
-void slavio_pic_set_irq(void *opaque, int irq, int level)
+void slavio_set_irq(void *opaque, int irq, int level)
 {
     SLAVIO_INTCTLState *s = opaque;
 
     DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
     if (irq < 32) {
 	uint32_t mask = 1 << irq;
-	uint32_t pil = intbit_to_level[irq];
+	uint32_t pil = s->intbit_to_level[irq];
 	if (pil > 0) {
 	    if (level) {
 		s->intregm_pending |= mask;
 		s->intreg_pending[s->target_cpu] |= 1 << pil;
+		slavio_check_interrupts(s);
 	    }
 	    else {
 		s->intregm_pending &= ~mask;
@@ -300,20 +297,19 @@
 	    }
 	}
     }
-    slavio_check_interrupts(s);
 }
 
-void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
+void pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
 {
     SLAVIO_INTCTLState *s = opaque;
 
     DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
     if (cpu == (unsigned int)-1) {
-        slavio_pic_set_irq(opaque, irq, level);
+        slavio_set_irq(opaque, irq, level);
         return;
     }
     if (irq < 32) {
-	uint32_t pil = intbit_to_level[irq];
+	uint32_t pil = s->intbit_to_level[irq];
     	if (pil > 0) {
 	    if (level) {
 		s->intreg_pending[cpu] |= 1 << pil;
@@ -375,7 +371,9 @@
     s->cpu_envs[cpu] = env;
 }
 
-void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
+void *slavio_intctl_init(uint32_t addr, uint32_t addrg,
+                         const uint32_t *intbit_to_level,
+                         qemu_irq **irq)
 {
     int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
     SLAVIO_INTCTLState *s;
@@ -384,6 +382,7 @@
     if (!s)
         return NULL;
 
+    s->intbit_to_level = intbit_to_level;
     for (i = 0; i < MAX_CPUS; i++) {
 	slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
 	cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
@@ -394,6 +393,7 @@
 
     register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
     qemu_register_reset(slavio_intctl_reset, s);
+    *irq = qemu_allocate_irqs(slavio_set_irq, s, 32);
     slavio_intctl_reset(s);
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/slavio_misc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_misc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/slavio_misc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -41,7 +41,7 @@
 #endif
 
 typedef struct MiscState {
-    int irq;
+    qemu_irq irq;
     uint8_t config;
     uint8_t aux1, aux2;
     uint8_t diag, mctrl, sysctrl;
@@ -54,9 +54,11 @@
     MiscState *s = opaque;
 
     if ((s->aux2 & 0x4) && (s->config & 0x8)) {
-        pic_set_irq(s->irq, 1);
+        MISC_DPRINTF("Raise IRQ\n");
+        qemu_irq_raise(s->irq);
     } else {
-        pic_set_irq(s->irq, 0);
+        MISC_DPRINTF("Lower IRQ\n");
+        qemu_irq_lower(s->irq);
     }
 }
 
@@ -180,8 +182,10 @@
 static void slavio_misc_save(QEMUFile *f, void *opaque)
 {
     MiscState *s = opaque;
+    int tmp;
 
-    qemu_put_be32s(f, &s->irq);
+    tmp = 0;
+    qemu_put_be32s(f, &tmp); /* ignored, was IRQ.  */
     qemu_put_8s(f, &s->config);
     qemu_put_8s(f, &s->aux1);
     qemu_put_8s(f, &s->aux2);
@@ -193,11 +197,12 @@
 static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
 {
     MiscState *s = opaque;
+    int tmp;
 
     if (version_id != 1)
         return -EINVAL;
 
-    qemu_get_be32s(f, &s->irq);
+    qemu_get_be32s(f, &tmp);
     qemu_get_8s(f, &s->config);
     qemu_get_8s(f, &s->aux1);
     qemu_get_8s(f, &s->aux2);
@@ -207,7 +212,7 @@
     return 0;
 }
 
-void *slavio_misc_init(uint32_t base, int irq)
+void *slavio_misc_init(uint32_t base, qemu_irq irq)
 {
     int slavio_misc_io_memory;
     MiscState *s;

Modified: trunk/src/host/qemu-neo1973/hw/slavio_serial.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_serial.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/slavio_serial.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -52,8 +52,6 @@
 #ifdef DEBUG_SERIAL
 #define SER_DPRINTF(fmt, args...) \
 do { printf("SER: " fmt , ##args); } while (0)
-#define pic_set_irq(irq, level) \
-do { printf("SER: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
 #else
 #define SER_DPRINTF(fmt, args...)
 #endif
@@ -88,7 +86,7 @@
 } SERIOQueue;
 
 typedef struct ChannelState {
-    int irq;
+    qemu_irq irq;
     int reg;
     int rxint, txint, rxint_under_svc, txint_under_svc;
     chn_id_t chn; // this channel, A (base+4) or B (base+0)
@@ -110,6 +108,13 @@
 static void serial_receive_byte(ChannelState *s, int ch);
 static inline void set_txint(ChannelState *s);
 
+static void clear_queue(void *opaque)
+{
+    ChannelState *s = opaque;
+    SERIOQueue *q = &s->queue;
+    q->rptr = q->wptr = q->count = 0;
+}
+
 static void put_queue(void *opaque, int b)
 {
     ChannelState *s = opaque;
@@ -139,7 +144,7 @@
             q->rptr = 0;
         q->count--;
     }
-    KBD_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
+    SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val);
     if (q->count > 0)
 	serial_receive_byte(s, 0);
     return val;
@@ -164,7 +169,8 @@
     irq = slavio_serial_update_irq_chn(s);
     irq |= slavio_serial_update_irq_chn(s->otherchn);
 
-    pic_set_irq(s->irq, irq);
+    SER_DPRINTF("IRQ = %d\n", irq);
+    qemu_set_irq(s->irq, irq);
 }
 
 static void slavio_serial_reset_chn(ChannelState *s)
@@ -187,6 +193,7 @@
     s->rx = s->tx = 0;
     s->rxint = s->txint = 0;
     s->rxint_under_svc = s->txint_under_svc = 0;
+    clear_queue(s);
 }
 
 static void slavio_serial_reset(void *opaque)
@@ -200,14 +207,21 @@
 {
     s->rxint = 0;
     s->rxint_under_svc = 0;
-    if (s->chn == chn_a)
+    if (s->chn == chn_a) {
+        if (s->wregs[9] & 0x10)
+            s->otherchn->rregs[2] = 0x60;
+        else
+            s->otherchn->rregs[2] = 0x06;
         s->rregs[3] &= ~0x20;
-    else
+    } else {
+        if (s->wregs[9] & 0x10)
+            s->rregs[2] = 0x60;
+        else
+            s->rregs[2] = 0x06;
         s->otherchn->rregs[3] &= ~4;
+    }
     if (s->txint)
         set_txint(s);
-    else
-        s->rregs[2] = 6;
     slavio_serial_update_irq(s);
 }
 
@@ -216,27 +230,44 @@
     s->rxint = 1;
     if (!s->txint_under_svc) {
         s->rxint_under_svc = 1;
-        if (s->chn == chn_a)
-            s->rregs[3] |= 0x20;
-        else
-            s->otherchn->rregs[3] |= 4;
-        s->rregs[2] = 4;
-        slavio_serial_update_irq(s);
+        if (s->chn == chn_a) {
+            if (s->wregs[9] & 0x10)
+                s->otherchn->rregs[2] = 0x30;
+            else
+                s->otherchn->rregs[2] = 0x0c;
+        } else {
+            if (s->wregs[9] & 0x10)
+                s->rregs[2] = 0x20;
+            else
+                s->rregs[2] = 0x04;
+        }
     }
+    if (s->chn == chn_a)
+        s->rregs[3] |= 0x20;
+    else
+        s->otherchn->rregs[3] |= 4;
+    slavio_serial_update_irq(s);
 }
 
 static inline void clr_txint(ChannelState *s)
 {
     s->txint = 0;
     s->txint_under_svc = 0;
-    if (s->chn == chn_a)
+    if (s->chn == chn_a) {
+        if (s->wregs[9] & 0x10)
+            s->otherchn->rregs[2] = 0x60;
+        else
+            s->otherchn->rregs[2] = 0x06;
         s->rregs[3] &= ~0x10;
-    else
+    } else {
+        if (s->wregs[9] & 0x10)
+            s->rregs[2] = 0x60;
+        else
+            s->rregs[2] = 0x06;
         s->otherchn->rregs[3] &= ~2;
+    }
     if (s->rxint)
         set_rxint(s);
-    else
-        s->rregs[2] = 6;
     slavio_serial_update_irq(s);
 }
 
@@ -245,13 +276,20 @@
     s->txint = 1;
     if (!s->rxint_under_svc) {
         s->txint_under_svc = 1;
-        if (s->chn == chn_a)
-            s->rregs[3] |= 0x10;
-        else
-            s->otherchn->rregs[3] |= 2;
-        s->rregs[2] = 0;
-        slavio_serial_update_irq(s);
+        if (s->chn == chn_a) {
+            if (s->wregs[9] & 0x10)
+                s->otherchn->rregs[2] = 0x10;
+            else
+                s->otherchn->rregs[2] = 0x08;
+        } else {
+            s->rregs[2] = 0;
+        }
     }
+    if (s->chn == chn_a)
+        s->rregs[3] |= 0x10;
+    else
+        s->otherchn->rregs[3] |= 2;
+    slavio_serial_update_irq(s);
 }
 
 static void slavio_serial_update_parameters(ChannelState *s)
@@ -492,7 +530,9 @@
 
 static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
 {
-    qemu_put_be32s(f, &s->irq);
+    int tmp;
+    tmp = 0;
+    qemu_put_be32s(f, &tmp); /* unused, was IRQ.  */
     qemu_put_be32s(f, &s->reg);
     qemu_put_be32s(f, &s->rxint);
     qemu_put_be32s(f, &s->txint);
@@ -514,10 +554,12 @@
 
 static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
 {
+    int tmp;
+
     if (version_id > 2)
         return -EINVAL;
 
-    qemu_get_be32s(f, &s->irq);
+    qemu_get_be32s(f, &tmp); /* unused */
     qemu_get_be32s(f, &s->reg);
     qemu_get_be32s(f, &s->rxint);
     qemu_get_be32s(f, &s->txint);
@@ -545,7 +587,8 @@
 
 }
 
-SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
+SerialState *slavio_serial_init(int base, qemu_irq irq, CharDriverState *chr1,
+                                CharDriverState *chr2)
 {
     int slavio_serial_io_memory, i;
     SerialState *s;
@@ -565,8 +608,8 @@
 	s->chn[i].chn = 1 - i;
 	s->chn[i].type = ser;
 	if (s->chn[i].chr) {
-	    qemu_chr_add_read_handler(s->chn[i].chr, serial_can_receive, serial_receive1, &s->chn[i]);
-	    qemu_chr_add_event_handler(s->chn[i].chr, serial_event);
+	    qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
+                                  serial_receive1, serial_event, &s->chn[i]);
 	}
     }
     s->chn[0].otherchn = &s->chn[1];
@@ -603,12 +646,15 @@
     KBD_DPRINTF("Command %d\n", val);
     switch (val) {
     case 1: // Reset, return type code
+        clear_queue(s);
 	put_queue(s, 0xff);
-	put_queue(s, 5); // Type 5
+	put_queue(s, 4); // Type 4
 	break;
     case 7: // Query layout
+    case 0xf:
+        clear_queue(s);
 	put_queue(s, 0xfe);
-	put_queue(s, 0x20); // XXX, layout?
+	put_queue(s, 19); // XXX, layout?
 	break;
     default:
 	break;
@@ -621,9 +667,6 @@
     ChannelState *s = opaque;
     int ch;
 
-    /* XXX: SDL sometimes generates nul events: we delete them */
-    if (dx == 0 && dy == 0 && dz == 0 && buttons_state == 0)
-        return;
     MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state);
 
     ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */
@@ -661,7 +704,7 @@
     put_queue(s, 0);
 }
 
-void slavio_serial_ms_kbd_init(int base, int irq)
+void slavio_serial_ms_kbd_init(int base, qemu_irq irq)
 {
     int slavio_serial_io_memory, i;
     SerialState *s;
@@ -684,6 +727,7 @@
 
     qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
     qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
+    register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save, slavio_serial_load, s);
     qemu_register_reset(slavio_serial_reset, s);
     slavio_serial_reset(s);
 }

Modified: trunk/src/host/qemu-neo1973/hw/slavio_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -57,6 +57,7 @@
     int reached, stopped;
     int mode; // 0 = processor, 1 = user, 2 = system
     unsigned int cpu;
+    void *intctl;
 } SLAVIO_TIMERState;
 
 #define TIMER_MAXADDR 0x1f
@@ -103,7 +104,7 @@
     DPRINTF("irq %d limit %d reached %d d %" PRId64 " count %d s->c %x diff %" PRId64 " stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
 
     if (s->mode != 1)
-	pic_set_irq_cpu(s->irq, out, s->cpu);
+	pic_set_irq_cpu(s->intctl, s->irq, out, s->cpu);
 }
 
 // timer callback
@@ -130,8 +131,7 @@
 	// part of counter (user mode)
 	if (s->mode != 1) {
 	    // clear irq
-	    pic_set_irq_cpu(s->irq, 0, s->cpu);
-	    s->count_load_time = qemu_get_clock(vm_clock);
+	    pic_set_irq_cpu(s->intctl, s->irq, 0, s->cpu);
 	    s->reached = 0;
 	    return s->limit;
 	}
@@ -266,7 +266,8 @@
     slavio_timer_get_out(s);
 }
 
-void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu)
+void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu,
+                       void *intctl)
 {
     int slavio_timer_io_memory;
     SLAVIO_TIMERState *s;
@@ -278,6 +279,7 @@
     s->mode = mode;
     s->cpu = cpu;
     s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
+    s->intctl = intctl;
 
     slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
 						    slavio_timer_mem_write, s);

Added: trunk/src/host/qemu-neo1973/hw/smbus.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/smbus.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/smbus.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,309 @@
+/* 
+ * QEMU SMBus device emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the LGPL.
+ */
+
+/* TODO: Implement PEC.  */
+
+#include "vl.h"
+
+#define DEBUG_SMBUS 1
+
+#ifdef DEBUG_SMBUS
+#define DPRINTF(fmt, args...) \
+do { printf("smbus(%02x): " fmt , dev->i2c.address, ##args); } while (0)
+#define BADF(fmt, args...) \
+do { fprintf(stderr, "smbus: error: " fmt , ##args); exit(1);} while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#define BADF(fmt, args...) \
+do { fprintf(stderr, "smbus: error: " fmt , ##args);} while (0)
+#endif
+
+enum {
+    SMBUS_IDLE,
+    SMBUS_WRITE_DATA,
+    SMBUS_RECV_BYTE,
+    SMBUS_READ_DATA,
+    SMBUS_DONE,
+    SMBUS_CONFUSED = -1
+};
+
+static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
+{
+    DPRINTF("Quick Command %d\n", recv);
+    if (dev->quick_cmd)
+        dev->quick_cmd(dev, recv);
+}
+
+static void smbus_do_write(SMBusDevice *dev)
+{
+    uint8_t *p;
+    int len;
+
+    if (dev->data_len == 0) {
+        smbus_do_quick_cmd(dev, 0);
+    } else if (dev->data_len == 1) {
+        DPRINTF("Send Byte\n");
+        if (dev->send_byte) {
+            dev->send_byte(dev, dev->data_buf[0]);
+        }
+    } else {
+        dev->command = dev->data_buf[0];
+        DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
+        if (dev->write_data) {
+            dev->write_data(dev, dev->command, dev->data_buf + 1,
+                            dev->data_len - 1);
+        }
+    }
+}
+
+void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
+{
+    SMBusDevice *dev = (SMBusDevice *)s;
+    switch (event) {
+    case I2C_START_SEND:
+        switch (dev->mode) {
+        case SMBUS_IDLE:
+            DPRINTF("Incoming data\n");
+            dev->mode = SMBUS_WRITE_DATA;
+            break;
+        default:
+            BADF("Unexpected send start condition in state %d\n", dev->mode);
+            dev->mode = SMBUS_CONFUSED;
+            break;
+        }
+        break;
+
+    case I2C_START_RECV:
+        switch (dev->mode) {
+        case SMBUS_IDLE:
+            DPRINTF("Read mode\n");
+            dev->mode = SMBUS_RECV_BYTE;
+            break;
+        case SMBUS_WRITE_DATA:
+            if (dev->data_len == 0) {
+                BADF("Read after write with no data\n");
+                dev->mode = SMBUS_CONFUSED;
+            } else {
+                if (dev->data_len > 1) {
+                    smbus_do_write(dev);
+                } else {
+                    dev->command = dev->data_buf[0];
+                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
+                            dev->command);
+                }
+                DPRINTF("Read mode\n");
+                dev->data_len = 0;
+                dev->mode = SMBUS_READ_DATA;
+            }
+            break;
+        default:
+            BADF("Unexpected recv start condition in state %d\n", dev->mode);
+            dev->mode = SMBUS_CONFUSED;
+            break;
+        }
+        break;
+
+    case I2C_FINISH:
+        switch (dev->mode) {
+        case SMBUS_WRITE_DATA:
+            smbus_do_write(dev);
+            break;
+        case SMBUS_RECV_BYTE:
+            smbus_do_quick_cmd(dev, 1);
+            break;
+        case SMBUS_READ_DATA:
+            BADF("Unexpected stop during receive\n");
+            break;
+        default:
+            /* Nothing to do.  */
+            break;
+        }
+        dev->mode = SMBUS_IDLE;
+        dev->data_len = 0;
+        break;
+
+    case I2C_NACK:
+        switch (dev->mode) {
+        case SMBUS_DONE:
+            /* Nothing to do.  */
+            break;
+        case SMBUS_READ_DATA:
+            dev->mode = SMBUS_DONE;
+            break;
+        default:
+            BADF("Unexpected NACK in state %d\n", dev->mode);
+            dev->mode = SMBUS_CONFUSED;
+            break;
+        }
+    }
+}
+
+static int smbus_i2c_recv(i2c_slave *s)
+{
+    SMBusDevice *dev = (SMBusDevice *)s;
+    int ret;
+
+    switch (dev->mode) {
+    case SMBUS_RECV_BYTE:
+        if (dev->receive_byte) {
+            ret = dev->receive_byte(dev);
+        } else {
+            ret = 0;
+        }
+        DPRINTF("Receive Byte %02x\n", ret);
+        dev->mode = SMBUS_DONE;
+        break;
+    case SMBUS_READ_DATA:
+        if (dev->read_data) {
+            ret = dev->read_data(dev, dev->command, dev->data_len);
+            dev->data_len++;
+        } else {
+            ret = 0;
+        }
+        DPRINTF("Read data %02x\n", ret);
+        break;
+    default:
+        BADF("Unexpected read in state %d\n", dev->mode);
+        dev->mode = SMBUS_CONFUSED;
+        ret = 0;
+        break;
+    }
+    return ret;
+}
+
+static int smbus_i2c_send(i2c_slave *s, uint8_t data)
+{
+    SMBusDevice *dev = (SMBusDevice *)s;
+    switch (dev->mode) {
+    case SMBUS_WRITE_DATA:
+        DPRINTF("Write data %02x\n", data);
+        dev->data_buf[dev->data_len++] = data;
+        break;
+    default:
+        BADF("Unexpected write in state %d\n", dev->mode);
+        break;
+    }
+    return 0;
+}
+
+SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size)
+{
+    SMBusDevice *dev;
+
+    if (size < sizeof(SMBusDevice))
+        cpu_abort(cpu_single_env, "SMBus struct too small");
+
+    dev = (SMBusDevice *)i2c_slave_init(bus, address, size);
+    dev->i2c.event = smbus_i2c_event;
+    dev->i2c.recv = smbus_i2c_recv;
+    dev->i2c.send = smbus_i2c_send;
+
+    return dev;
+}
+
+/* Master device commands.  */
+void smbus_quick_command(i2c_bus *bus, int addr, int read)
+{
+    i2c_start_transfer(bus, addr, read);
+    i2c_end_transfer(bus);
+}
+
+uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
+{
+    uint8_t data;
+
+    i2c_start_transfer(bus, addr, 1);
+    data = i2c_recv(bus);
+    i2c_nack(bus);
+    i2c_end_transfer(bus);
+    return data;
+}
+
+void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data)
+{
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, data);
+    i2c_end_transfer(bus);
+}
+
+uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command)
+{
+    uint8_t data;
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_start_transfer(bus, addr, 1);
+    data = i2c_recv(bus);
+    i2c_nack(bus);
+    i2c_end_transfer(bus);
+    return data;
+}
+
+void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data)
+{
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_send(bus, data);
+    i2c_end_transfer(bus);
+}
+
+uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command)
+{
+    uint16_t data;
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_start_transfer(bus, addr, 1);
+    data = i2c_recv(bus);
+    data |= i2c_recv(bus) << 8;
+    i2c_nack(bus);
+    i2c_end_transfer(bus);
+    return data;
+}
+
+void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data)
+{
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_send(bus, data & 0xff);
+    i2c_send(bus, data >> 8);
+    i2c_end_transfer(bus);
+}
+
+int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data)
+{
+    int len;
+    int i;
+
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_start_transfer(bus, addr, 1);
+    len = i2c_recv(bus);
+    if (len > 32)
+        len = 0;
+    for (i = 0; i < len; i++)
+        data[i] = i2c_recv(bus);
+    i2c_nack(bus);
+    i2c_end_transfer(bus);
+    return len;
+}
+
+void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
+                       int len)
+{
+    int i;
+
+    if (len > 32)
+        len = 32;
+
+    i2c_start_transfer(bus, addr, 0);
+    i2c_send(bus, command);
+    i2c_send(bus, len);
+    for (i = 0; i < len; i++)
+        i2c_send(bus, data[i]);
+    i2c_end_transfer(bus);
+}

Added: trunk/src/host/qemu-neo1973/hw/smbus.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/smbus.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/smbus.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,70 @@
+/*
+ * QEMU SMBus API
+ * 
+ * Copyright (c) 2007 Arastra, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+typedef struct SMBusDevice SMBusDevice;
+
+struct SMBusDevice {
+    /* The SMBus protocol is implemented on top of I2C.  */
+    i2c_slave i2c;
+
+    /* Callbacks set by the device.  */
+    void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
+    void (*send_byte)(SMBusDevice *dev, uint8_t val);
+    uint8_t (*receive_byte)(SMBusDevice *dev);
+    /* We can't distinguish between a word write and a block write with
+       length 1, so pass the whole data block including the length byte
+       (if present).  The device is responsible figuring out what type of
+       command  this is.  */
+    void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len);
+    /* Likewise we can't distinguish between different reads, or even know
+       the length of the read until the read is complete, so read data a
+       byte at a time.  The device is responsible for adding the length
+       byte on block reads.  */
+    uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n);
+
+    /* Remaining fields for internal use only.  */
+    int mode;
+    int data_len;
+    uint8_t data_buf[34]; /* command + len + 32 bytes of data.  */
+    uint8_t command;
+};
+
+/* Create a slave device.  */
+SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size);
+
+/* Master device commands.  */
+void smbus_quick_command(i2c_bus *bus, int addr, int read);
+uint8_t smbus_receive_byte(i2c_bus *bus, int addr);
+void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data);
+uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command);
+void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data);
+uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command);
+void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data);
+int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data);
+void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
+                       int len);
+
+/* smbus_eeprom.c */
+void smbus_eeprom_device_init(i2c_bus *bus, uint8_t addr, uint8_t *buf);
+

Added: trunk/src/host/qemu-neo1973/hw/smbus_eeprom.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/smbus_eeprom.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/smbus_eeprom.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,108 @@
+/*
+ * QEMU SMBus EEPROM device
+ * 
+ * Copyright (c) 2007 Arastra, Inc.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+//#define DEBUG
+
+typedef struct SMBusEEPROMDevice {
+    SMBusDevice dev;
+    uint8_t *data;
+    uint8_t offset;
+} SMBusEEPROMDevice;
+
+static void eeprom_quick_cmd(SMBusDevice *dev, uint8_t read)
+{
+#ifdef DEBUG
+    printf("eeprom_quick_cmd: addr=0x%02x read=%d\n", dev->addr, read);
+#endif
+}
+
+static void eeprom_send_byte(SMBusDevice *dev, uint8_t val)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+#ifdef DEBUG
+    printf("eeprom_send_byte: addr=0x%02x val=0x%02x\n", dev->addr, val);
+#endif
+    eeprom->offset = val;
+}
+
+static uint8_t eeprom_receive_byte(SMBusDevice *dev)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+    uint8_t val = eeprom->data[eeprom->offset++];
+#ifdef DEBUG
+    printf("eeprom_receive_byte: addr=0x%02x val=0x%02x\n", dev->addr, val);
+#endif
+    return val;
+}
+
+static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+    int n;
+#ifdef DEBUG
+    printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr,
+           cmd, buf[0]);
+#endif
+    /* An page write operation is not a valid SMBus command.
+       It is a block write without a length byte.  Fortunately we
+       get the full block anyway.  */
+    /* TODO: Should this set the current location?  */
+    if (cmd + len > 256)
+        n = 256 - cmd;
+    else
+        n = len;
+    memcpy(eeprom->data + cmd, buf, n);
+    len -= n;
+    if (len)
+        memcpy(eeprom->data, buf + n, len);
+}
+
+static uint8_t eeprom_read_data(SMBusDevice *dev, uint8_t cmd, int n)
+{
+    SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
+    /* If this is the first byte then set the current position.  */
+    if (n == 0)
+        eeprom->offset = cmd;
+    /* As with writes, we implement block reads without the
+       SMBus length byte.  */
+    return eeprom_receive_byte(dev);
+}
+
+void smbus_eeprom_device_init(i2c_bus *bus, uint8_t addr, uint8_t *buf)
+{
+    SMBusEEPROMDevice *eeprom;
+    
+    eeprom = (SMBusEEPROMDevice *)smbus_device_init(bus, addr,
+        sizeof(SMBusEEPROMDevice));
+
+    eeprom->dev.quick_cmd = eeprom_quick_cmd;
+    eeprom->dev.send_byte = eeprom_send_byte;
+    eeprom->dev.receive_byte = eeprom_receive_byte;
+    eeprom->dev.write_data = eeprom_write_data;
+    eeprom->dev.read_data = eeprom_read_data;
+    eeprom->data = buf;
+    eeprom->offset = 0;
+}

Modified: trunk/src/host/qemu-neo1973/hw/smc91c111.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/smc91c111.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/smc91c111.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -24,8 +24,7 @@
     uint16_t gpr;
     uint16_t ptr;
     uint16_t ercv;
-    void *pic;
-    int irq;
+    qemu_irq irq;
     int bank;
     int packet_num;
     int tx_alloc;
@@ -86,7 +85,7 @@
     if (s->tx_fifo_done_len != 0)
         s->int_level |= INT_TX;
     level = (s->int_level & s->int_mask) != 0;
-    pic_set_irq_new(s->pic, s->irq, level);
+    qemu_set_irq(s->irq, level);
 }
 
 /* Try to allocate a packet.  Returns 0x80 on failure.  */
@@ -446,7 +445,9 @@
         case 7:
             /* Not implemented.  */
             return 0;
-        case 8: /* Free memory available.  */
+        case 8: /* Memory size.  */
+            return NUM_PACKETS;
+        case 9: /* Free memory available.  */
             {
                 int i;
                 int n;
@@ -457,8 +458,6 @@
                 }
                 return n;
             }
-        case 9: /* Memory size.  */
-            return NUM_PACKETS;
         case 10: case 11: /* RPCR */
             /* Not implemented.  */
             return 0;
@@ -693,7 +692,7 @@
     smc91c111_writel
 };
 
-void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)
+void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
 {
     smc91c111_state *s;
     int iomemtype;
@@ -703,7 +702,6 @@
                                        smc91c111_writefn, s);
     cpu_register_physical_memory(base, 16, iomemtype);
     s->base = base;
-    s->pic = pic;
     s->irq = irq;
     memcpy(s->macaddr, nd->macaddr, 6);
 

Modified: trunk/src/host/qemu-neo1973/hw/sparc32_dma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sparc32_dma.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sparc32_dma.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -37,9 +37,6 @@
 #ifdef DEBUG_DMA
 #define DPRINTF(fmt, args...) \
 do { printf("DMA: " fmt , ##args); } while (0)
-#define pic_set_irq_new(ctl, irq, level)                                \
-    do { printf("DMA: set_irq(%d): %d\n", (irq), (level));              \
-        pic_set_irq_new((ctl), (irq),(level));} while (0)
 #else
 #define DPRINTF(fmt, args...)
 #endif
@@ -58,17 +55,11 @@
 
 struct DMAState {
     uint32_t dmaregs[DMA_REGS];
-    int espirq, leirq;
-    void *iommu, *esp_opaque, *lance_opaque, *intctl;
+    qemu_irq espirq, leirq;
+    void *iommu, *esp_opaque, *lance_opaque;
+    qemu_irq *pic;
 };
 
-void ledma_set_irq(void *opaque, int isr)
-{
-    DMAState *s = opaque;
-
-    pic_set_irq_new(s->intctl, s->leirq, isr);
-}
-
 /* Note: on sparc, the lance 16 bit bus is swapped */
 void ledma_memory_read(void *opaque, target_phys_addr_t addr, 
                        uint8_t *buf, int len, int do_bswap)
@@ -125,8 +116,9 @@
 {
     DMAState *s = opaque;
 
+    DPRINTF("Raise ESP IRQ\n");
     s->dmaregs[0] |= DMA_INTR;
-    pic_set_irq_new(s->intctl, s->espirq, 1);
+    qemu_irq_raise(s->espirq);
 }
 
 void espdma_clear_irq(void *opaque)
@@ -134,7 +126,8 @@
     DMAState *s = opaque;
 
     s->dmaregs[0] &= ~DMA_INTR;
-    pic_set_irq_new(s->intctl, s->espirq, 0);
+    DPRINTF("Lower ESP IRQ\n");
+    qemu_irq_lower(s->espirq);
 }
 
 void espdma_memory_read(void *opaque, uint8_t *buf, int len)
@@ -179,8 +172,10 @@
     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->dmaregs[saddr], val);
     switch (saddr) {
     case 0:
-        if (!(val & DMA_INTREN))
-            pic_set_irq_new(s->intctl, s->espirq, 0);
+        if (!(val & DMA_INTREN)) {
+            DPRINTF("Lower ESP IRQ\n");
+            qemu_irq_lower(s->espirq);
+        }
         if (val & DMA_RESET) {
             esp_reset(s->esp_opaque);
         } else if (val & 0x40) {
@@ -194,8 +189,12 @@
         s->dmaregs[0] |= DMA_LOADED;
         break;
     case 4:
-        if (!(val & DMA_INTREN))
-            pic_set_irq_new(s->intctl, s->leirq, 0);
+        /* ??? Should this mask out the lance IRQ?  The NIC may re-assert
+           this IRQ unexpectedly.  */
+        if (!(val & DMA_INTREN)) {
+            DPRINTF("Lower Lance IRQ\n");
+            qemu_irq_lower(s->leirq);
+        }
         if (val & DMA_RESET)
             pcnet_h_reset(s->lance_opaque);
         val &= 0x0fffffff;
@@ -250,7 +249,8 @@
     return 0;
 }
 
-void *sparc32_dma_init(uint32_t daddr, int espirq, int leirq, void *iommu, void *intctl)
+void *sparc32_dma_init(uint32_t daddr, qemu_irq espirq, qemu_irq leirq,
+                       void *iommu)
 {
     DMAState *s;
     int dma_io_memory;
@@ -262,7 +262,6 @@
     s->espirq = espirq;
     s->leirq = leirq;
     s->iommu = iommu;
-    s->intctl = intctl;
 
     dma_io_memory = cpu_register_io_memory(0, dma_mem_read, dma_mem_write, s);
     cpu_register_physical_memory(daddr, 16 * 2, dma_io_memory);

Modified: trunk/src/host/qemu-neo1973/hw/spitz.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/spitz.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/spitz.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,16 +1,18 @@
 /*
- * Sharp Zaurus SL-C1000/C3000/C3100/C3200 platforms.
+ * PXA270-based Clamshell PDA platforms.
  *
  * Copyright (c) 2006 Openedhand Ltd.
  * Written by Andrzej Zaborowski <balrog at zabor.org>
  *
- * This code is licensed under the GPLv2.
+ * This code is licensed under the GNU GPL v2.
  */
 
 #include "vl.h"
 
 #define spitz_printf(format, ...)	\
     fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
+#undef REG_FMT
+#define REG_FMT			"0x%02lx"
 
 /* Spitz Flash */
 #define FLASH_BASE		0x0c000000
@@ -30,16 +32,16 @@
 #define FLASHCTL_RYBY		(1 << 5)
 #define FLASHCTL_NCE		(FLASHCTL_CE0 | FLASHCTL_CE1)
 
-struct sharpsl_nand_s {
+struct sl_nand_s {
     target_phys_addr_t target_base;
     struct nand_flash_s *nand;
     uint8_t ctl;
     struct ecc_state_s ecc;
 };
 
-static uint32_t sharpsl_readb(void *opaque, target_phys_addr_t addr)
+static uint32_t sl_readb(void *opaque, target_phys_addr_t addr)
 {
-    struct sharpsl_nand_s *s = (struct sharpsl_nand_s *) opaque;
+    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
     int ryby;
     addr -= s->target_base;
 
@@ -71,15 +73,15 @@
         return ecc_digest(&s->ecc, nand_getio(s->nand));
 
     default:
-        spitz_printf("Bad register offset 0x%02lx\n", addr);
+        spitz_printf("Bad register offset " REG_FMT "\n", addr);
     }
     return 0;
 }
 
-static void sharpsl_writeb(void *opaque, target_phys_addr_t addr,
+static void sl_writeb(void *opaque, target_phys_addr_t addr,
                 uint32_t value)
 {
-    struct sharpsl_nand_s *s = (struct sharpsl_nand_s *) opaque;
+    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
     addr -= s->target_base;
 
     switch (addr) {
@@ -103,7 +105,7 @@
         break;
 
     default:
-        spitz_printf("Bad register offset 0x%02lx\n", addr);
+        spitz_printf("Bad register offset " REG_FMT "\n", addr);
     }
 }
 
@@ -112,23 +114,22 @@
     FLASH_1024M,
 };
 
-static void sharpsl_flash_register(struct pxa2xx_state_s *cpu, int size)
+static void sl_flash_register(struct pxa2xx_state_s *cpu, int size)
 {
     int iomemtype;
-    struct sharpsl_nand_s *s;
-    CPUReadMemoryFunc *sharpsl_readfn[] = {
-        sharpsl_readb,
-        sharpsl_readb,
-        sharpsl_readb,
+    struct sl_nand_s *s;
+    CPUReadMemoryFunc *sl_readfn[] = {
+        sl_readb,
+        sl_readb,
+        sl_readb,
     };
-    CPUWriteMemoryFunc *sharpsl_writefn[] = {
-        sharpsl_writeb,
-        sharpsl_writeb,
-        sharpsl_writeb,
+    CPUWriteMemoryFunc *sl_writefn[] = {
+        sl_writeb,
+        sl_writeb,
+        sl_writeb,
     };
 
-    s = (struct sharpsl_nand_s *)
-            qemu_mallocz(sizeof(struct sharpsl_nand_s));
+    s = (struct sl_nand_s *) qemu_mallocz(sizeof(struct sl_nand_s));
     s->target_base = FLASH_BASE;
     s->ctl = 0;
     if (size == FLASH_128M)
@@ -136,8 +137,8 @@
     else if (size == FLASH_1024M)
         s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
 
-    iomemtype = cpu_register_io_memory(0, sharpsl_readfn,
-                    sharpsl_writefn, s);
+    iomemtype = cpu_register_io_memory(0, sl_readfn,
+                    sl_writefn, s);
     cpu_register_physical_memory(s->target_base, 0x40, iomemtype);
 }
 
@@ -302,7 +303,7 @@
             QUEUE_KEY(0x2a | (~keycode & 0x80));
         if ((code & FN   ) && (s->modifiers & 2))
             QUEUE_KEY(0x36 | (~keycode & 0x80));
-#endif
+#else
         if (keycode & 0x80) {
             if ((s->imodifiers & 1   ) && !(s->modifiers & 1))
                 QUEUE_KEY(0x2a | 0x80);
@@ -339,6 +340,7 @@
                 s->imodifiers |= 0x20;
             }
         }
+#endif
     }
 
     QUEUE_KEY((code & 0x7f) | (keycode & 0x80));
@@ -508,7 +510,7 @@
     case SCOOP_GPRR:
         return s->gprr;
     default:
-        spitz_printf("Bad register offset 0x%02lx\n", addr);
+        spitz_printf("Bad register offset " REG_FMT "\n", addr);
     }
 
     return 0;
@@ -556,7 +558,7 @@
         s->gprr = value;
         break;
     default:
-        spitz_printf("Bad register offset 0x%02lx\n", addr);
+        spitz_printf("Bad register offset " REG_FMT "\n", addr);
     }
 }
 
@@ -755,7 +757,7 @@
         max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
 }
 
-static void spitz_pendown_set(void *opaque, int level)
+static void spitz_pendown_set(void *opaque, int line, int level)
 {
     struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
     pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_TP_INT, level);
@@ -765,9 +767,9 @@
 {
     lcd_en = ads_en = max_en = 0;
 
-    ads7846 = ads7846_init(spitz_pendown_set, cpu);
+    ads7846 = ads7846_init(qemu_allocate_irqs(spitz_pendown_set, cpu, 1)[0]);
 
-    max1111 = max1111_init(0, cpu);
+    max1111 = max1111_init(0);
     max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT);
     max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
     max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
@@ -802,30 +804,41 @@
 /* Wm8750 and Max7310 on I2C */
 
 #define AKITA_MAX_ADDR	0x18
-#define SPITZ_WM_ADDR	0x1b
+#define SPITZ_WM_ADDRL	0x1a
+#define SPITZ_WM_ADDRH	0x1b
 
-static void spitz_i2c_setup(struct pxa2xx_state_s *cpu)
-{
+#define SPITZ_GPIO_WM	5
+
 #ifdef HAS_AUDIO
-    AudioState *audio;
-    struct i2c_slave_s *wm;
+static void spitz_wm8750_addr(int line, int level, void *opaque)
+{
+    i2c_slave *wm = (i2c_slave *) opaque;
+    if (level)
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRH);
+    else
+        i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
+}
 #endif
-    struct i2c_bus_s *bus = (struct i2c_bus_s *)
-            qemu_mallocz(sizeof(struct i2c_bus_s));
 
+static void spitz_i2c_setup(struct pxa2xx_state_s *cpu)
+{
     /* Attach the CPU on one end of our I2C bus.  */
-    i2c_master_attach(bus, &cpu->i2c[0]->master);
+    i2c_bus *bus = cpu->i2c[0]->bus;
 
 #ifdef HAS_AUDIO
+    AudioState *audio;
+    i2c_slave *wm;
+
     audio = AUD_init();
     if (!audio)
         return;
-    wm = wm8750_init(audio);
-
     /* Attach a WM8750 to the bus */
-    i2c_slave_attach(bus, SPITZ_WM_ADDR, wm);
+    wm = wm8750_init(bus, audio);
+
+    spitz_wm8750_addr(0, 0, wm);
+    pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_WM, spitz_wm8750_addr, wm);
     /* .. and to the sound interface.  */
-    cpu->i2s->opaque = wm->opaque;
+    cpu->i2s->opaque = wm;
     cpu->i2s->codec_out = wm8750_dac_dat;
     cpu->i2s->codec_in = wm8750_adc_dat;
     wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
@@ -835,7 +848,7 @@
 static void spitz_akita_i2c_setup(struct pxa2xx_state_s *cpu)
 {
     /* Attach a Max7310 to Akita I2C bus.  */
-    i2c_slave_attach(cpu->i2c[0]->master.bus, AKITA_MAX_ADDR, max7310_init());
+    i2c_set_slave_address(max7310_init(cpu->i2c[0]->bus), AKITA_MAX_ADDR);
 }
 
 /* Other peripherals */
@@ -929,8 +942,19 @@
     pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_SD_WP, wp);
 }
 
+static void spitz_pcmcia_cb(void *opaque, int line, int level)
+{
+    struct pxa2xx_state_s *cpu = (struct pxa2xx_state_s *) opaque;
+    static const int gpio_map[] = {
+        SPITZ_GPIO_CF1_IRQ, SPITZ_GPIO_CF1_CD,
+        SPITZ_GPIO_CF2_IRQ, SPITZ_GPIO_CF2_CD,
+    };
+    pxa2xx_gpio_set(cpu->gpio, gpio_map[line], level);
+}
+
 static void spitz_gpio_setup(struct pxa2xx_state_s *cpu, int slots)
 {
+    qemu_irq *pcmcia_cb;
     /*
      * Bad hack: We toggle the LCD hsync GPIO on every GPIO status
      * read to satisfy broken guests that poll-wait for hsync.
@@ -952,14 +976,11 @@
     pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_ON_RESET, pxa2xx_reset, cpu);
 
     /* PCMCIA signals: card's IRQ and Card-Detect */
+    pcmcia_cb = qemu_allocate_irqs(spitz_pcmcia_cb, cpu, slots * 2);
     if (slots >= 1)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        (void (*)(void *, int, int)) pxa2xx_gpio_set,
-                        SPITZ_GPIO_CF1_IRQ, SPITZ_GPIO_CF1_CD, cpu->gpio);
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0], pcmcia_cb[0], pcmcia_cb[1]);
     if (slots >= 2)
-        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        (void (*)(void *, int, int)) pxa2xx_gpio_set,
-                        SPITZ_GPIO_CF2_IRQ, SPITZ_GPIO_CF2_CD, cpu->gpio);
+        pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1], pcmcia_cb[2], pcmcia_cb[3]);
 
     /* Initialise the screen rotation related signals */
     spitz_gpio_invert[3] = 0;	/* Always open */
@@ -976,7 +997,7 @@
 
 #define MAGIC_CHG(a, b, c, d)	((d << 24) | (c << 16) | (b << 8) | a)
 
-struct __attribute__ ((__packed__)) sharpsl_param_info {
+struct __attribute__ ((__packed__)) sl_param_info {
     uint32_t comadj_keyword;
     int32_t comadj;
 
@@ -1007,227 +1028,130 @@
     .phadadj		= 0x01,
 };
 
-static void sharpsl_bootparam_write(uint32_t ptr)
+static void sl_bootparam_write(uint32_t ptr)
 {
     memcpy(phys_ram_base + ptr, &spitz_bootparam,
-                    sizeof(struct sharpsl_param_info));
+                    sizeof(struct sl_param_info));
 }
 
-#define SHARPSL_PXA_PARAM_BASE	0xa0000a00
+#define SL_PXA_PARAM_BASE	0xa0000a00
 
 /* Board init.  */
+enum spitz_model_e { spitz, akita, borzoi, terrier };
 
-static void spitz_init(int ram_size, int vga_ram_size, int boot_device,
-                DisplayState *ds, const char **fd_filename, int snapshot,
-                const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+static void spitz_common_init(int ram_size, int vga_ram_size,
+                DisplayState *ds, const char *kernel_filename,
+                const char *kernel_cmdline, const char *initrd_filename,
+                const char *cpu_model, enum spitz_model_e model, int arm_id)
 {
     uint32_t spitz_ram = 0x04000000;
     uint32_t spitz_rom = 0x00800000;
     struct pxa2xx_state_s *cpu;
     struct scoop_info_s *scp;
 
-    cpu = pxa270_init(ds, 4);
+    if (!cpu_model)
+        cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
 
-    /* Setup memory */
+    /* Setup CPU & memory */
     if (ram_size < spitz_ram + spitz_rom) {
         fprintf(stderr, "This platform requires %i bytes of memory\n",
                         spitz_ram + spitz_rom);
         exit(1);
     }
-    cpu_register_physical_memory(PXA2XX_RAM_BASE, spitz_ram, IO_MEM_RAM);
+    cpu = pxa270_init(spitz_ram, ds, cpu_model);
 
-    sharpsl_flash_register(cpu, FLASH_128M);
+    sl_flash_register(cpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
 
-    cpu_register_physical_memory(0, spitz_rom, spitz_ram | IO_MEM_ROM);
+    cpu_register_physical_memory(0, spitz_rom,
+                    qemu_ram_alloc(spitz_rom) | IO_MEM_ROM);
 
     /* Setup peripherals */
     spitz_keyboard_register(cpu);
 
     spitz_ssp_attach(cpu);
 
-    scp = spitz_scoop_init(cpu, 2);
+    scp = spitz_scoop_init(cpu, (model == akita) ? 1 : 2);
 
-    spitz_scoop_gpio_setup(cpu, scp, 2);
+    spitz_scoop_gpio_setup(cpu, scp, (model == akita) ? 1 : 2);
 
-    spitz_gpio_setup(cpu, 2);
+    spitz_gpio_setup(cpu, (model == akita) ? 1 : 2);
 
     spitz_i2c_setup(cpu);
 
-    /* A 4.0 GB microdrive is permanently sitting in CF slot 0 */
-    spitz_microdrive_attach(cpu);
+    if (model == akita)
+        spitz_akita_i2c_setup(cpu);
 
+    if (model == terrier)
+        /* A 6.0 GB microdrive is permanently sitting in CF slot 0.  */
+        spitz_microdrive_attach(cpu);
+    else if (model != akita)
+        /* A 4.0 GB microdrive is permanently sitting in CF slot 0.  */
+        spitz_microdrive_attach(cpu);
+
     /* Setup initial (reset) machine state */
-    cpu->env->regs[15] = PXA2XX_RAM_BASE;
+    cpu->env->regs[15] = PXA2XX_SDRAM_BASE;
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
-                    initrd_filename, 0x2c9, PXA2XX_RAM_BASE);
-    sharpsl_bootparam_write(SHARPSL_PXA_PARAM_BASE - PXA2XX_RAM_BASE);
+    arm_load_kernel(cpu->env, spitz_ram, kernel_filename, kernel_cmdline,
+                    initrd_filename, arm_id, PXA2XX_SDRAM_BASE);
+    sl_bootparam_write(SL_PXA_PARAM_BASE - PXA2XX_SDRAM_BASE);
 }
 
-/* TODO: remember to update this when Spitz support is more complete */
-static void borzoi_init(int ram_size, int vga_ram_size, int boot_device,
+static void spitz_init(int ram_size, int vga_ram_size, int boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+                const char *initrd_filename, const char *cpu_model)
 {
-    uint32_t spitz_ram = 0x04000000;
-    uint32_t spitz_rom = 0x00800000;
-    struct pxa2xx_state_s *cpu;
-    struct scoop_info_s *scp;
+    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, spitz, 0x2c9);
+}
 
-    cpu = pxa270_init(ds, 4);
-
-    /* Setup memory */
-    if (ram_size < spitz_ram) {
-        fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        ram_size);
-        exit(1);
-    }
-    cpu_register_physical_memory(PXA2XX_RAM_BASE, spitz_ram, IO_MEM_RAM);
-
-    sharpsl_flash_register(cpu, FLASH_1024M);
-
-    cpu_register_physical_memory(0, spitz_rom, spitz_ram | IO_MEM_ROM);
-
-    /* Setup peripherals */
-    spitz_keyboard_register(cpu);
-
-    spitz_ssp_attach(cpu);
-
-    scp = spitz_scoop_init(cpu, 2);
-
-    spitz_scoop_gpio_setup(cpu, scp, 2);
-
-    spitz_gpio_setup(cpu, 2);
-
-    spitz_i2c_setup(cpu);
-
-    /* A 4.0 GB microdrive is permanently sitting in CF slot 0 */
-    spitz_microdrive_attach(cpu);
-
-    /* Setup initial (reset) machine state */
-    cpu->env->regs[15] = PXA2XX_RAM_BASE;
-
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
-                    initrd_filename, 0x33f, PXA2XX_RAM_BASE);
-    sharpsl_bootparam_write(SHARPSL_PXA_PARAM_BASE - PXA2XX_RAM_BASE);
+static void borzoi_init(int ram_size, int vga_ram_size, int boot_device,
+                DisplayState *ds, const char **fd_filename, int snapshot,
+                const char *kernel_filename, const char *kernel_cmdline,
+                const char *initrd_filename, const char *cpu_model)
+{
+    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, borzoi, 0x33f);
 }
 
 static void akita_init(int ram_size, int vga_ram_size, int boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+                const char *initrd_filename, const char *cpu_model)
 {
-    uint32_t spitz_ram = 0x04000000;
-    uint32_t spitz_rom = 0x00800000;
-    struct pxa2xx_state_s *cpu;
-    struct scoop_info_s *scp;
-
-    cpu = pxa270_init(ds, 4);
-
-    /* Setup memory */
-    if (ram_size < spitz_ram) {
-        fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        ram_size);
-        exit(1);
-    }
-    cpu_register_physical_memory(PXA2XX_RAM_BASE, spitz_ram, IO_MEM_RAM);
-
-    sharpsl_flash_register(cpu, FLASH_1024M);
-
-    cpu_register_physical_memory(0, spitz_rom, spitz_ram | IO_MEM_ROM);
-
-    /* Setup peripherals */
-    spitz_keyboard_register(cpu);
-
-    spitz_ssp_attach(cpu);
-
-    scp = spitz_scoop_init(cpu, 1);
-
-    spitz_scoop_gpio_setup(cpu, scp, 1);
-
-    spitz_gpio_setup(cpu, 1);
-
-    spitz_i2c_setup(cpu);
-    spitz_akita_i2c_setup(cpu);
-
-    /* Setup initial (reset) machine state */
-    cpu->env->regs[15] = PXA2XX_RAM_BASE;
-
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
-                    initrd_filename, 0x2e8, PXA2XX_RAM_BASE);
-    sharpsl_bootparam_write(SHARPSL_PXA_PARAM_BASE - PXA2XX_RAM_BASE);
+    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, akita, 0x2e8);
 }
 
 static void terrier_init(int ram_size, int vga_ram_size, int boot_device,
                 DisplayState *ds, const char **fd_filename, int snapshot,
                 const char *kernel_filename, const char *kernel_cmdline,
-                const char *initrd_filename)
+                const char *initrd_filename, const char *cpu_model)
 {
-    uint32_t spitz_ram = 0x04000000;
-    uint32_t spitz_rom = 0x00800000;
-    struct pxa2xx_state_s *cpu;
-    struct scoop_info_s *scp;
-
-    cpu = pxa270_init(ds, 7);
-
-    /* Setup memory */
-    if (ram_size < spitz_ram) {
-        fprintf(stderr, "This platform requires %i bytes of memory\n",
-                        ram_size);
-        exit(1);
-    }
-    cpu_register_physical_memory(PXA2XX_RAM_BASE, spitz_ram, IO_MEM_RAM);
-
-    sharpsl_flash_register(cpu, FLASH_1024M);
-
-    cpu_register_physical_memory(0, spitz_rom, spitz_ram | IO_MEM_ROM);
-
-    /* Setup peripherals */
-    spitz_keyboard_register(cpu);
-
-    spitz_ssp_attach(cpu);
-
-    scp = spitz_scoop_init(cpu, 2);
-
-    spitz_scoop_gpio_setup(cpu, scp, 2);
-
-    spitz_gpio_setup(cpu, 2);
-
-    spitz_i2c_setup(cpu);
-
-    /* A 6.0 GB microdrive is permanently sitting in CF slot 0 */
-    spitz_microdrive_attach(cpu);
-
-    /* Setup initial (reset) machine state */
-    cpu->env->regs[15] = PXA2XX_RAM_BASE;
-
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
-                    initrd_filename, 0x33f, PXA2XX_RAM_BASE);
-    sharpsl_bootparam_write(SHARPSL_PXA_PARAM_BASE - PXA2XX_RAM_BASE);
+    spitz_common_init(ram_size, vga_ram_size, ds, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, terrier, 0x33f);
 }
 
-QEMUMachine zaurusakita_machine = {
+QEMUMachine akitapda_machine = {
     "akita",
-    "Sharp Zaurus SL-C1000 aka Akita (PXA270)",
+    "Akita PDA (PXA270)",
     akita_init,
 };
 
-QEMUMachine zaurusspitz_machine = {
+QEMUMachine spitzpda_machine = {
     "spitz",
-    "Sharp Zaurus SL-C3000 aka Spitz (PXA270)",
+    "Spitz PDA (PXA270)",
     spitz_init,
 };
 
-QEMUMachine zaurusborzoi_machine = {
+QEMUMachine borzoipda_machine = {
     "borzoi",
-    "Sharp Zaurus SL-C3100 aka Borzoi (PXA270)",
+    "Borzoi PDA (PXA270)",
     borzoi_init,
 };
 
-QEMUMachine zaurusterrier_machine = {
+QEMUMachine terrierpda_machine = {
     "terrier",
-    "Sharp Zaurus SL-C3200 aka Terrier (PXA270)",
+    "Terrier PDA (PXA270)",
     terrier_init,
 };

Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -23,43 +23,45 @@
  */
 #include "vl.h"
 
+/*
+ * Sun4m architecture was used in the following machines:
+ *
+ * SPARCserver 6xxMP/xx
+ * SPARCclassic (SPARCclassic Server)(SPARCstation LC) (4/15), SPARCclassic X (4/10)
+ * SPARCstation LX/ZX (4/30)
+ * SPARCstation Voyager
+ * SPARCstation 10/xx, SPARCserver 10/xx
+ * SPARCstation 5, SPARCserver 5
+ * SPARCstation 20/xx, SPARCserver 20
+ * SPARCstation 4
+ *
+ * See for example: http://www.sunhelp.org/faq/sunref1.html
+ */
+
 #define KERNEL_LOAD_ADDR     0x00004000
 #define CMDLINE_ADDR         0x007ff000
 #define INITRD_LOAD_ADDR     0x00800000
 #define PROM_SIZE_MAX        (256 * 1024)
 #define PROM_ADDR	     0xffd00000
 #define PROM_FILENAME	     "openbios-sparc32"
-#define PHYS_JJ_EEPROM	0x71200000	/* m48t08 */
-#define PHYS_JJ_IDPROM_OFF	0x1FD8
-#define PHYS_JJ_EEPROM_SIZE	0x2000
-// IRQs are not PIL ones, but master interrupt controller register
-// bits
-#define PHYS_JJ_IOMMU	0x10000000	/* I/O MMU */
-#define PHYS_JJ_TCX_FB	0x50000000	/* TCX frame buffer */
-#define PHYS_JJ_SLAVIO	0x70000000	/* Slavio base */
-#define PHYS_JJ_DMA     0x78400000      /* DMA controller */
-#define PHYS_JJ_ESP     0x78800000      /* ESP SCSI */
-#define PHYS_JJ_ESP_IRQ    18
-#define PHYS_JJ_LE      0x78C00000      /* Lance ethernet */
-#define PHYS_JJ_LE_IRQ     16
-#define PHYS_JJ_CLOCK	0x71D00000      /* Per-CPU timer/counter, L14 */
-#define PHYS_JJ_CLOCK_IRQ  7
-#define PHYS_JJ_CLOCK1	0x71D10000      /* System timer/counter, L10 */
-#define PHYS_JJ_CLOCK1_IRQ 19
-#define PHYS_JJ_INTR0	0x71E00000	/* Per-CPU interrupt control registers */
-#define PHYS_JJ_INTR_G	0x71E10000	/* Master interrupt control registers */
-#define PHYS_JJ_MS_KBD	0x71000000	/* Mouse and keyboard */
-#define PHYS_JJ_MS_KBD_IRQ    14
-#define PHYS_JJ_SER	0x71100000	/* Serial */
-#define PHYS_JJ_SER_IRQ    15
-#define PHYS_JJ_FDC	0x71400000	/* Floppy */
-#define PHYS_JJ_FLOPPY_IRQ 22
-#define PHYS_JJ_ME_IRQ 30		/* Module error, power fail */
-#define PHYS_JJ_CS      0x6c000000      /* Crystal CS4231 */
-#define PHYS_JJ_CS_IRQ  5
 
 #define MAX_CPUS 16
 
+struct hwdef {
+    target_ulong iommu_base, slavio_base;
+    target_ulong intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
+    target_ulong fd_base;
+    target_ulong dma_base, esp_base, le_base;
+    target_ulong tcx_base, cs_base;
+    long vram_size, nvram_size;
+    // IRQ numbers are not PIL ones, but master interrupt controller register
+    // bit numbers
+    int intctl_g_intr, esp_irq, le_irq, cpu_irq, clock_irq, clock1_irq;
+    int ser_irq, ms_kb_irq, fd_irq, me_irq, cs_irq;
+    int machine_id; // For NVRAM
+    uint32_t intbit_to_level[32];
+};
+
 /* TSC handling */
 
 uint64_t cpu_get_tsc()
@@ -115,6 +117,34 @@
     m48t59_write(nvram, addr + max - 1, '\0');
 }
 
+static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
+                                const unsigned char *str)
+{
+    uint32_t len;
+
+    len = strlen(str) + 1;
+    nvram_set_string(nvram, addr, str, len);
+
+    return addr + len;
+}
+
+static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
+                                    uint32_t end)
+{
+    unsigned int i, sum;
+
+    // Length divided by 16
+    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
+    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
+    // Checksum
+    sum = m48t59_read(nvram, start);
+    for (i = 0; i < 14; i++) {
+        sum += m48t59_read(nvram, start + 2 + i);
+        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
+    }
+    m48t59_write(nvram, start + 1, sum & 0xff);
+}
+
 static m48t59_t *nvram;
 
 extern int nographic;
@@ -122,10 +152,12 @@
 static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
 		       int boot_device, uint32_t RAM_size,
 		       uint32_t kernel_size,
-		       int width, int height, int depth)
+		       int width, int height, int depth,
+                       int machine_id)
 {
     unsigned char tmp = 0;
-    int i, j;
+    unsigned int i, j;
+    uint32_t start, end;
 
     // Try to match PPC NVRAM
     nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
@@ -148,10 +180,32 @@
     nvram_set_word(nvram,   0x56, height);
     nvram_set_word(nvram,   0x58, depth);
 
+    // OpenBIOS nvram variables
+    // Variable partition
+    start = 252;
+    m48t59_write(nvram, start, 0x70);
+    nvram_set_string(nvram, start + 4, "system", 12);
+
+    end = start + 16;
+    for (i = 0; i < nb_prom_envs; i++)
+        end = nvram_set_var(nvram, end, prom_envs[i]);
+
+    m48t59_write(nvram, end++ , 0);
+    end = start + ((end - start + 15) & ~15);
+    nvram_finish_partition(nvram, start, end);
+
+    // free partition
+    start = end;
+    m48t59_write(nvram, start, 0x7f);
+    nvram_set_string(nvram, start + 4, "free", 12);
+
+    end = 0x1fd0;
+    nvram_finish_partition(nvram, start, end);
+
     // Sun4m specific use
-    i = 0x1fd8;
+    start = i = 0x1fd8;
     m48t59_write(nvram, i++, 0x01);
-    m48t59_write(nvram, i++, 0x80); /* Sun4m OBP */
+    m48t59_write(nvram, i++, machine_id);
     j = 0;
     m48t59_write(nvram, i++, macaddr[j++]);
     m48t59_write(nvram, i++, macaddr[j++]);
@@ -161,10 +215,10 @@
     m48t59_write(nvram, i, macaddr[j]);
 
     /* Calculate checksum */
-    for (i = 0x1fd8; i < 0x1fe7; i++) {
-	tmp ^= m48t59_read(nvram, i);
+    for (i = start; i < start + 15; i++) {
+        tmp ^= m48t59_read(nvram, i);
     }
-    m48t59_write(nvram, 0x1fe7, tmp);
+    m48t59_write(nvram, start + 15, tmp);
 }
 
 static void *slavio_intctl;
@@ -179,21 +233,6 @@
     slavio_irq_info(slavio_intctl);
 }
 
-void pic_set_irq(int irq, int level)
-{
-    slavio_pic_set_irq(slavio_intctl, irq, level);
-}
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
-    pic_set_irq(irq, level);
-}
-
-void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
-{
-    slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
-}
-
 static void *slavio_misc;
 
 void qemu_system_powerdown(void)
@@ -207,24 +246,25 @@
     cpu_reset(env);
 }
 
-/* Sun4m hardware initialisation */
-static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
-                       DisplayState *ds, const char **fd_filename, int snapshot,
-                       const char *kernel_filename, const char *kernel_cmdline,
-                       const char *initrd_filename)
+static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size,
+                          DisplayState *ds, const char *cpu_model)
+
 {
     CPUState *env, *envs[MAX_CPUS];
-    char buf[1024];
-    int ret, linux_boot;
     unsigned int i;
-    long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
     void *iommu, *dma, *main_esp, *main_lance = NULL;
+    const sparc_def_t *def;
+    qemu_irq *slavio_irq;
 
-    linux_boot = (kernel_filename != NULL);
-
     /* init CPUs */
+    sparc_find_by_name(cpu_model, &def);
+    if (def == NULL) {
+        fprintf(stderr, "Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
     for(i = 0; i < smp_cpus; i++) {
         env = cpu_init();
+        cpu_sparc_register(env, def);
         envs[i] = env;
         if (i != 0)
             env->halted = 1;
@@ -234,45 +274,82 @@
     /* allocate RAM */
     cpu_register_physical_memory(0, ram_size, 0);
 
-    iommu = iommu_init(PHYS_JJ_IOMMU);
-    slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
+    iommu = iommu_init(hwdef->iommu_base);
+    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
+                                       hwdef->intctl_base + 0x10000,
+                                       &hwdef->intbit_to_level[0],
+                                       &slavio_irq);
     for(i = 0; i < smp_cpus; i++) {
         slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
     }
-    dma = sparc32_dma_init(PHYS_JJ_DMA, PHYS_JJ_ESP_IRQ, PHYS_JJ_LE_IRQ, iommu, slavio_intctl);
+    dma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],
+                           slavio_irq[hwdef->le_irq], iommu);
 
-    tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
+    if (graphic_depth != 8 && graphic_depth != 24) {
+        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);
+        exit (1);
+    }
+    tcx_init(ds, hwdef->tcx_base, phys_ram_base + ram_size, ram_size,
+             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "lance") == 0) {
-            main_lance = lance_init(&nd_table[0], PHYS_JJ_LE, dma);
+            main_lance = lance_init(&nd_table[0], hwdef->le_base, dma,
+                                    slavio_irq[hwdef->le_irq]);
         } else {
             fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
             exit (1);
         }
     }
-    nvram = m48t59_init(0, PHYS_JJ_EEPROM, 0, PHYS_JJ_EEPROM_SIZE, 8);
+    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
+                        hwdef->nvram_size, 8);
     for (i = 0; i < MAX_CPUS; i++) {
-        slavio_timer_init(PHYS_JJ_CLOCK + i * TARGET_PAGE_SIZE, PHYS_JJ_CLOCK_IRQ, 0, i);
+        slavio_timer_init(hwdef->counter_base + i * TARGET_PAGE_SIZE,
+                          hwdef->clock_irq, 0, i, slavio_intctl);
     }
-    slavio_timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ, 2, (unsigned int)-1);
-    slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
+    slavio_timer_init(hwdef->counter_base + 0x10000, hwdef->clock1_irq, 2,
+                      (unsigned int)-1, slavio_intctl);
+    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq]);
     // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
     // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
-    slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[1], serial_hds[0]);
-    fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
-    main_esp = esp_init(bs_table, PHYS_JJ_ESP, dma);
-    slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
-    cs_init(PHYS_JJ_CS, PHYS_JJ_CS_IRQ, slavio_intctl);
+    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
+                       serial_hds[1], serial_hds[0]);
+    fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table);
+    main_esp = esp_init(bs_table, hwdef->esp_base, dma);
+
+    for (i = 0; i < MAX_DISKS; i++) {
+        if (bs_table[i]) {
+            esp_scsi_attach(main_esp, bs_table[i], i);
+        }
+    }
+
+    slavio_misc = slavio_misc_init(hwdef->slavio_base, 
+                                   slavio_irq[hwdef->me_irq]);
+    if (hwdef->cs_base != (target_ulong)-1)
+        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);
     sparc32_dma_set_reset_data(dma, main_esp, main_lance);
+}
 
+static void sun4m_load_kernel(long vram_size, int ram_size, int boot_device,
+                              const char *kernel_filename,
+                              const char *kernel_cmdline,
+                              const char *initrd_filename,
+                              int machine_id)
+{
+    int ret, linux_boot;
+    char buf[1024];
+    unsigned int i;
+    long prom_offset, initrd_size, kernel_size;
+
+    linux_boot = (kernel_filename != NULL);
+
     prom_offset = ram_size + vram_size;
     cpu_register_physical_memory(PROM_ADDR, 
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK, 
                                  prom_offset | IO_MEM_ROM);
 
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
-    ret = load_elf(buf, 0, NULL);
+    ret = load_elf(buf, 0, NULL, NULL, NULL);
     if (ret < 0) {
 	fprintf(stderr, "qemu: could not load prom '%s'\n", 
 		buf);
@@ -281,7 +358,7 @@
 
     kernel_size = 0;
     if (linux_boot) {
-        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL);
+        kernel_size = load_elf(kernel_filename, -0xf0000000, NULL, NULL, NULL);
         if (kernel_size < 0)
 	    kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
 	if (kernel_size < 0)
@@ -313,11 +390,124 @@
 	    }
         }
     }
-    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
+    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
+               boot_device, ram_size, kernel_size, graphic_width,
+               graphic_height, graphic_depth, machine_id);
 }
 
-QEMUMachine sun4m_machine = {
-    "sun4m",
-    "Sun4m platform",
-    sun4m_init,
+static const struct hwdef hwdefs[] = {
+    /* SS-5 */
+    {
+        .iommu_base   = 0x10000000,
+        .tcx_base     = 0x50000000,
+        .cs_base      = 0x6c000000,
+        .slavio_base  = 0x70000000,
+        .ms_kb_base   = 0x71000000,
+        .serial_base  = 0x71100000,
+        .nvram_base   = 0x71200000,
+        .fd_base      = 0x71400000,
+        .counter_base = 0x71d00000,
+        .intctl_base  = 0x71e00000,
+        .dma_base     = 0x78400000,
+        .esp_base     = 0x78800000,
+        .le_base      = 0x78c00000,
+        .vram_size    = 0x00100000,
+        .nvram_size   = 0x2000,
+        .esp_irq = 18,
+        .le_irq = 16,
+        .clock_irq = 7,
+        .clock1_irq = 19,
+        .ms_kb_irq = 14,
+        .ser_irq = 15,
+        .fd_irq = 22,
+        .me_irq = 30,
+        .cs_irq = 5,
+        .machine_id = 0x80,
+        .intbit_to_level = {
+            2, 3, 5, 7, 9, 11, 0, 14,	3, 5, 7, 9, 11, 13, 12, 12,
+            6, 0, 4, 10, 8, 0, 11, 0,	0, 0, 0, 0, 15, 0, 15, 0,
+        },
+    },
+    /* SS-10 */
+    {
+        .iommu_base   = 0xe0000000, // XXX Actually at 0xfe0000000ULL (36 bits)
+        .tcx_base     = 0x20000000, // 0xe20000000ULL,
+        .cs_base      = -1,
+        .slavio_base  = 0xf0000000, // 0xff0000000ULL,
+        .ms_kb_base   = 0xf1000000, // 0xff1000000ULL,
+        .serial_base  = 0xf1100000, // 0xff1100000ULL,
+        .nvram_base   = 0xf1200000, // 0xff1200000ULL,
+        .fd_base      = 0xf1700000, // 0xff1700000ULL,
+        .counter_base = 0xf1300000, // 0xff1300000ULL,
+        .intctl_base  = 0xf1400000, // 0xff1400000ULL,
+        .dma_base     = 0xf0400000, // 0xef0400000ULL,
+        .esp_base     = 0xf0800000, // 0xef0800000ULL,
+        .le_base      = 0xf0c00000, // 0xef0c00000ULL,
+        .vram_size    = 0x00100000,
+        .nvram_size   = 0x2000,
+        .esp_irq = 18,
+        .le_irq = 16,
+        .clock_irq = 7,
+        .clock1_irq = 19,
+        .ms_kb_irq = 14,
+        .ser_irq = 15,
+        .fd_irq = 22,
+        .me_irq = 30,
+        .cs_irq = -1,
+        .machine_id = 0x72,
+        .intbit_to_level = {
+            2, 3, 5, 7, 9, 11, 0, 14,	3, 5, 7, 9, 11, 13, 12, 12,
+            6, 0, 4, 10, 8, 0, 11, 0,	0, 0, 0, 0, 15, 0, 15, 0,
+        },
+    },
 };
+
+static void sun4m_common_init(int ram_size, int boot_device, DisplayState *ds,
+                              const char *kernel_filename, const char *kernel_cmdline,
+                              const char *initrd_filename, const char *cpu_model,
+                              unsigned int machine)
+{
+    sun4m_hw_init(&hwdefs[machine], ram_size, ds, cpu_model);
+
+    sun4m_load_kernel(hwdefs[machine].vram_size, ram_size, boot_device,
+                      kernel_filename, kernel_cmdline, initrd_filename,
+                      hwdefs[machine].machine_id);
+}
+
+/* SPARCstation 5 hardware initialisation */
+static void ss5_init(int ram_size, int vga_ram_size, int boot_device,
+                       DisplayState *ds, const char **fd_filename, int snapshot,
+                       const char *kernel_filename, const char *kernel_cmdline,
+                       const char *initrd_filename, const char *cpu_model)
+{
+    if (cpu_model == NULL)
+        cpu_model = "Fujitsu MB86904";
+    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
+                      kernel_cmdline, initrd_filename, cpu_model,
+                      0);
+}
+
+/* SPARCstation 10 hardware initialisation */
+static void ss10_init(int ram_size, int vga_ram_size, int boot_device,
+                            DisplayState *ds, const char **fd_filename, int snapshot,
+                            const char *kernel_filename, const char *kernel_cmdline,
+                            const char *initrd_filename, const char *cpu_model)
+{
+    if (cpu_model == NULL)
+        cpu_model = "TI SuperSparc II";
+    sun4m_common_init(ram_size, boot_device, ds, kernel_filename,
+                      kernel_cmdline, initrd_filename, cpu_model,
+                      1);
+}
+
+QEMUMachine ss5_machine = {
+    "SS-5",
+    "Sun4m platform, SPARCstation 5",
+    ss5_init,
+};
+
+QEMUMachine ss10_machine = {
+    "SS-10",
+    "Sun4m platform, SPARCstation 10",
+    ss10_init,
+};

Modified: trunk/src/host/qemu-neo1973/hw/sun4u.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4u.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/sun4u.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -170,6 +170,34 @@
     return crc;
 }
 
+static uint32_t nvram_set_var (m48t59_t *nvram, uint32_t addr,
+                                const unsigned char *str)
+{
+    uint32_t len;
+
+    len = strlen(str) + 1;
+    NVRAM_set_string(nvram, addr, str, len);
+
+    return addr + len;
+}
+
+static void nvram_finish_partition (m48t59_t *nvram, uint32_t start,
+                                    uint32_t end)
+{
+    unsigned int i, sum;
+
+    // Length divided by 16
+    m48t59_write(nvram, start + 2, ((end - start) >> 12) & 0xff);
+    m48t59_write(nvram, start + 3, ((end - start) >> 4) & 0xff);
+    // Checksum
+    sum = m48t59_read(nvram, start);
+    for (i = 0; i < 14; i++) {
+        sum += m48t59_read(nvram, start + 2 + i);
+        sum = (sum + ((sum & 0xff00) >> 8)) & 0xff;
+    }
+    m48t59_write(nvram, start + 1, sum & 0xff);
+}
+
 extern int nographic;
 
 int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
@@ -182,6 +210,8 @@
                           int width, int height, int depth)
 {
     uint16_t crc;
+    unsigned int i;
+    uint32_t start, end;
 
     /* Set parameters for Open Hack'Ware BIOS */
     NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
@@ -212,6 +242,28 @@
     crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
     NVRAM_set_word(nvram,  0xFC, crc);
 
+    // OpenBIOS nvram variables
+    // Variable partition
+    start = 252;
+    m48t59_write(nvram, start, 0x70);
+    NVRAM_set_string(nvram, start + 4, "system", 12);
+
+    end = start + 16;
+    for (i = 0; i < nb_prom_envs; i++)
+        end = nvram_set_var(nvram, end, prom_envs[i]);
+
+    m48t59_write(nvram, end++ , 0);
+    end = start + ((end - start + 15) & ~15);
+    nvram_finish_partition(nvram, start, end);
+
+    // free partition
+    start = end;
+    m48t59_write(nvram, start, 0x7f);
+    NVRAM_set_string(nvram, start + 4, "free", 12);
+
+    end = 0x1fd0;
+    nvram_finish_partition(nvram, start, end);
+
     return 0;
 }
 
@@ -223,14 +275,6 @@
 {
 }
 
-void pic_set_irq(int irq, int level)
-{
-}
-
-void pic_set_irq_new(void *opaque, int irq, int level)
-{
-}
-
 void qemu_system_powerdown(void)
 {
 }
@@ -257,7 +301,7 @@
 static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
-             const char *initrd_filename)
+             const char *initrd_filename, const char *cpu_model)
 {
     CPUState *env;
     char buf[1024];
@@ -266,10 +310,20 @@
     unsigned int i;
     long prom_offset, initrd_size, kernel_size;
     PCIBus *pci_bus;
+    const sparc_def_t *def;
 
     linux_boot = (kernel_filename != NULL);
 
+    /* init CPUs */
+    if (cpu_model == NULL)
+        cpu_model = "TI UltraSparc II";
+    sparc_find_by_name(cpu_model, &def);
+    if (def == NULL) {
+        fprintf(stderr, "Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
     env = cpu_init();
+    cpu_sparc_register(env, def);
     register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
     qemu_register_reset(main_cpu_reset, env);
 
@@ -282,7 +336,7 @@
                                  prom_offset | IO_MEM_ROM);
 
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
-    ret = load_elf(buf, 0, NULL);
+    ret = load_elf(buf, 0, NULL, NULL, NULL);
     if (ret < 0) {
 	fprintf(stderr, "qemu: could not load prom '%s'\n", 
 		buf);
@@ -293,7 +347,7 @@
     initrd_size = 0;
     if (linux_boot) {
         /* XXX: put correct offset */
-        kernel_size = load_elf(kernel_filename, 0, NULL);
+        kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL);
         if (kernel_size < 0)
 	    kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
 	if (kernel_size < 0)
@@ -330,27 +384,27 @@
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(&pic_set_irq_new, NULL,
-                        serial_io[i], serial_irq[i], serial_hds[i]);
+            serial_init(serial_io[i], NULL/*serial_irq[i]*/, serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
+            parallel_init(parallel_io[i], NULL/*parallel_irq[i]*/, parallel_hds[i]);
         }
     }
 
     for(i = 0; i < nb_nics; i++) {
         if (!nd_table[i].model)
             nd_table[i].model = "ne2k_pci";
-	pci_nic_init(pci_bus, &nd_table[i]);
+	pci_nic_init(pci_bus, &nd_table[i], -1);
     }
 
     pci_cmd646_ide_init(pci_bus, bs_table, 1);
-    kbd_init();
-    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
-    nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
+    /* FIXME: wire up interrupts.  */
+    i8042_init(NULL/*1*/, NULL/*12*/, 0x60);
+    floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd_table);
+    nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
     sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device,
                          KERNEL_LOAD_ADDR, kernel_size,
                          kernel_cmdline,

Modified: trunk/src/host/qemu-neo1973/hw/tcx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/tcx.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/tcx.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -26,19 +26,24 @@
 #define MAXX 1024
 #define MAXY 768
 #define TCX_DAC_NREGS 16
+#define TCX_THC_NREGS_8  0x081c
+#define TCX_THC_NREGS_24 0x1000
+#define TCX_TEC_NREGS    0x1000
 
 typedef struct TCXState {
     uint32_t addr;
     DisplayState *ds;
     uint8_t *vram;
-    ram_addr_t vram_offset;
-    uint16_t width, height;
+    uint32_t *vram24, *cplane;
+    ram_addr_t vram_offset, vram24_offset, cplane_offset;
+    uint16_t width, height, depth;
     uint8_t r[256], g[256], b[256];
     uint32_t palette[256];
     uint8_t dac_index, dac_state;
 } TCXState;
 
 static void tcx_screen_dump(void *opaque, const char *filename);
+static void tcx24_screen_dump(void *opaque, const char *filename);
 
 /* XXX: unify with vga draw line functions */
 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
@@ -121,6 +126,57 @@
     }
 }
 
+static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
+                                     const uint8_t *s, int width,
+                                     const uint32_t *cplane,
+                                     const uint32_t *s24)
+{
+    int x;
+    uint8_t val;
+    uint32_t *p = (uint32_t *)d;
+    uint32_t dval;
+
+    for(x = 0; x < width; x++, s++, s24++) {
+        if ((bswap32(*cplane++) & 0xff000000) == 0x03000000) { // 24-bit direct
+            dval = bswap32(*s24) & 0x00ffffff;
+        } else {
+            val = *s;
+            dval = s1->palette[val];
+        }
+        *p++ = dval;
+    }
+}
+
+static inline int check_dirty(TCXState *ts, ram_addr_t page, ram_addr_t page24,
+                              ram_addr_t cpage)
+{
+    int ret;
+    unsigned int off;
+
+    ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
+    for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
+        ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG);
+        ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG);
+    }
+    return ret;
+}
+
+static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
+                               ram_addr_t page_max, ram_addr_t page24,
+                              ram_addr_t cpage)
+{
+    cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
+                                    VGA_DIRTY_FLAG);
+    page_min -= ts->vram_offset;
+    page_max -= ts->vram_offset;
+    cpu_physical_memory_reset_dirty(page24 + page_min * 4,
+                                    page24 + page_max * 4 + TARGET_PAGE_SIZE,
+                                    VGA_DIRTY_FLAG);
+    cpu_physical_memory_reset_dirty(cpage + page_min * 4,
+                                    cpage + page_max * 4 + TARGET_PAGE_SIZE,
+                                    VGA_DIRTY_FLAG);
+}
+
 /* Fixed line length 1024 allows us to do nice tricks not possible on
    VGA... */
 static void tcx_update_display(void *opaque)
@@ -201,6 +257,82 @@
     }
 }
 
+static void tcx24_update_display(void *opaque)
+{
+    TCXState *ts = opaque;
+    ram_addr_t page, page_min, page_max, cpage, page24;
+    int y, y_start, dd, ds;
+    uint8_t *d, *s;
+    uint32_t *cptr, *s24;
+
+    if (ts->ds->depth != 32)
+            return;
+    page = ts->vram_offset;
+    page24 = ts->vram24_offset;
+    cpage = ts->cplane_offset;
+    y_start = -1;
+    page_min = 0xffffffff;
+    page_max = 0;
+    d = ts->ds->data;
+    s = ts->vram;
+    s24 = ts->vram24;
+    cptr = ts->cplane;
+    dd = ts->ds->linesize;
+    ds = 1024;
+
+    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
+            page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
+        if (check_dirty(ts, page, page24, cpage)) {
+            if (y_start < 0)
+                y_start = y;
+            if (page < page_min)
+                page_min = page;
+            if (page > page_max)
+                page_max = page;
+            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
+            d += dd;
+            s += ds;
+            cptr += ds;
+            s24 += ds;
+            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
+            d += dd;
+            s += ds;
+            cptr += ds;
+            s24 += ds;
+            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
+            d += dd;
+            s += ds;
+            cptr += ds;
+            s24 += ds;
+            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
+            d += dd;
+            s += ds;
+            cptr += ds;
+            s24 += ds;
+        } else {
+            if (y_start >= 0) {
+                /* flush to display */
+                dpy_update(ts->ds, 0, y_start,
+                           ts->width, y - y_start);
+                y_start = -1;
+            }
+            d += dd * 4;
+            s += ds * 4;
+            cptr += ds * 4;
+            s24 += ds * 4;
+        }
+    }
+    if (y_start >= 0) {
+        /* flush to display */
+        dpy_update(ts->ds, 0, y_start,
+                   ts->width, y - y_start);
+    }
+    /* reset modified pages */
+    if (page_min <= page_max) {
+        reset_dirty(ts, page_min, page_max, page24, cpage);
+    }
+}
+
 static void tcx_invalidate_display(void *opaque)
 {
     TCXState *s = opaque;
@@ -211,14 +343,29 @@
     }
 }
 
+static void tcx24_invalidate_display(void *opaque)
+{
+    TCXState *s = opaque;
+    int i;
+
+    tcx_invalidate_display(s);
+    for (i = 0; i < MAXX*MAXY * 4; i += TARGET_PAGE_SIZE) {
+        cpu_physical_memory_set_dirty(s->vram24_offset + i);
+        cpu_physical_memory_set_dirty(s->cplane_offset + i);
+    }
+}
+
 static void tcx_save(QEMUFile *f, void *opaque)
 {
     TCXState *s = opaque;
     
     qemu_put_be32s(f, (uint32_t *)&s->addr);
     qemu_put_be32s(f, (uint32_t *)&s->vram);
+    qemu_put_be32s(f, (uint32_t *)&s->vram24);
+    qemu_put_be32s(f, (uint32_t *)&s->cplane);
     qemu_put_be16s(f, (uint16_t *)&s->height);
     qemu_put_be16s(f, (uint16_t *)&s->width);
+    qemu_put_be16s(f, (uint16_t *)&s->depth);
     qemu_put_buffer(f, s->r, 256);
     qemu_put_buffer(f, s->g, 256);
     qemu_put_buffer(f, s->b, 256);
@@ -230,19 +377,24 @@
 {
     TCXState *s = opaque;
     
-    if (version_id != 1)
+    if (version_id != 2)
         return -EINVAL;
 
     qemu_get_be32s(f, (uint32_t *)&s->addr);
     qemu_get_be32s(f, (uint32_t *)&s->vram);
+    qemu_get_be32s(f, (uint32_t *)&s->vram24);
+    qemu_get_be32s(f, (uint32_t *)&s->cplane);
     qemu_get_be16s(f, (uint16_t *)&s->height);
     qemu_get_be16s(f, (uint16_t *)&s->width);
+    qemu_get_be16s(f, (uint16_t *)&s->depth);
     qemu_get_buffer(f, s->r, 256);
     qemu_get_buffer(f, s->g, 256);
     qemu_get_buffer(f, s->b, 256);
     qemu_get_8s(f, &s->dac_index);
     qemu_get_8s(f, &s->dac_state);
     update_palette_entries(s, 0, 256);
+    tcx_invalidate_display(s);
+
     return 0;
 }
 
@@ -257,8 +409,8 @@
     s->r[255] = s->g[255] = s->b[255] = 255;
     update_palette_entries(s, 0, 256);
     memset(s->vram, 0, MAXX*MAXY);
-    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
-                                    VGA_DIRTY_FLAG);
+    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset +
+                                    MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG);
     s->dac_index = 0;
     s->dac_state = 0;
 }
@@ -294,6 +446,7 @@
 	case 2:
 	    s->b[s->dac_index] = val >> 24;
             update_palette_entries(s, s->dac_index, s->dac_index + 1);
+            s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
 	default:
 	    s->dac_state = 0;
 	    break;
@@ -317,28 +470,85 @@
     tcx_dac_writel,
 };
 
+static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
+{
+    return 0;
+}
+
+static void tcx_dummy_writel(void *opaque, target_phys_addr_t addr,
+                             uint32_t val)
+{
+}
+
+static CPUReadMemoryFunc *tcx_dummy_read[3] = {
+    tcx_dummy_readl,
+    tcx_dummy_readl,
+    tcx_dummy_readl,
+};
+
+static CPUWriteMemoryFunc *tcx_dummy_write[3] = {
+    tcx_dummy_writel,
+    tcx_dummy_writel,
+    tcx_dummy_writel,
+};
+
 void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
-	      unsigned long vram_offset, int vram_size, int width, int height)
+              unsigned long vram_offset, int vram_size, int width, int height,
+              int depth)
 {
     TCXState *s;
-    int io_memory;
+    int io_memory, dummy_memory;
+    int size;
 
     s = qemu_mallocz(sizeof(TCXState));
     if (!s)
         return;
     s->ds = ds;
     s->addr = addr;
-    s->vram = vram_base;
     s->vram_offset = vram_offset;
     s->width = width;
     s->height = height;
+    s->depth = depth;
 
-    cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);
+    // 8-bit plane
+    s->vram = vram_base;
+    size = vram_size;
+    cpu_register_physical_memory(addr + 0x00800000, size, vram_offset);
+    vram_offset += size;
+    vram_base += size;
+
     io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
-    cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);
+    cpu_register_physical_memory(addr + 0x00200000, TCX_DAC_NREGS, io_memory);
 
-    graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
-                         tcx_screen_dump, s);
+    dummy_memory = cpu_register_io_memory(0, tcx_dummy_read, tcx_dummy_write,
+                                          s);
+    cpu_register_physical_memory(addr + 0x00700000, TCX_TEC_NREGS,
+                                 dummy_memory);
+    if (depth == 24) {
+        // 24-bit plane
+        size = vram_size * 4;
+        s->vram24 = (uint32_t *)vram_base;
+        s->vram24_offset = vram_offset;
+        cpu_register_physical_memory(addr + 0x02000000, size, vram_offset);
+        vram_offset += size;
+        vram_base += size;
+
+        // Control plane
+        size = vram_size * 4;
+        s->cplane = (uint32_t *)vram_base;
+        s->cplane_offset = vram_offset;
+        cpu_register_physical_memory(addr + 0x0a000000, size, vram_offset);
+        cpu_register_physical_memory(addr + 0x00301000, TCX_THC_NREGS_24,
+                                     dummy_memory);
+        graphic_console_init(s->ds, tcx24_update_display,
+                             tcx24_invalidate_display, tcx24_screen_dump, s);
+    } else {
+        cpu_register_physical_memory(addr + 0x00300000, TCX_THC_NREGS_8,
+                                     dummy_memory);
+        graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
+                             tcx_screen_dump, s);
+    }
+
     register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
     qemu_register_reset(tcx_reset, s);
     tcx_reset(s);
@@ -372,5 +582,38 @@
     return;
 }
 
+static void tcx24_screen_dump(void *opaque, const char *filename)
+{
+    TCXState *s = opaque;
+    FILE *f;
+    uint8_t *d, *d1, v;
+    uint32_t *s24, *cptr, dval;
+    int y, x;
 
-
+    f = fopen(filename, "wb");
+    if (!f)
+        return;
+    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
+    d1 = s->vram;
+    s24 = s->vram24;
+    cptr = s->cplane;
+    for(y = 0; y < s->height; y++) {
+        d = d1;
+        for(x = 0; x < s->width; x++, d++, s24++) {
+            if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
+                dval = *s24 & 0x00ffffff;
+                fputc((dval >> 16) & 0xff, f);
+                fputc((dval >> 8) & 0xff, f);
+                fputc(dval & 0xff, f);
+            } else {
+                v = *d;
+                fputc(s->r[v], f);
+                fputc(s->g[v], f);
+                fputc(s->b[v], f);
+            }
+        }
+        d1 += MAXX;
+    }
+    fclose(f);
+    return;
+}

Modified: trunk/src/host/qemu-neo1973/hw/unin_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/unin_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/unin_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -146,12 +146,12 @@
     return (irq_num + (pci_dev->devfn >> 3)) & 3;
 }
 
-static void pci_unin_set_irq(void *pic, int irq_num, int level)
+static void pci_unin_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    openpic_set_irq(pic, irq_num + 8, level);
+    qemu_set_irq(pic[irq_num + 8], level);
 }
 
-PCIBus *pci_pmac_init(void *pic)
+PCIBus *pci_pmac_init(qemu_irq *pic)
 {
     UNINState *s;
     PCIDevice *d;

Modified: trunk/src/host/qemu-neo1973/hw/usb-hid.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-hid.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb-hid.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -46,7 +46,7 @@
 static const uint8_t qemu_mouse_dev_descriptor[] = {
 	0x12,       /*  u8 bLength; */
 	0x01,       /*  u8 bDescriptorType; Device */
-	0x10, 0x00, /*  u16 bcdUSB; v1.0 */
+	0x00, 0x01, /*  u16 bcdUSB; v1.0 */
 
 	0x00,	    /*  u8  bDeviceClass; */
 	0x00,	    /*  u8  bDeviceSubClass; */
@@ -170,7 +170,7 @@
 	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
  	0x03,       /*  u8  ep_bmAttributes; Interrupt */
  	0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
-	0x03,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
 };
 
 static const uint8_t qemu_mouse_hid_report_descriptor[] = {

Modified: trunk/src/host/qemu-neo1973/hw/usb-msd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-msd.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb-msd.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -66,7 +66,7 @@
 static const uint8_t qemu_msd_dev_descriptor[] = {
 	0x12,       /*  u8 bLength; */
 	0x01,       /*  u8 bDescriptorType; Device */
-	0x10, 0x00, /*  u16 bcdUSB; v1.0 */
+	0x00, 0x01, /*  u16 bcdUSB; v1.0 */
 
 	0x00,	    /*  u8  bDeviceClass; */
 	0x00,	    /*  u8  bDeviceSubClass; */

Modified: trunk/src/host/qemu-neo1973/hw/usb-net.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-net.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb-net.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -111,7 +111,7 @@
 	STRING_MANUFACTURER, /*  u8  iManufacturer; */
 	STRING_PRODUCT,      /*  u8  iProduct; */
 	STRING_SERIALNUMBER, /*  u8  iSerialNumber; */
-	0x01                 /*  u8  bNumConfigurations; */
+	0x02                 /*  u8  bNumConfigurations; */
 };
 
 static const uint8_t qemu_net_rndis_config_descriptor[] = {
@@ -195,8 +195,8 @@
 	USB_DT_CONFIG,       /*  u8  bDescriptorType */
         0x50, 0x00,          /*  le16 wTotalLength */
         0x02,                /*  u8  bNumInterfaces */
-        DEV_RNDIS_CONFIG_VALUE, /*  u8  bConfigurationValue */
-        STRING_RNDIS,        /*  u8  iConfiguration */
+        DEV_CONFIG_VALUE,    /*  u8  bConfigurationValue */
+        STRING_CDC,          /*  u8  iConfiguration */
         0xc0,                /*  u8  bmAttributes */
         0x32,                /*  u8  bMaxPower */
 	/* CDC Control Interface */
@@ -972,12 +972,12 @@
 
 		case USB_DT_CONFIG:
 			switch (value & 0xff) {
-			case 1:
+			case 0:
 				ret = sizeof(qemu_net_rndis_config_descriptor);
 				memcpy(data, qemu_net_rndis_config_descriptor, ret);
 				break;
 
-			case 0:
+			case 1:
 				ret = sizeof(qemu_net_cdc_config_descriptor);
 				memcpy(data, qemu_net_cdc_config_descriptor, ret);
 				break;

Modified: trunk/src/host/qemu-neo1973/hw/usb-ohci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-ohci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb-ohci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -53,12 +53,14 @@
     uint32_t ctrl;
 } OHCIPort;
 
-typedef void (*ohci_irq_service_t)(void *opaque, int irq, int level);
+enum ohci_type {
+    OHCI_TYPE_PCI,
+    OHCI_TYPE_MEMIO
+};
 
 typedef struct {
-    void *pic;
-    int irq;
-    ohci_irq_service_t set_irq;
+    qemu_irq irq;
+    enum ohci_type type;
     target_phys_addr_t mem_base;
     int mem;
     int num_ports;
@@ -279,7 +281,7 @@
         (ohci->intr_status & ohci->intr))
         level = 1;
 
-    ohci->set_irq(ohci->pic, ohci->irq, level);
+    qemu_set_irq(ohci->irq, level);
 }
 
 /* Set an interrupt */
@@ -1257,7 +1259,7 @@
 };
 
 static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn,
-            void *pic, int irq, ohci_irq_service_t set_irq, const char *name)
+            qemu_irq irq, enum ohci_type type, const char *name)
 {
     int i;
 
@@ -1280,9 +1282,8 @@
     ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci);
     ohci->name = name;
 
-    ohci->pic = pic;
     ohci->irq = irq;
-    ohci->set_irq = set_irq;
+    ohci->type = type;
 
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
@@ -1328,20 +1329,20 @@
     ohci->pci_dev.config[0x0b] = 0xc;
     ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
 
-    usb_ohci_init(&ohci->state, num_ports, devfn, &ohci->pci_dev,
-                  0, (ohci_irq_service_t) pci_set_irq, ohci->pci_dev.name);
+    usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0],
+                  OHCI_TYPE_PCI, ohci->pci_dev.name);
 
     pci_register_io_region((struct PCIDevice *)ohci, 0, 256,
                            PCI_ADDRESS_SPACE_MEM, ohci_mapfunc);
 }
 
 void usb_ohci_init_memio(target_phys_addr_t base, int num_ports, int devfn,
-            void *pic, int irq)
+                         qemu_irq irq)
 {
     OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState));
 
-    usb_ohci_init(ohci, num_ports, devfn, pic, irq,
-                  pic_set_irq_new, "OHCI USB");
+    usb_ohci_init(ohci, num_ports, devfn, irq,
+                  OHCI_TYPE_MEMIO, "OHCI USB");
     ohci->mem_base = base;
 
     cpu_register_physical_memory(ohci->mem_base, 0xfff, ohci->mem);

Modified: trunk/src/host/qemu-neo1973/hw/usb-uhci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-uhci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb-uhci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -26,6 +26,8 @@
 //#define DEBUG
 //#define DEBUG_PACKET
 
+#define UHCI_CMD_FGR      (1 << 4)
+#define UHCI_CMD_EGSM     (1 << 3)
 #define UHCI_CMD_GRESET   (1 << 2)
 #define UHCI_CMD_HCRESET  (1 << 1)
 #define UHCI_CMD_RS       (1 << 0)
@@ -87,7 +89,7 @@
        is to allow multiple pending requests.  */
     uint32_t async_qh;
     USBPacket usb_packet;
-    uint8_t usb_buf[1280];
+    uint8_t usb_buf[2048];
 } UHCIState;
 
 typedef struct UHCI_TD {
@@ -117,7 +119,7 @@
     } else {
         level = 0;
     }
-    pci_set_irq(&s->dev, 3, level);
+    qemu_set_irq(s->dev.irq[3], level);
 }
 
 static void uhci_reset(UHCIState *s)
@@ -327,6 +329,21 @@
     return val;
 }
 
+/* signal resume if controller suspended */
+static void uhci_resume (void *opaque)
+{
+    UHCIState *s = (UHCIState *)opaque;
+
+    if (!s)
+        return;
+
+    if (s->cmd & UHCI_CMD_EGSM) {
+        s->cmd |= UHCI_CMD_FGR;
+        s->status |= UHCI_STS_RD;
+        uhci_update_irq(s);
+    }
+}
+
 static void uhci_attach(USBPort *port1, USBDevice *dev)
 {
     UHCIState *s = port1->opaque;
@@ -344,6 +361,9 @@
             port->ctrl |= UHCI_PORT_LSDA;
         else
             port->ctrl &= ~UHCI_PORT_LSDA;
+
+        uhci_resume(s);
+
         port->port.dev = dev;
         /* send the attach message */
         usb_send_msg(dev, USB_MSG_ATTACH);
@@ -358,6 +378,9 @@
             port->ctrl &= ~UHCI_PORT_EN;
             port->ctrl |= UHCI_PORT_ENC;
         }
+
+        uhci_resume(s);
+
         dev = port->port.dev;
         if (dev) {
             /* send the detach message */

Modified: trunk/src/host/qemu-neo1973/hw/usb.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/usb.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -164,7 +164,7 @@
     USBCallback *complete_cb;
     void *complete_opaque;
     USBCallback *cancel_cb;
-    void * *cancel_opaque;
+    void *cancel_opaque;
 };
 
 /* Defer completion of a USB packet.  The hadle_packet routine should then
@@ -209,7 +209,7 @@
 /* usb-ohci.c */
 void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn);
 void usb_ohci_init_memio(target_phys_addr_t base, int num_ports, int devfn,
-                         void *pic, int irq);
+                         qemu_irq irq);
 
 /* usb-linux.c */
 USBDevice *usb_host_device_open(const char *devname);
@@ -225,6 +225,3 @@
 
 /* usb-msd.c */
 USBDevice *usb_msd_init(const char *filename);
-
-/* usb-net.c */
-USBDevice *usb_net_init(NICInfo *nd);

Modified: trunk/src/host/qemu-neo1973/hw/versatile_pci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/versatile_pci.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/versatile_pci.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -84,12 +84,12 @@
     return irq_num;
 }
 
-static void pci_vpb_set_irq(void *pic, int irq_num, int level)
+static void pci_vpb_set_irq(qemu_irq *pic, int irq_num, int level)
 {
-    pic_set_irq_new(pic, pci_vpb_irq + irq_num, level);
+    qemu_set_irq(pic[pci_vpb_irq + irq_num], level);
 }
 
-PCIBus *pci_vpb_init(void *pic, int irq, int realview)
+PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview)
 {
     PCIBus *s;
     PCIDevice *d;

Modified: trunk/src/host/qemu-neo1973/hw/versatilepb.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/versatilepb.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/versatilepb.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /* 
  * ARM Versatile Platform/Application Baseboard System emulation.
  *
- * Copyright (c) 2005-2006 CodeSourcery.
+ * Copyright (c) 2005-2007 CodeSourcery.
  * Written by Paul Brook
  *
  * This code is licenced under the GPL.
@@ -14,12 +14,11 @@
 
 typedef struct vpb_sic_state
 {
-  arm_pic_handler handler;
   uint32_t base;
   uint32_t level;
   uint32_t mask;
   uint32_t pic_enable;
-  void *parent;
+  qemu_irq *parent;
   int irq;
 } vpb_sic_state;
 
@@ -28,7 +27,7 @@
     uint32_t flags;
 
     flags = s->level & s->mask;
-    pic_set_irq_new(s->parent, s->irq, flags != 0);
+    qemu_set_irq(s->parent[s->irq], flags != 0);
 }
 
 static void vpb_sic_update_pic(vpb_sic_state *s)
@@ -40,7 +39,7 @@
         mask = 1u << i;
         if (!(s->pic_enable & mask))
             continue;
-        pic_set_irq_new(s->parent, i, (s->level & mask) != 0);
+        qemu_set_irq(s->parent[i], (s->level & mask) != 0);
     }
 }
 
@@ -52,7 +51,7 @@
     else
         s->level &= ~(1u << irq);
     if (s->pic_enable & (1u << irq))
-        pic_set_irq_new(s->parent, irq, level);
+        qemu_set_irq(s->parent[irq], level);
     vpb_sic_update(s);
 }
 
@@ -126,15 +125,16 @@
    vpb_sic_write
 };
 
-static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq)
+static qemu_irq *vpb_sic_init(uint32_t base, qemu_irq *parent, int irq)
 {
     vpb_sic_state *s;
+    qemu_irq *qi;
     int iomemtype;
 
     s = (vpb_sic_state *)qemu_mallocz(sizeof(vpb_sic_state));
     if (!s)
         return NULL;
-    s->handler = vpb_sic_set_irq;
+    qi = qemu_allocate_irqs(vpb_sic_set_irq, s, 32);
     s->base = base;
     s->parent = parent;
     s->irq = irq;
@@ -142,7 +142,7 @@
                                        vpb_sic_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     /* ??? Save/restore.  */
-    return s;
+    return qi;
 }
 
 /* Board init.  */
@@ -154,11 +154,12 @@
 static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename, int board_id)
+                     const char *initrd_filename, const char *cpu_model,
+                     int board_id)
 {
     CPUState *env;
-    void *pic;
-    void *sic;
+    qemu_irq *pic;
+    qemu_irq *sic;
     void *scsi_hba;
     PCIBus *pci_bus;
     NICInfo *nd;
@@ -166,17 +167,19 @@
     int done_smc = 0;
 
     env = cpu_init();
-    cpu_arm_set_model(env, ARM_CPUID_ARM926);
+    if (!cpu_model)
+        cpu_model = "arm926";
+    cpu_arm_set_model(env, cpu_model);
     /* ??? RAM shoud repeat to fill physical memory space.  */
     /* SDRAM at address zero.  */
     cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
 
     arm_sysctl_init(0x10000000, 0x41007004);
     pic = arm_pic_init_cpu(env);
-    pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
+    pic = pl190_init(0x10140000, pic[0], pic[1]);
     sic = vpb_sic_init(0x10003000, pic, 31);
-    pl050_init(0x10006000, sic, 3, 0);
-    pl050_init(0x10007000, sic, 4, 1);
+    pl050_init(0x10006000, sic[3], 0);
+    pl050_init(0x10007000, sic[4], 1);
 
     pci_bus = pci_vpb_init(sic, 27, 0);
     /* The Versatile PCI bridge does not provide access to PCI IO space,
@@ -186,9 +189,9 @@
         if (!nd->model)
             nd->model = done_smc ? "rtl8139" : "smc91c111";
         if (strcmp(nd->model, "smc91c111") == 0) {
-            smc91c111_init(nd, 0x10010000, sic, 25);
+            smc91c111_init(nd, 0x10010000, sic[25]);
         } else {
-            pci_nic_init(pci_bus, nd);
+            pci_nic_init(pci_bus, nd, -1);
         }
     }
     if (usb_enabled) {
@@ -201,32 +204,38 @@
         }
     }
 
-    pl011_init(0x101f1000, pic, 12, serial_hds[0]);
-    pl011_init(0x101f2000, pic, 13, serial_hds[1]);
-    pl011_init(0x101f3000, pic, 14, serial_hds[2]);
-    pl011_init(0x10009000, sic, 6, serial_hds[3]);
+    pl011_init(0x101f1000, pic[12], serial_hds[0]);
+    pl011_init(0x101f2000, pic[13], serial_hds[1]);
+    pl011_init(0x101f3000, pic[14], serial_hds[2]);
+    pl011_init(0x10009000, sic[6], serial_hds[3]);
 
-    pl080_init(0x10130000, pic, 17, 8);
-    sp804_init(0x101e2000, pic, 4);
-    sp804_init(0x101e3000, pic, 5);
+    pl080_init(0x10130000, pic[17], 8);
+    sp804_init(0x101e2000, pic[4]);
+    sp804_init(0x101e3000, pic[5]);
 
     /* The versatile/PB actually has a modified Color LCD controller
        that includes hardware cursor support from the PL111.  */
-    pl110_init(ds, 0x10120000, pic, 16, 1);
+    pl110_init(ds, 0x10120000, pic[16], 1);
 
+    pl181_init(0x10005000, sd_bdrv, sic[22], sic[1]);
+#if 0
+    /* Disabled because there's no way of specifying a block device.  */
+    pl181_init(0x1000b000, NULL, sic, 23, 2);
+#endif
+
     /* Memory map for Versatile/PB:  */
     /* 0x10000000 System registers.  */
     /* 0x10001000 PCI controller config registers.  */
     /* 0x10002000 Serial bus interface.  */
     /*  0x10003000 Secondary interrupt controller.  */
     /* 0x10004000 AACI (audio).  */
-    /* 0x10005000 MMCI0.  */
+    /*  0x10005000 MMCI0.  */
     /*  0x10006000 KMI0 (keyboard).  */
     /*  0x10007000 KMI1 (mouse).  */
     /* 0x10008000 Character LCD Interface.  */
     /*  0x10009000 UART3.  */
     /* 0x1000a000 Smart card 1.  */
-    /* 0x1000b000 MMCI1.  */
+    /*  0x1000b000 MMCI1.  */
     /*  0x10010000 Ethernet.  */
     /* 0x10020000 USB.  */
     /* 0x10100000 SSMC.  */
@@ -250,30 +259,30 @@
     /*  0x101f3000 UART2.  */
     /* 0x101f4000 SSPI.  */
 
-    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
+    arm_load_kernel(env, ram_size, kernel_filename, kernel_cmdline,
                     initrd_filename, board_id, 0x0);
 }
 
 static void vpb_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename)
+                     const char *initrd_filename, const char *cpu_model)
 {
     versatile_init(ram_size, vga_ram_size, boot_device,
                    ds, fd_filename, snapshot,
                    kernel_filename, kernel_cmdline,
-                   initrd_filename, 0x183);
+                   initrd_filename, cpu_model, 0x183);
 }
 
 static void vab_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename)
+                     const char *initrd_filename, const char *cpu_model)
 {
     versatile_init(ram_size, vga_ram_size, boot_device,
                    ds, fd_filename, snapshot,
                    kernel_filename, kernel_cmdline,
-                   initrd_filename, 0x25e);
+                   initrd_filename, cpu_model, 0x25e);
 }
 
 QEMUMachine versatilepb_machine = {

Modified: trunk/src/host/qemu-neo1973/hw/vga.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vga.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/vga.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1788,12 +1788,13 @@
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
     s->get_resolution = vga_get_resolution;
-    graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
-                         vga_screen_dump, s);
+    s->update = vga_update_display;
+    s->invalidate = vga_invalidate_display;
+    s->screen_dump = vga_screen_dump;
 }
 
 /* used by both ISA and PCI */
-static void vga_init(VGAState *s)
+void vga_init(VGAState *s)
 {
     int vga_io_memory;
 
@@ -1844,6 +1845,81 @@
                                  vga_io_memory);
 }
 
+/* Memory mapped interface */
+static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
+}
+
+static void vga_mm_writeb (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
+}
+
+static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
+}
+
+static void vga_mm_writew (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
+}
+
+static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
+}
+
+static void vga_mm_writel (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
+    &vga_mm_readb,
+    &vga_mm_readw,
+    &vga_mm_readl,
+};
+
+static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
+    &vga_mm_writeb,
+    &vga_mm_writew,
+    &vga_mm_writel,
+};
+
+static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
+                        target_phys_addr_t ctrl_base, int it_shift)
+{
+    int s_ioport_ctrl, vga_io_memory;
+
+    s->base_ctrl = ctrl_base;
+    s->it_shift = it_shift;
+    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
+    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
+
+    register_savevm("vga", 0, 2, vga_save, vga_load, s);
+
+    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
+    s->bank_offset = 0;
+    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
+}
+
 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
                  unsigned long vga_ram_offset, int vga_ram_size)
 {
@@ -1856,6 +1932,8 @@
     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     vga_init(s);
 
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
 #ifdef CONFIG_BOCHS_VBE
     /* XXX: use optimized standard vga accesses */
     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
@@ -1864,6 +1942,30 @@
     return 0;
 }
 
+int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
+                    unsigned long vga_ram_offset, int vga_ram_size,
+                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
+                    int it_shift)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_mm_init(s, vram_base, ctrl_base, it_shift);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
+#ifdef CONFIG_BOCHS_VBE
+    /* XXX: use optimized standard vga accesses */
+    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                 vga_ram_size, vga_ram_offset);
+#endif
+    return 0;
+}
+
 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
                  unsigned long vga_ram_offset, int vga_ram_size,
                  unsigned long vga_bios_offset, int vga_bios_size)
@@ -1881,6 +1983,9 @@
     
     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
     vga_init(s);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
     s->pci_dev = &d->dev;
     
     pci_conf = d->dev.config;

Modified: trunk/src/host/qemu-neo1973/hw/vga_int.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vga_int.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/vga_int.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -85,6 +85,8 @@
     unsigned int vram_size;                                             \
     unsigned long bios_offset;                                          \
     unsigned int bios_size;                                             \
+    target_phys_addr_t base_ctrl;                                       \
+    int it_shift;                                                       \
     PCIDevice *pci_dev;                                                 \
     uint32_t latch;                                                     \
     uint8_t sr_index;                                                   \
@@ -134,6 +136,9 @@
     uint32_t cursor_offset;                                             \
     unsigned int (*rgb_to_pixel)(unsigned int r,                        \
                                  unsigned int g, unsigned b);           \
+    vga_hw_update_ptr update;                                           \
+    vga_hw_invalidate_ptr invalidate;                                   \
+    vga_hw_screen_dump_ptr screen_dump;                                 \
     /* hardware mouse cursor support */                                 \
     uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32];                  \
     void (*cursor_invalidate)(struct VGAState *s);                      \
@@ -157,6 +162,7 @@
 
 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
                      unsigned long vga_ram_offset, int vga_ram_size);
+void vga_init(VGAState *s);
 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGAState *s, int y1, int y2);

Added: trunk/src/host/qemu-neo1973/hw/vmmouse.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vmmouse.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/vmmouse.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,300 @@
+/*
+ * QEMU VMMouse emulation
+ * 
+ * Copyright (C) 2007 Anthony Liguori <anthony at codemonkey.ws>
+ * 
+ * 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 "vl.h"
+
+/* debug only vmmouse */
+//#define DEBUG_VMMOUSE
+
+/* VMMouse Commands */
+#define VMMOUSE_GETVERSION	10
+#define VMMOUSE_DATA		39
+#define VMMOUSE_STATUS		40
+#define VMMOUSE_COMMAND		41
+
+#define VMMOUSE_READ_ID			0x45414552
+#define VMMOUSE_DISABLE			0x000000f5
+#define VMMOUSE_REQUEST_RELATIVE	0x4c455252
+#define VMMOUSE_REQUEST_ABSOLUTE	0x53424152
+
+#define VMMOUSE_QUEUE_SIZE	1024
+
+#define VMMOUSE_MAGIC		0x564D5868
+#define VMMOUSE_VERSION		0x3442554a
+
+#ifdef DEBUG_VMMOUSE
+#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+typedef struct _VMMouseState
+{
+    uint32_t queue[VMMOUSE_QUEUE_SIZE];
+    uint16_t nb_queue;
+    uint16_t status;
+    uint8_t absolute;
+    QEMUPutMouseEntry *entry;
+    void *ps2_mouse;
+} VMMouseState;
+
+static uint32_t vmmouse_get_version(VMMouseState *s, uint32_t *magic)
+{
+    DPRINTF("vmmouse_get_version(%x)\n", *magic);
+    *magic = VMMOUSE_MAGIC;
+    return VMMOUSE_VERSION;
+}
+
+static uint32_t vmmouse_get_status(VMMouseState *s)
+{
+    DPRINTF("vmmouse_get_status()\n");
+    return (s->status << 16) | s->nb_queue;
+}
+
+static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_state)
+{
+    VMMouseState *s = opaque;
+    int buttons = 0;
+
+    if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
+	return;
+
+    DPRINTF("vmmouse_mouse_event(%d, %d, %d, %d)\n",
+	    x, y, dz, buttons_state);
+
+    if ((buttons_state & MOUSE_EVENT_LBUTTON))
+	buttons |= 0x20;
+    if ((buttons_state & MOUSE_EVENT_RBUTTON))
+	buttons |= 0x10;
+    if ((buttons_state & MOUSE_EVENT_MBUTTON))
+	buttons |= 0x08;
+
+    if (s->absolute) {
+	x <<= 1;
+	y <<= 1;
+    }
+
+    s->queue[s->nb_queue++] = buttons;
+    s->queue[s->nb_queue++] = x;
+    s->queue[s->nb_queue++] = y;
+    s->queue[s->nb_queue++] = dz;
+
+    /* need to still generate PS2 events to notify driver to
+       read from queue */
+    ps2_mouse_fake_event(s->ps2_mouse);
+}
+
+static void vmmouse_update_handler(VMMouseState *s)
+{
+    if (s->entry) {
+	qemu_remove_mouse_event_handler(s->entry);
+	s->entry = NULL;
+    }
+    if (s->status == 0)
+	s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
+						s, s->absolute,
+						"vmmouse");
+}
+
+static void vmmouse_read_id(VMMouseState *s)
+{
+    DPRINTF("vmmouse_read_id()\n");
+
+    if (s->nb_queue == VMMOUSE_QUEUE_SIZE)
+	return;
+
+    s->queue[s->nb_queue++] = VMMOUSE_VERSION;
+    s->status = 0;
+    vmmouse_update_handler(s);
+}
+
+static void vmmouse_request_relative(VMMouseState *s)
+{
+    DPRINTF("vmmouse_request_relative()\n");
+    s->absolute = 0;
+    vmmouse_update_handler(s);
+}
+
+static void vmmouse_request_absolute(VMMouseState *s)
+{
+    DPRINTF("vmmouse_request_absolute()\n");
+    s->absolute = 1;
+    vmmouse_update_handler(s);
+}
+
+static void vmmouse_disable(VMMouseState *s)
+{
+    DPRINTF("vmmouse_disable()\n");
+    s->status = 0xffff;
+    vmmouse_update_handler(s);
+}
+
+static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
+{
+    int i;
+
+    DPRINTF("vmmouse_data(%d)\n", size);
+
+    if (size == 0 || size > 6 || size > s->nb_queue) {
+	printf("vmmouse: driver requested too much data %d\n", size);
+	s->status = 0xffff;
+	vmmouse_update_handler(s);
+	return;
+    }
+
+    for (i = 0; i < size; i++)
+	data[i] = s->queue[i];
+
+    s->nb_queue -= size;
+    if (s->nb_queue)
+	memmove(s->queue, &s->queue[size], sizeof(s->queue[0]) * s->nb_queue);
+}
+
+static void vmmouse_get_data(uint32_t *data)
+{
+    CPUState *env = cpu_single_env;
+
+    data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
+    data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
+    data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI];
+
+    DPRINTF("get_data = {%x, %x, %x, %x, %x, %x}\n",
+	    data[0], data[1], data[2], data[3], data[4], data[5]);
+}
+
+static void vmmouse_set_data(const uint32_t *data)
+{
+    CPUState *env = cpu_single_env;
+
+    DPRINTF("set_data = {%x, %x, %x, %x, %x, %x}\n",
+	    data[0], data[1], data[2], data[3], data[4], data[5]);
+
+    env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
+    env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
+    env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5];
+}
+
+static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr)
+{
+    VMMouseState *s = opaque;
+    uint32_t data[6];
+    uint16_t command;
+
+    vmmouse_get_data(data);
+    if (data[0] != VMMOUSE_MAGIC)
+	goto error;
+
+    command = data[2] & 0xFFFF;
+
+    switch (command) {
+    case VMMOUSE_GETVERSION:
+	data[0] = vmmouse_get_version(s, &data[1]);
+	break;
+    case VMMOUSE_STATUS:
+	data[0] = vmmouse_get_status(s);
+	break;
+    case VMMOUSE_COMMAND:
+	switch (data[1]) {
+	case VMMOUSE_DISABLE:
+	    vmmouse_disable(s);
+	    break;
+	case VMMOUSE_READ_ID:
+	    vmmouse_read_id(s);
+	    break;
+	case VMMOUSE_REQUEST_RELATIVE:
+	    vmmouse_request_relative(s);
+	    break;
+	case VMMOUSE_REQUEST_ABSOLUTE:
+	    vmmouse_request_absolute(s);
+	    break;
+	default:
+	    printf("vmmouse: unknown command %x\n", data[1]);
+	    break;
+	}
+	break;
+    case VMMOUSE_DATA:
+	vmmouse_data(s, data, data[1]);
+	break;
+    default:
+	printf("vmmouse: unknown command %x\n", command);
+	break;
+    }
+
+error:
+    vmmouse_set_data(data);
+    return data[0];
+}
+
+static void vmmouse_save(QEMUFile *f, void *opaque)
+{
+    VMMouseState *s = opaque;
+    int i;
+
+    qemu_put_be32(f, VMMOUSE_QUEUE_SIZE);
+    for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
+	qemu_put_be32s(f, &s->queue[i]);
+    qemu_put_be16s(f, &s->nb_queue);
+    qemu_put_be16s(f, &s->status);
+    qemu_put_8s(f, &s->absolute);
+}
+
+static int vmmouse_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VMMouseState *s = opaque;
+    int i;
+
+    if (version_id != 0)
+        return -EINVAL;
+
+    if (qemu_get_be32(f) != VMMOUSE_QUEUE_SIZE)
+	return -EINVAL;
+    for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
+	qemu_get_be32s(f, &s->queue[i]);
+    qemu_get_be16s(f, &s->nb_queue);
+    qemu_get_be16s(f, &s->status);
+    qemu_get_8s(f, &s->absolute);
+
+    vmmouse_update_handler(s);
+
+    return 0;
+}
+
+void *vmmouse_init(void *m)
+{
+    VMMouseState *s = NULL;
+
+    DPRINTF("vmmouse_init\n");
+
+    s = qemu_mallocz(sizeof(VMMouseState));
+    if (!s)
+	return NULL;
+
+    s->status = 0xffff;
+    s->ps2_mouse = m;
+
+    register_ioport_read(0x5658, 1, 4, vmmouse_ioport_read, s);
+    register_savevm("vmmouse", 0, 0, vmmouse_save, vmmouse_load, s);
+
+    return s;
+}
+

Added: trunk/src/host/qemu-neo1973/hw/vmware_vga.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/vmware_vga.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/vmware_vga.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1187 @@
+/*
+ * QEMU VMware-SVGA "chipset".
+ *
+ * Copyright (c) 2007 Andrzej Zaborowski  <balrog at zabor.org>
+ *
+ * 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 "vl.h"
+
+#define VERBOSE
+#define EMBED_STDVGA
+#undef DIRECT_VRAM
+#define HW_RECT_ACCEL
+#define HW_FILL_ACCEL
+#define HW_MOUSE_ACCEL
+
+#ifdef EMBED_STDVGA
+# include "vga_int.h"
+#endif
+
+struct vmsvga_state_s {
+#ifdef EMBED_STDVGA
+    VGA_STATE_COMMON
+#endif
+
+    int width;
+    int height;
+    int invalidated;
+    int depth;
+    int bypp;
+    int enable;
+    int config;
+    struct {
+        int id;
+        int x;
+        int y;
+        int on;
+    } cursor;
+
+#ifndef EMBED_STDVGA
+    DisplayState *ds;
+    int vram_size;
+#endif
+    uint8_t *vram;
+
+    int index;
+    int scratch_size;
+    uint32_t *scratch;
+    int new_width;
+    int new_height;
+    uint32_t guest;
+    uint32_t svgaid;
+    uint32_t wred;
+    uint32_t wgreen;
+    uint32_t wblue;
+    int syncing;
+    int fb_size;
+
+    union {
+        uint32_t *fifo;
+        struct __attribute__((__packed__)) {
+            uint32_t min;
+            uint32_t max;
+            uint32_t next_cmd;
+            uint32_t stop;
+            /* Add registers here when adding capabilities.  */
+            uint32_t fifo[0];
+        } *cmd;
+    };
+
+#define REDRAW_FIFO_LEN	512
+    struct vmsvga_rect_s {
+        int x, y, w, h;
+    } redraw_fifo[REDRAW_FIFO_LEN];
+    int redraw_fifo_first, redraw_fifo_last;
+};
+
+struct pci_vmsvga_state_s {
+    PCIDevice card;
+    struct vmsvga_state_s chip;
+};
+
+#define SVGA_MAGIC		0x900000UL
+#define SVGA_MAKE_ID(ver)	(SVGA_MAGIC << 8 | (ver))
+#define SVGA_ID_0		SVGA_MAKE_ID(0)
+#define SVGA_ID_1		SVGA_MAKE_ID(1)
+#define SVGA_ID_2		SVGA_MAKE_ID(2)
+
+#define SVGA_LEGACY_BASE_PORT	0x4560
+#define SVGA_INDEX_PORT		0x0
+#define SVGA_VALUE_PORT		0x1
+#define SVGA_BIOS_PORT		0x2
+
+#define SVGA_VERSION_2
+
+#ifdef SVGA_VERSION_2
+# define SVGA_ID		SVGA_ID_2
+# define SVGA_IO_BASE		SVGA_LEGACY_BASE_PORT
+# define SVGA_IO_MUL		1
+# define SVGA_FIFO_SIZE		0x10000
+# define SVGA_MEM_BASE		0xe0000000
+# define SVGA_PCI_DEVICE_ID	PCI_DEVICE_ID_VMWARE_SVGA2
+#else
+# define SVGA_ID		SVGA_ID_1
+# define SVGA_IO_BASE		SVGA_LEGACY_BASE_PORT
+# define SVGA_IO_MUL		4
+# define SVGA_FIFO_SIZE		0x10000
+# define SVGA_MEM_BASE		0xe0000000
+# define SVGA_PCI_DEVICE_ID	PCI_DEVICE_ID_VMWARE_SVGA
+#endif
+
+enum {
+    /* ID 0, 1 and 2 registers */
+    SVGA_REG_ID = 0,
+    SVGA_REG_ENABLE = 1,
+    SVGA_REG_WIDTH = 2,
+    SVGA_REG_HEIGHT = 3,
+    SVGA_REG_MAX_WIDTH = 4,
+    SVGA_REG_MAX_HEIGHT = 5,
+    SVGA_REG_DEPTH = 6,
+    SVGA_REG_BITS_PER_PIXEL = 7,	/* Current bpp in the guest */
+    SVGA_REG_PSEUDOCOLOR = 8,
+    SVGA_REG_RED_MASK = 9,
+    SVGA_REG_GREEN_MASK = 10,
+    SVGA_REG_BLUE_MASK = 11,
+    SVGA_REG_BYTES_PER_LINE = 12,
+    SVGA_REG_FB_START = 13,
+    SVGA_REG_FB_OFFSET = 14,
+    SVGA_REG_VRAM_SIZE = 15,
+    SVGA_REG_FB_SIZE = 16,
+
+    /* ID 1 and 2 registers */
+    SVGA_REG_CAPABILITIES = 17,
+    SVGA_REG_MEM_START = 18,		/* Memory for command FIFO */
+    SVGA_REG_MEM_SIZE = 19,
+    SVGA_REG_CONFIG_DONE = 20,		/* Set when memory area configured */
+    SVGA_REG_SYNC = 21,			/* Write to force synchronization */
+    SVGA_REG_BUSY = 22,			/* Read to check if sync is done */
+    SVGA_REG_GUEST_ID = 23,		/* Set guest OS identifier */
+    SVGA_REG_CURSOR_ID = 24,		/* ID of cursor */
+    SVGA_REG_CURSOR_X = 25,		/* Set cursor X position */
+    SVGA_REG_CURSOR_Y = 26,		/* Set cursor Y position */
+    SVGA_REG_CURSOR_ON = 27,		/* Turn cursor on/off */
+    SVGA_REG_HOST_BITS_PER_PIXEL = 28,	/* Current bpp in the host */
+    SVGA_REG_SCRATCH_SIZE = 29,		/* Number of scratch registers */
+    SVGA_REG_MEM_REGS = 30,		/* Number of FIFO registers */
+    SVGA_REG_NUM_DISPLAYS = 31,		/* Number of guest displays */
+    SVGA_REG_PITCHLOCK = 32,		/* Fixed pitch for all modes */
+
+    SVGA_PALETTE_BASE = 1024,		/* Base of SVGA color map */
+    SVGA_PALETTE_END  = SVGA_PALETTE_BASE + 767,
+    SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + 768,
+};
+
+#define SVGA_CAP_NONE			0
+#define SVGA_CAP_RECT_FILL		(1 << 0)
+#define SVGA_CAP_RECT_COPY		(1 << 1)
+#define SVGA_CAP_RECT_PAT_FILL		(1 << 2)
+#define SVGA_CAP_LEGACY_OFFSCREEN	(1 << 3)
+#define SVGA_CAP_RASTER_OP		(1 << 4)
+#define SVGA_CAP_CURSOR			(1 << 5)
+#define SVGA_CAP_CURSOR_BYPASS		(1 << 6)
+#define SVGA_CAP_CURSOR_BYPASS_2	(1 << 7)
+#define SVGA_CAP_8BIT_EMULATION		(1 << 8)
+#define SVGA_CAP_ALPHA_CURSOR		(1 << 9)
+#define SVGA_CAP_GLYPH			(1 << 10)
+#define SVGA_CAP_GLYPH_CLIPPING		(1 << 11)
+#define SVGA_CAP_OFFSCREEN_1		(1 << 12)
+#define SVGA_CAP_ALPHA_BLEND		(1 << 13)
+#define SVGA_CAP_3D			(1 << 14)
+#define SVGA_CAP_EXTENDED_FIFO		(1 << 15)
+#define SVGA_CAP_MULTIMON		(1 << 16)
+#define SVGA_CAP_PITCHLOCK		(1 << 17)
+
+/*
+ * FIFO offsets (seen as an array of 32-bit words)
+ */
+enum {
+    /*
+     * The original defined FIFO offsets
+     */
+    SVGA_FIFO_MIN = 0,
+    SVGA_FIFO_MAX,	/* The distance from MIN to MAX must be at least 10K */
+    SVGA_FIFO_NEXT_CMD,
+    SVGA_FIFO_STOP,
+
+    /*
+     * Additional offsets added as of SVGA_CAP_EXTENDED_FIFO
+     */
+    SVGA_FIFO_CAPABILITIES = 4,
+    SVGA_FIFO_FLAGS,
+    SVGA_FIFO_FENCE,
+    SVGA_FIFO_3D_HWVERSION,
+    SVGA_FIFO_PITCHLOCK,
+};
+
+#define SVGA_FIFO_CAP_NONE		0
+#define SVGA_FIFO_CAP_FENCE		(1 << 0)
+#define SVGA_FIFO_CAP_ACCELFRONT	(1 << 1)
+#define SVGA_FIFO_CAP_PITCHLOCK		(1 << 2)
+
+#define SVGA_FIFO_FLAG_NONE		0
+#define SVGA_FIFO_FLAG_ACCELFRONT	(1 << 0)
+
+/* These values can probably be changed arbitrarily.  */
+#define SVGA_SCRATCH_SIZE		0x8000
+#define SVGA_MAX_WIDTH			2360
+#define SVGA_MAX_HEIGHT			1770
+
+#ifdef VERBOSE
+# define GUEST_OS_BASE		0x5001
+static const char *vmsvga_guest_id[] = {
+    [0x0] = "Dos",
+    [0x1] = "Windows 3.1",
+    [0x2] = "Windows 95",
+    [0x3] = "Windows 98",
+    [0x4] = "Windows ME",
+    [0x5] = "Windows NT",
+    [0x6] = "Windows 2000",
+    [0x7] = "Linux",
+    [0x8] = "OS/2",
+    [0x9] = "Unknown",
+    [0xa] = "BSD",
+    [0xb] = "Whistler",
+};
+#endif
+
+enum {
+    SVGA_CMD_INVALID_CMD = 0,
+    SVGA_CMD_UPDATE = 1,
+    SVGA_CMD_RECT_FILL = 2,
+    SVGA_CMD_RECT_COPY = 3,
+    SVGA_CMD_DEFINE_BITMAP = 4,
+    SVGA_CMD_DEFINE_BITMAP_SCANLINE = 5,
+    SVGA_CMD_DEFINE_PIXMAP = 6,
+    SVGA_CMD_DEFINE_PIXMAP_SCANLINE = 7,
+    SVGA_CMD_RECT_BITMAP_FILL = 8,
+    SVGA_CMD_RECT_PIXMAP_FILL = 9,
+    SVGA_CMD_RECT_BITMAP_COPY = 10,
+    SVGA_CMD_RECT_PIXMAP_COPY = 11,
+    SVGA_CMD_FREE_OBJECT = 12,
+    SVGA_CMD_RECT_ROP_FILL = 13,
+    SVGA_CMD_RECT_ROP_COPY = 14,
+    SVGA_CMD_RECT_ROP_BITMAP_FILL = 15,
+    SVGA_CMD_RECT_ROP_PIXMAP_FILL = 16,
+    SVGA_CMD_RECT_ROP_BITMAP_COPY = 17,
+    SVGA_CMD_RECT_ROP_PIXMAP_COPY = 18,
+    SVGA_CMD_DEFINE_CURSOR = 19,
+    SVGA_CMD_DISPLAY_CURSOR = 20,
+    SVGA_CMD_MOVE_CURSOR = 21,
+    SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
+    SVGA_CMD_DRAW_GLYPH = 23,
+    SVGA_CMD_DRAW_GLYPH_CLIPPED = 24,
+    SVGA_CMD_UPDATE_VERBOSE = 25,
+    SVGA_CMD_SURFACE_FILL = 26,
+    SVGA_CMD_SURFACE_COPY = 27,
+    SVGA_CMD_SURFACE_ALPHA_BLEND = 28,
+    SVGA_CMD_FRONT_ROP_FILL = 29,
+    SVGA_CMD_FENCE = 30,
+};
+
+/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */
+enum {
+    SVGA_CURSOR_ON_HIDE = 0,
+    SVGA_CURSOR_ON_SHOW = 1,
+    SVGA_CURSOR_ON_REMOVE_FROM_FB = 2,
+    SVGA_CURSOR_ON_RESTORE_TO_FB = 3,
+};
+
+static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
+                int x, int y, int w, int h)
+{
+#ifndef DIRECT_VRAM
+    int line = h;
+    int bypl = s->bypp * s->width;
+    int width = s->bypp * w;
+    int start = s->bypp * x + bypl * y;
+    uint8_t *src = s->vram + start;
+    uint8_t *dst = s->ds->data + start;
+
+    for (; line > 0; line --, src += bypl, dst += bypl)
+        memcpy(dst, src, width);
+#endif
+
+    dpy_update(s->ds, x, y, w, h);
+}
+
+static inline void vmsvga_update_screen(struct vmsvga_state_s *s)
+{
+#ifndef DIRECT_VRAM
+    memcpy(s->ds->data, s->vram, s->bypp * s->width * s->height);
+#endif
+
+    dpy_update(s->ds, 0, 0, s->width, s->height);
+}
+
+#ifdef DIRECT_VRAM
+# define vmsvga_update_rect_delayed	vmsvga_update_rect
+#else
+static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
+                int x, int y, int w, int h)
+{
+    struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last ++];
+    s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
+    rect->x = x;
+    rect->y = y;
+    rect->w = w;
+    rect->h = h;
+}
+#endif
+
+static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
+{
+    struct vmsvga_rect_s *rect;
+    if (s->invalidated) {
+        s->redraw_fifo_first = s->redraw_fifo_last;
+        return;
+    }
+    /* Overlapping region updates can be optimised out here - if someone
+     * knows a smart algorithm to do that, please share.  */
+    while (s->redraw_fifo_first != s->redraw_fifo_last) {
+        rect = &s->redraw_fifo[s->redraw_fifo_first ++];
+        s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1;
+        vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h);
+    }
+}
+
+#ifdef HW_RECT_ACCEL
+static inline void vmsvga_copy_rect(struct vmsvga_state_s *s,
+                int x0, int y0, int x1, int y1, int w, int h)
+{
+# ifdef DIRECT_VRAM
+    uint8_t *vram = s->ds->data;
+# else
+    uint8_t *vram = s->vram;
+# endif
+    int bypl = s->bypp * s->width;
+    int width = s->bypp * w;
+    int line = h;
+    uint8_t *ptr[2];
+
+# ifdef DIRECT_VRAM
+    if (s->ds->dpy_copy)
+        s->ds->dpy_copy(s->ds, x0, y0, x1, y1, w, h);
+    else
+# endif
+    {
+        if (y1 > y0) {
+            ptr[0] = vram + s->bypp * x0 + bypl * (y0 + h - 1);
+            ptr[1] = vram + s->bypp * x1 + bypl * (y1 + h - 1);
+            for (; line > 0; line --, ptr[0] -= bypl, ptr[1] -= bypl)
+                memmove(ptr[1], ptr[0], width);
+        } else {
+            ptr[0] = vram + s->bypp * x0 + bypl * y0;
+            ptr[1] = vram + s->bypp * x1 + bypl * y1;
+            for (; line > 0; line --, ptr[0] += bypl, ptr[1] += bypl)
+                memmove(ptr[1], ptr[0], width);
+        }
+    }
+
+    vmsvga_update_rect_delayed(s, x1, y1, w, h);
+}
+#endif
+
+#ifdef HW_FILL_ACCEL
+static inline void vmsvga_fill_rect(struct vmsvga_state_s *s,
+                uint32_t c, int x, int y, int w, int h)
+{
+# ifdef DIRECT_VRAM
+    uint8_t *vram = s->ds->data;
+# else
+    uint8_t *vram = s->vram;
+# endif
+    int bypp = s->bypp;
+    int bypl = bypp * s->width;
+    int width = bypp * w;
+    int line = h;
+    int column;
+    uint8_t *fst = vram + bypp * x + bypl * y;
+    uint8_t *dst;
+    uint8_t *src;
+    uint8_t col[4];
+
+# ifdef DIRECT_VRAM
+    if (s->ds->dpy_fill)
+        s->ds->dpy_fill(s->ds, x, y, w, h, c);
+    else
+# endif
+    {
+        col[0] = c;
+        col[1] = c >> 8;
+        col[2] = c >> 16;
+        col[3] = c >> 24;
+
+        if (line --) {
+            dst = fst;
+            src = col;
+            for (column = width; column > 0; column --) {
+                *(dst ++) = *(src ++);
+                if (src - col == bypp)
+                    src = col;
+            }
+            dst = fst;
+            for (; line > 0; line --) {
+                dst += bypl;
+                memcpy(dst, fst, width);
+            }
+        }
+    }
+
+    vmsvga_update_rect_delayed(s, x, y, w, h);
+}
+#endif
+
+struct vmsvga_cursor_definition_s {
+    int width;
+    int height;
+    int id;
+    int bpp;
+    int hot_x;
+    int hot_y;
+    uint32_t mask[1024];
+    uint32_t image[1024];
+};
+
+#define SVGA_BITMAP_SIZE(w, h)		((((w) + 31) >> 5) * (h))
+#define SVGA_PIXMAP_SIZE(w, h, bpp)	(((((w) * (bpp)) + 31) >> 5) * (h))
+
+#ifdef HW_MOUSE_ACCEL
+static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
+                struct vmsvga_cursor_definition_s *c)
+{
+    int i;
+    for (i = SVGA_BITMAP_SIZE(c->width, c->height) - 1; i >= 0; i --)
+        c->mask[i] = ~c->mask[i];
+
+    if (s->ds->cursor_define)
+        s->ds->cursor_define(c->width, c->height, c->bpp, c->hot_x, c->hot_y,
+                        (uint8_t *) c->image, (uint8_t *) c->mask);
+}
+#endif
+
+static inline int vmsvga_fifo_empty(struct vmsvga_state_s *s)
+{
+    if (!s->config || !s->enable)
+        return 0;
+    return (s->cmd->next_cmd == s->cmd->stop);
+}
+
+static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
+{
+    uint32_t cmd = s->fifo[s->cmd->stop >> 2];
+    s->cmd->stop += 4;
+    if (s->cmd->stop >= s->cmd->max)
+        s->cmd->stop = s->cmd->min;
+    return cmd;
+}
+
+static void vmsvga_fifo_run(struct vmsvga_state_s *s)
+{
+    uint32_t cmd, colour;
+    int args = 0;
+    int x, y, dx, dy, width, height;
+    struct vmsvga_cursor_definition_s cursor;
+    while (!vmsvga_fifo_empty(s))
+        switch (cmd = vmsvga_fifo_read(s)) {
+        case SVGA_CMD_UPDATE:
+        case SVGA_CMD_UPDATE_VERBOSE:
+            x = vmsvga_fifo_read(s);
+            y = vmsvga_fifo_read(s);
+            width = vmsvga_fifo_read(s);
+            height = vmsvga_fifo_read(s);
+            vmsvga_update_rect_delayed(s, x, y, width, height);
+            break;
+
+        case SVGA_CMD_RECT_FILL:
+            colour = vmsvga_fifo_read(s);
+            x = vmsvga_fifo_read(s);
+            y = vmsvga_fifo_read(s);
+            width = vmsvga_fifo_read(s);
+            height = vmsvga_fifo_read(s);
+#ifdef HW_FILL_ACCEL
+            vmsvga_fill_rect(s, colour, x, y, width, height);
+            break;
+#else
+            goto badcmd;
+#endif
+
+        case SVGA_CMD_RECT_COPY:
+            x = vmsvga_fifo_read(s);
+            y = vmsvga_fifo_read(s);
+            dx = vmsvga_fifo_read(s);
+            dy = vmsvga_fifo_read(s);
+            width = vmsvga_fifo_read(s);
+            height = vmsvga_fifo_read(s);
+#ifdef HW_RECT_ACCEL
+            vmsvga_copy_rect(s, x, y, dx, dy, width, height);
+            break;
+#else
+            goto badcmd;
+#endif
+
+        case SVGA_CMD_DEFINE_CURSOR:
+            cursor.id = vmsvga_fifo_read(s);
+            cursor.hot_x = vmsvga_fifo_read(s);
+            cursor.hot_y = vmsvga_fifo_read(s);
+            cursor.width = x = vmsvga_fifo_read(s);
+            cursor.height = y = vmsvga_fifo_read(s);
+            vmsvga_fifo_read(s);
+            cursor.bpp = vmsvga_fifo_read(s);
+            for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++)
+                cursor.mask[args] = vmsvga_fifo_read(s);
+            for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++)
+                cursor.image[args] = vmsvga_fifo_read(s);
+#ifdef HW_MOUSE_ACCEL
+            vmsvga_cursor_define(s, &cursor);
+            break;
+#else
+            args = 0;
+            goto badcmd;
+#endif
+
+        /*
+         * Other commands that we at least know the number of arguments
+         * for so we can avoid FIFO desync if driver uses them illegally.
+         */
+        case SVGA_CMD_DEFINE_ALPHA_CURSOR:
+            vmsvga_fifo_read(s);
+            vmsvga_fifo_read(s);
+            vmsvga_fifo_read(s);
+            x = vmsvga_fifo_read(s);
+            y = vmsvga_fifo_read(s);
+            args = x * y;
+            goto badcmd;
+        case SVGA_CMD_RECT_ROP_FILL:
+            args = 6;
+            goto badcmd;
+        case SVGA_CMD_RECT_ROP_COPY:
+            args = 7;
+            goto badcmd;
+        case SVGA_CMD_DRAW_GLYPH_CLIPPED:
+            vmsvga_fifo_read(s);
+            vmsvga_fifo_read(s);
+            args = 7 + (vmsvga_fifo_read(s) >> 2);
+            goto badcmd;
+        case SVGA_CMD_SURFACE_ALPHA_BLEND:
+            args = 12;
+            goto badcmd;
+
+        /*
+         * Other commands that are not listed as depending on any
+         * CAPABILITIES bits, but are not described in the README either.
+         */
+        case SVGA_CMD_SURFACE_FILL:
+        case SVGA_CMD_SURFACE_COPY:
+        case SVGA_CMD_FRONT_ROP_FILL:
+        case SVGA_CMD_FENCE:
+        case SVGA_CMD_INVALID_CMD:
+            break; /* Nop */
+
+        default:
+        badcmd:
+            while (args --)
+                vmsvga_fifo_read(s);
+            printf("%s: Unknown command 0x%02x in SVGA command FIFO\n",
+                            __FUNCTION__, cmd);
+            break;
+        }
+
+    s->syncing = 0;
+}
+
+static uint32_t vmsvga_index_read(void *opaque, uint32_t address)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    return s->index;
+}
+
+static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    s->index = index;
+}
+
+static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
+{
+    uint32_t caps;
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    switch (s->index) {
+    case SVGA_REG_ID:
+        return s->svgaid;
+
+    case SVGA_REG_ENABLE:
+        return s->enable;
+
+    case SVGA_REG_WIDTH:
+        return s->width;
+
+    case SVGA_REG_HEIGHT:
+        return s->height;
+
+    case SVGA_REG_MAX_WIDTH:
+        return SVGA_MAX_WIDTH;
+
+    case SVGA_REG_MAX_HEIGHT:
+        return SVGA_MAX_WIDTH;
+
+    case SVGA_REG_DEPTH:
+        return s->depth;
+
+    case SVGA_REG_BITS_PER_PIXEL:
+        return (s->depth + 7) & ~7;
+
+    case SVGA_REG_PSEUDOCOLOR:
+        return 0x0;
+
+    case SVGA_REG_RED_MASK:
+        return s->wred;
+    case SVGA_REG_GREEN_MASK:
+        return s->wgreen;
+    case SVGA_REG_BLUE_MASK:
+        return s->wblue;
+
+    case SVGA_REG_BYTES_PER_LINE:
+        return ((s->depth + 7) >> 3) * s->new_width;
+
+    case SVGA_REG_FB_START:
+        return SVGA_MEM_BASE;
+
+    case SVGA_REG_FB_OFFSET:
+        return 0x0;
+
+    case SVGA_REG_VRAM_SIZE:
+        return s->vram_size - SVGA_FIFO_SIZE;
+
+    case SVGA_REG_FB_SIZE:
+        return s->fb_size;
+
+    case SVGA_REG_CAPABILITIES:
+        caps = SVGA_CAP_NONE;
+#ifdef HW_RECT_ACCEL
+        caps |= SVGA_CAP_RECT_COPY;
+#endif
+#ifdef HW_FILL_ACCEL
+        caps |= SVGA_CAP_RECT_FILL;
+#endif
+#ifdef HW_MOUSE_ACCEL
+        if (s->ds->mouse_set)
+            caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
+                    SVGA_CAP_CURSOR_BYPASS;
+#endif
+        return caps;
+
+    case SVGA_REG_MEM_START:
+        return SVGA_MEM_BASE + s->vram_size - SVGA_FIFO_SIZE;
+
+    case SVGA_REG_MEM_SIZE:
+        return SVGA_FIFO_SIZE;
+
+    case SVGA_REG_CONFIG_DONE:
+        return s->config;
+
+    case SVGA_REG_SYNC:
+    case SVGA_REG_BUSY:
+        return s->syncing;
+
+    case SVGA_REG_GUEST_ID:
+        return s->guest;
+
+    case SVGA_REG_CURSOR_ID:
+        return s->cursor.id;
+
+    case SVGA_REG_CURSOR_X:
+        return s->cursor.x;
+
+    case SVGA_REG_CURSOR_Y:
+        return s->cursor.x;
+
+    case SVGA_REG_CURSOR_ON:
+        return s->cursor.on;
+
+    case SVGA_REG_HOST_BITS_PER_PIXEL:
+        return (s->depth + 7) & ~7;
+
+    case SVGA_REG_SCRATCH_SIZE:
+        return s->scratch_size;
+
+    case SVGA_REG_MEM_REGS:
+    case SVGA_REG_NUM_DISPLAYS:
+    case SVGA_REG_PITCHLOCK:
+    case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
+        return 0;
+
+    default:
+        if (s->index >= SVGA_SCRATCH_BASE &&
+                s->index < SVGA_SCRATCH_BASE + s->scratch_size)
+            return s->scratch[s->index - SVGA_SCRATCH_BASE];
+        printf("%s: Bad register %02x\n", __FUNCTION__, s->index);
+    }
+
+    return 0;
+}
+
+static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    switch (s->index) {
+    case SVGA_REG_ID:
+        if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0)
+            s->svgaid = value;
+        break;
+
+    case SVGA_REG_ENABLE:
+        s->enable = s->config = value & s->config;
+        s->width = -1;
+        s->height = -1;
+        s->invalidated = 1;
+#ifdef EMBED_STDVGA
+        s->invalidate(opaque);
+#endif
+        if (s->enable)
+            s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
+        break;
+
+    case SVGA_REG_WIDTH:
+        s->new_width = value;
+        s->invalidated = 1;
+        break;
+
+    case SVGA_REG_HEIGHT:
+        s->new_height = value;
+        s->invalidated = 1;
+        break;
+
+    case SVGA_REG_DEPTH:
+    case SVGA_REG_BITS_PER_PIXEL:
+        if (value != s->depth) {
+            printf("%s: Bad colour depth: %i bits\n", __FUNCTION__, value);
+            s->config = 0;
+        }
+        break;
+
+    case SVGA_REG_CONFIG_DONE:
+        if (value) {
+            s->fifo = (uint32_t *) &s->vram[s->vram_size - SVGA_FIFO_SIZE];
+            /* Check range and alignment.  */
+            if ((s->cmd->min | s->cmd->max |
+                        s->cmd->next_cmd | s->cmd->stop) & 3)
+                break;
+            if (s->cmd->min < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo)
+                break;
+            if (s->cmd->max > SVGA_FIFO_SIZE)
+                break;
+            if (s->cmd->max < s->cmd->min + 10 * 1024)
+                break;
+        }
+        s->config = value;
+        break;
+
+    case SVGA_REG_SYNC:
+        s->syncing = 1;
+        vmsvga_fifo_run(s); /* Or should we just wait for update_display? */
+        break;
+
+    case SVGA_REG_GUEST_ID:
+        s->guest = value;
+#ifdef VERBOSE
+        if (value >= GUEST_OS_BASE && value < GUEST_OS_BASE +
+                sizeof(vmsvga_guest_id) / sizeof(*vmsvga_guest_id))
+            printf("%s: guest runs %s.\n", __FUNCTION__,
+                            vmsvga_guest_id[value - GUEST_OS_BASE]);
+#endif
+        break;
+
+    case SVGA_REG_CURSOR_ID:
+        s->cursor.id = value;
+        break;
+
+    case SVGA_REG_CURSOR_X:
+        s->cursor.x = value;
+        break;
+
+    case SVGA_REG_CURSOR_Y:
+        s->cursor.y = value;
+        break;
+
+    case SVGA_REG_CURSOR_ON:
+        s->cursor.on |= (value == SVGA_CURSOR_ON_SHOW);
+        s->cursor.on &= (value != SVGA_CURSOR_ON_HIDE);
+#ifdef HW_MOUSE_ACCEL
+        if (s->ds->mouse_set && value <= SVGA_CURSOR_ON_SHOW)
+            s->ds->mouse_set(s->cursor.x, s->cursor.y, s->cursor.on);
+#endif
+        break;
+
+    case SVGA_REG_MEM_REGS:
+    case SVGA_REG_NUM_DISPLAYS:
+    case SVGA_REG_PITCHLOCK:
+    case SVGA_PALETTE_BASE ... SVGA_PALETTE_END:
+        break;
+
+    default:
+        if (s->index >= SVGA_SCRATCH_BASE &&
+                s->index < SVGA_SCRATCH_BASE + s->scratch_size) {
+            s->scratch[s->index - SVGA_SCRATCH_BASE] = value;
+            break;
+        }
+        printf("%s: Bad register %02x\n", __FUNCTION__, s->index);
+    }
+}
+
+static uint32_t vmsvga_bios_read(void *opaque, uint32_t address)
+{
+    printf("%s: what are we supposed to return?\n", __FUNCTION__);
+    return 0xcafe;
+}
+
+static void vmsvga_bios_write(void *opaque, uint32_t address, uint32_t data)
+{
+    printf("%s: what are we supposed to do with (%08x)?\n",
+                    __FUNCTION__, data);
+}
+
+static inline void vmsvga_size(struct vmsvga_state_s *s)
+{
+    if (s->new_width != s->width || s->new_height != s->height) {
+        s->width = s->new_width;
+        s->height = s->new_height;
+        dpy_resize(s->ds, s->width, s->height);
+        s->invalidated = 1;
+    }
+}
+
+static void vmsvga_update_display(void *opaque)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    if (!s->enable) {
+#ifdef EMBED_STDVGA
+        s->update(opaque);
+#endif
+        return;
+    }
+
+    vmsvga_size(s);
+
+    vmsvga_fifo_run(s);
+    vmsvga_update_rect_flush(s);
+
+    /*
+     * Is it more efficient to look at vram VGA-dirty bits or wait
+     * for the driver to issue SVGA_CMD_UPDATE?
+     */
+    if (s->invalidated) {
+        s->invalidated = 0;
+        vmsvga_update_screen(s);
+    }
+}
+
+static void vmsvga_reset(struct vmsvga_state_s *s)
+{
+    s->index = 0;
+    s->enable = 0;
+    s->config = 0;
+    s->width = -1;
+    s->height = -1;
+    s->svgaid = SVGA_ID;
+    s->depth = s->ds->depth ? s->ds->depth : 24;
+    s->bypp = (s->depth + 7) >> 3;
+    s->cursor.on = 0;
+    s->redraw_fifo_first = 0;
+    s->redraw_fifo_last = 0;
+    switch (s->depth) {
+    case 8:
+        s->wred   = 0x00000007;
+        s->wgreen = 0x00000038;
+        s->wblue  = 0x000000c0;
+        break;
+    case 15:
+        s->wred   = 0x0000001f;
+        s->wgreen = 0x000003e0;
+        s->wblue  = 0x00007c00;
+        break;
+    case 16:
+        s->wred   = 0x0000001f;
+        s->wgreen = 0x000007e0;
+        s->wblue  = 0x0000f800;
+        break;
+    case 24:
+        s->wred   = 0x000000ff;
+        s->wgreen = 0x0000ff00;
+        s->wblue  = 0x00ff0000;
+        break;
+    case 32:
+        s->wred   = 0x000000ff;
+        s->wgreen = 0x0000ff00;
+        s->wblue  = 0x00ff0000;
+        break;
+    }
+    s->syncing = 0;
+}
+
+static void vmsvga_invalidate_display(void *opaque)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    if (!s->enable) {
+#ifdef EMBED_STDVGA
+        s->invalidate(opaque);
+#endif
+        return;
+    }
+
+    s->invalidated = 1;
+}
+
+static void vmsvga_screen_dump(void *opaque, const char *filename)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    if (!s->enable) {
+#ifdef EMBED_STDVGA
+        s->screen_dump(opaque, filename);
+#endif
+        return;
+    }
+
+    /* TODO */
+}
+
+#ifdef DIRECT_VRAM
+static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        return *(uint8_t *) (s->ds->data + addr);
+    else
+        return *(uint8_t *) (s->vram + addr);
+}
+
+static uint32_t vmsvga_vram_readw(void *opaque, target_phys_addr_t addr)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        return *(uint16_t *) (s->ds->data + addr);
+    else
+        return *(uint16_t *) (s->vram + addr);
+}
+
+static uint32_t vmsvga_vram_readl(void *opaque, target_phys_addr_t addr)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        return *(uint32_t *) (s->ds->data + addr);
+    else
+        return *(uint32_t *) (s->vram + addr);
+}
+
+static void vmsvga_vram_writeb(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        *(uint8_t *) (s->ds->data + addr) = value;
+    else
+        *(uint8_t *) (s->vram + addr) = value;
+}
+
+static void vmsvga_vram_writew(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        *(uint16_t *) (s->ds->data + addr) = value;
+    else
+        *(uint16_t *) (s->vram + addr) = value;
+}
+
+static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+    struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+    addr -= SVGA_MEM_BASE;
+    if (addr < s->fb_size)
+        *(uint32_t *) (s->ds->data + addr) = value;
+    else
+        *(uint32_t *) (s->vram + addr) = value;
+}
+
+static CPUReadMemoryFunc *vmsvga_vram_read[] = {
+    vmsvga_vram_readb,
+    vmsvga_vram_readw,
+    vmsvga_vram_readl,
+};
+
+static CPUWriteMemoryFunc *vmsvga_vram_write[] = {
+    vmsvga_vram_writeb,
+    vmsvga_vram_writew,
+    vmsvga_vram_writel,
+};
+#endif
+
+static void vmsvga_save(struct vmsvga_state_s *s, QEMUFile *f)
+{
+    qemu_put_be32s(f, &s->depth);
+    qemu_put_be32s(f, &s->enable);
+    qemu_put_be32s(f, &s->config);
+    qemu_put_be32s(f, &s->cursor.id);
+    qemu_put_be32s(f, &s->cursor.x);
+    qemu_put_be32s(f, &s->cursor.y);
+    qemu_put_be32s(f, &s->cursor.on);
+    qemu_put_be32s(f, &s->index);
+    qemu_put_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
+    qemu_put_be32s(f, &s->new_width);
+    qemu_put_be32s(f, &s->new_height);
+    qemu_put_be32s(f, &s->guest);
+    qemu_put_be32s(f, &s->svgaid);
+    qemu_put_be32s(f, &s->syncing);
+    qemu_put_be32s(f, &s->fb_size);
+}
+
+static int vmsvga_load(struct vmsvga_state_s *s, QEMUFile *f)
+{
+    int depth;
+    qemu_get_be32s(f, &depth);
+    qemu_get_be32s(f, &s->enable);
+    qemu_get_be32s(f, &s->config);
+    qemu_get_be32s(f, &s->cursor.id);
+    qemu_get_be32s(f, &s->cursor.x);
+    qemu_get_be32s(f, &s->cursor.y);
+    qemu_get_be32s(f, &s->cursor.on);
+    qemu_get_be32s(f, &s->index);
+    qemu_get_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
+    qemu_get_be32s(f, &s->new_width);
+    qemu_get_be32s(f, &s->new_height);
+    qemu_get_be32s(f, &s->guest);
+    qemu_get_be32s(f, &s->svgaid);
+    qemu_get_be32s(f, &s->syncing);
+    qemu_get_be32s(f, &s->fb_size);
+
+    if (s->enable && depth != s->depth) {
+        printf("%s: need colour depth of %i bits to resume operation.\n",
+                        __FUNCTION__, depth);
+        return -EINVAL;
+    }
+
+    s->invalidated = 1;
+    if (s->config)
+        s->fifo = (uint32_t *) &s->vram[s->vram_size - SVGA_FIFO_SIZE];
+
+    return 0;
+}
+
+static void vmsvga_init(struct vmsvga_state_s *s, DisplayState *ds,
+                uint8_t *vga_ram_base, unsigned long vga_ram_offset,
+                int vga_ram_size)
+{
+    int iomemtype;
+    s->ds = ds;
+    s->vram = vga_ram_base;
+    s->vram_size = vga_ram_size;
+
+    s->scratch_size = SVGA_SCRATCH_SIZE;
+    s->scratch = (uint32_t *) qemu_malloc(s->scratch_size * 4);
+
+    vmsvga_reset(s);
+
+#ifdef DIRECT_VRAM
+    iomemtype = cpu_register_io_memory(0, vmsvga_vram_read,
+                    vmsvga_vram_write, s);
+#else
+    iomemtype = vga_ram_offset | IO_MEM_RAM;
+#endif
+    cpu_register_physical_memory(SVGA_MEM_BASE, vga_ram_size,
+                    iomemtype);
+
+    register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_INDEX_PORT,
+                    1, 4, vmsvga_index_read, s);
+    register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_INDEX_PORT,
+                    1, 4, vmsvga_index_write, s);
+    register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_VALUE_PORT,
+                    1, 4, vmsvga_value_read, s);
+    register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_VALUE_PORT,
+                    1, 4, vmsvga_value_write, s);
+    register_ioport_read(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_BIOS_PORT,
+                    1, 4, vmsvga_bios_read, s);
+    register_ioport_write(SVGA_IO_BASE + SVGA_IO_MUL * SVGA_BIOS_PORT,
+                    1, 4, vmsvga_bios_write, s);
+
+    graphic_console_init(ds, vmsvga_update_display,
+                    vmsvga_invalidate_display, vmsvga_screen_dump, s);
+
+#ifdef EMBED_STDVGA
+    vga_common_init((VGAState *) s, ds,
+                    vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_init((VGAState *) s);
+#endif
+}
+
+static void pci_vmsvga_save(QEMUFile *f, void *opaque)
+{
+    struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
+    pci_device_save(&s->card, f);
+    vmsvga_save(&s->chip, f);
+}
+
+static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
+    int ret;
+
+    ret = pci_device_load(&s->card, f);
+    if (ret < 0)
+        return ret;
+
+    ret = vmsvga_load(&s->chip, f);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+#define PCI_VENDOR_ID_VMWARE		0x15ad
+#define PCI_DEVICE_ID_VMWARE_SVGA2	0x0405
+#define PCI_DEVICE_ID_VMWARE_SVGA	0x0710
+#define PCI_DEVICE_ID_VMWARE_NET	0x0720
+#define PCI_DEVICE_ID_VMWARE_SCSI	0x0730
+#define PCI_DEVICE_ID_VMWARE_IDE	0x1729
+#define PCI_CLASS_BASE_DISPLAY		0x03
+#define PCI_CLASS_SUB_VGA		0x00
+#define PCI_CLASS_HEADERTYPE_00h	0x00
+
+void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+                     unsigned long vga_ram_offset, int vga_ram_size)
+{
+    struct pci_vmsvga_state_s *s;
+
+    /* Setup PCI configuration */
+    s = (struct pci_vmsvga_state_s *)
+        pci_register_device(bus, "QEMUware SVGA",
+                sizeof(struct pci_vmsvga_state_s), -1, 0, 0);
+    s->card.config[PCI_VENDOR_ID]	= PCI_VENDOR_ID_VMWARE & 0xff;
+    s->card.config[PCI_VENDOR_ID + 1]	= PCI_VENDOR_ID_VMWARE >> 8;
+    s->card.config[PCI_DEVICE_ID]	= SVGA_PCI_DEVICE_ID & 0xff;
+    s->card.config[PCI_DEVICE_ID + 1]	= SVGA_PCI_DEVICE_ID >> 8;
+    s->card.config[PCI_COMMAND]		= 0x07;		/* I/O + Memory */
+    s->card.config[PCI_CLASS_DEVICE]	= PCI_CLASS_SUB_VGA;
+    s->card.config[0x0b]		= PCI_CLASS_BASE_DISPLAY;
+    s->card.config[0x0c]		= 0x08;		/* Cache line size */
+    s->card.config[0x0d]		= 0x40;		/* Latency timer */
+    s->card.config[0x0e]		= PCI_CLASS_HEADERTYPE_00h;
+    s->card.config[0x10]		= ((SVGA_IO_BASE >>  0) & 0xff) | 1;
+    s->card.config[0x11]		=  (SVGA_IO_BASE >>  8) & 0xff;
+    s->card.config[0x12]		=  (SVGA_IO_BASE >> 16) & 0xff;
+    s->card.config[0x13]		=  (SVGA_IO_BASE >> 24) & 0xff;
+    s->card.config[0x18]		= (SVGA_MEM_BASE >>  0) & 0xff;
+    s->card.config[0x19]		= (SVGA_MEM_BASE >>  8) & 0xff;
+    s->card.config[0x1a]		= (SVGA_MEM_BASE >> 16) & 0xff;
+    s->card.config[0x1b]		= (SVGA_MEM_BASE >> 24) & 0xff;
+    s->card.config[0x2c]		= PCI_VENDOR_ID_VMWARE & 0xff;
+    s->card.config[0x2d]		= PCI_VENDOR_ID_VMWARE >> 8;
+    s->card.config[0x2e]		= SVGA_PCI_DEVICE_ID & 0xff;
+    s->card.config[0x2f]		= SVGA_PCI_DEVICE_ID >> 8;
+    s->card.config[0x3c]		= 0xff;		/* End */
+
+    vmsvga_init(&s->chip, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+
+    register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
+}

Modified: trunk/src/host/qemu-neo1973/hw/wm8750.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/wm8750.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/wm8750.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -16,8 +16,9 @@
 
 struct wm_rate_s;
 struct wm8750_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
+    i2c_slave i2c;
+    uint8_t i2c_data[2];
+    int i2c_len;
     QEMUSoundCard card;
     SWVoiceIn *adc_voice[IN_PORT_N];
     SWVoiceOut *dac_voice[OUT_PORT_N];
@@ -207,9 +208,9 @@
             (s->mute ? NONE : BOTH);
 }
 
-void wm8750_reset(struct i2c_slave_s *i2c)
+void wm8750_reset(i2c_slave *i2c)
 {
-    struct wm8750_s *s = (struct wm8750_s *) i2c->opaque;
+    struct wm8750_s *s = (struct wm8750_s *) i2c;
     s->enable = 0;
     wm8750_set_format(s);
     s->diff[0] = 0;
@@ -245,12 +246,27 @@
     s->idx_out = 0;
     s->req_out = 0;
     wm8750_mask_update(s);
+    s->i2c_len = 0;
 }
 
-static void wm8750_start(void *opaque, int dir)
+static void wm8750_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct wm8750_s *s = (struct wm8750_s *) opaque;
-    s->i2c_dir = dir;
+    struct wm8750_s *s = (struct wm8750_s *) i2c;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->i2c_len = 0;
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->i2c_len < 2)
+            printf("%s: message too short (%i bytes)\n",
+                            __FUNCTION__, s->i2c_len);
+#endif
+        break;
+    default:
+        break;
+    }
 }
 
 #define WM8750_LINVOL	0x00
@@ -290,27 +306,25 @@
 #define WM8750_ROUT2V	0x29
 #define WM8750_MOUTV	0x2a
 
-static int wm8750_tx(void *opaque, uint8_t *data, int len)
+static int wm8750_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct wm8750_s *s = (struct wm8750_s *) opaque;
+    struct wm8750_s *s = (struct wm8750_s *) i2c;
     uint8_t cmd;
     uint16_t value;
 
-    if (s->i2c_dir)
+    if (s->i2c_len >= 2) {
+        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
+#ifdef VERBOSE
         return 1;
-    if (len < 2) {
-#ifdef VERBOSE
-        printf("%s: message too short (%i bytes)\n", __FUNCTION__, len);
 #endif
+    }
+    s->i2c_data[s->i2c_len ++] = data;
+    if (s->i2c_len != 2)
         return 0;
-    }
-    cmd = data[0] >> 1;
-    value = ((data[0] << 8) | data[1]) & 0x1ff;
-#ifdef VERBOSE
-    if (len > 2)
-        printf("%s: long message (%i bytes)\n", __FUNCTION__, len);
-#endif
 
+    cmd = s->i2c_data[0] >> 1;
+    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
+
     switch (cmd) {
     case WM8750_LADCIN:	/* ADC Signal Path Control (Left) */
         s->diff[0] = (((value >> 6) & 3) == 3);	/* LINSEL */
@@ -472,30 +486,36 @@
     return 0;
 }
 
-struct i2c_slave_s *wm8750_init(AudioState *audio)
+static int wm8750_rx(i2c_slave *i2c)
 {
-    struct wm8750_s *s = qemu_mallocz(sizeof(struct wm8750_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = wm8750_tx;
-    s->i2c.start = wm8750_start;
+    return 0x00;
+}
 
+i2c_slave *wm8750_init(i2c_bus *bus, AudioState *audio)
+{
+    struct wm8750_s *s = (struct wm8750_s *)
+            i2c_slave_init(bus, 0, sizeof(struct wm8750_s));
+    s->i2c.event = wm8750_event;
+    s->i2c.recv = wm8750_rx;
+    s->i2c.send = wm8750_tx;
+
     AUD_register_card(audio, CODEC, &s->card);
     wm8750_reset(&s->i2c);
     return &s->i2c;
 }
 
-void wm8750_fini(struct i2c_slave_s *i2c)
+void wm8750_fini(i2c_slave *i2c)
 {
-    struct wm8750_s *s = (struct wm8750_s *) i2c->opaque;
+    struct wm8750_s *s = (struct wm8750_s *) i2c;
     wm8750_reset(&s->i2c);
     AUD_remove_card(&s->card);
     qemu_free(s);
 }
 
-void wm8750_data_req_set(struct i2c_slave_s *i2c,
+void wm8750_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque)
 {
-    struct wm8750_s *s = (struct wm8750_s *) i2c->opaque;
+    struct wm8750_s *s = (struct wm8750_s *) i2c;
     s->data_req = data_req;
     s->opaque = opaque;
 }

Modified: trunk/src/host/qemu-neo1973/hw/wm8753.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/wm8753.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/hw/wm8753.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -16,8 +16,9 @@
 
 struct wm_rate_s;
 struct wm8753_s {
-    int i2c_dir;
-    struct i2c_slave_s i2c;
+    i2c_slave i2c;
+    uint8_t i2c_data[2];
+    int i2c_len;
     QEMUSoundCard card;
     SWVoiceIn *adc_voice[IN_PORT_N];
     SWVoiceOut *dac_voice[OUT_PORT_N];
@@ -48,10 +49,10 @@
     uint8_t intintr;
     uint8_t intprev;
     struct {
-        gpio_handler_t fn;
-        void *opaque;
+        qemu_irq handler;
         enum { input, low, high, intr } type;
-    } handler[8];
+    } line[8];
+    qemu_irq *gpio_in;
 
     uint8_t response;
 
@@ -219,24 +220,23 @@
 
     while ((line = ffs(level))) {
         line --;
-        if (s->handler[line].fn)
-            s->handler[line].fn(line, (s->intprev >> line) & 1,
-                            s->handler[line].opaque);
+        if (s->line[line].handler)
+            qemu_set_irq(s->line[line].handler, (s->intprev >> line) & 1);
         level ^= 1 << line;
     }
 }
 
 static inline void wm8753_input_update(struct wm8753_s *s, int line)
 {
-    if (s->handler[line].type == input)
+    if (s->line[line].type == input)
         s->intinput |= 1 << line;
     else
         s->intinput &= ~(1 << line);
-    if (s->handler[line].type == high)
+    if (s->line[line].type == high)
         s->inthigh |= 1 << line;
     else
         s->inthigh &= ~(1 << line);
-    if (s->handler[line].type == intr)
+    if (s->line[line].type == intr)
         s->intintr |= 1 << line;
     else
         s->intintr &= ~(1 << line);
@@ -283,10 +283,10 @@
     return 0;
 }
 
-void wm8753_reset(struct i2c_slave_s *i2c)
+void wm8753_reset(i2c_slave *i2c)
 {
     int i;
-    struct wm8753_s *s = (struct wm8753_s *) i2c->opaque;
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
     s->enable = 0;
     wm8753_set_format(s);
 
@@ -326,7 +326,7 @@
     s->inthigh = 0x00;
     s->intintr = 0x00;
     for (i = 0; i < 8; i ++)
-        s->handler[i].type = input;
+        s->line[i].type = input;
 
     s->power[0] = 0x000;
     s->power[1] = 0x000;
@@ -346,10 +346,24 @@
     wm8753_mask_update(s);
 }
 
-static void wm8753_start(void *opaque, int dir)
+static void wm8753_event(i2c_slave *i2c, enum i2c_event event)
 {
-    struct wm8753_s *s = (struct wm8753_s *) opaque;
-    s->i2c_dir = dir;
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
+
+    switch (event) {
+    case I2C_START_SEND:
+        s->i2c_len = 0;
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->i2c_len < 2)
+            printf("%s: message too short (%i bytes)\n",
+                            __FUNCTION__, s->i2c_len);
+#endif
+        break;
+    default:
+        break;
+    }
 }
 
 #define WM8753_DAC	0x01
@@ -413,27 +427,25 @@
 #define WM8753_BIASCTL	0x3d
 #define WM8753_ADCTL2	0x3f
 
-static int wm8753_tx(void *opaque, uint8_t *data, int len)
+static int wm8753_tx(i2c_slave *i2c, uint8_t data)
 {
-    struct wm8753_s *s = (struct wm8753_s *) opaque;
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
     uint8_t cmd;
     uint16_t value;
 
-    if (s->i2c_dir)
+    if (s->i2c_len >= 2) {
+        printf("%s: long message (%i bytes)\n", __FUNCTION__, s->i2c_len);
+#ifdef VERBOSE
         return 1;
-    if (len < 2) {
-#ifdef VERBOSE
-        printf("%s: message too short (%i bytes)\n", __FUNCTION__, len);
 #endif
+    }
+    s->i2c_data[s->i2c_len ++] = data;
+    if (s->i2c_len != 2)
         return 0;
-    }
-    cmd = data[0] >> 1;
-    value = ((data[0] << 8) | data[1]) & 0x1ff;
-#ifdef VERBOSE
-    if (len > 2)
-        printf("%s: long message (%i bytes)\n", __FUNCTION__, len);
-#endif
 
+    cmd = s->i2c_data[0] >> 1;
+    value = ((s->i2c_data[0] << 8) | s->i2c_data[1]) & 0x1ff;
+
     switch (cmd) {
     case WM8753_ADCIN:		/* ADC Input Mode */
         s->adcin = value;
@@ -601,17 +613,17 @@
     case WM8753_GPIO1:		/* GPIO Control (1) */
         s->inten = !!(value & 3);
         switch ((value >> 3) & 3) {
-        case 0:  s->handler[5].type = input; break;
-        case 1:  s->handler[5].type = intr; break;
-        case 2:  s->handler[5].type = low; break;
-        case 3:  s->handler[5].type = high; break;
+        case 0:  s->line[5].type = input; break;
+        case 1:  s->line[5].type = intr; break;
+        case 2:  s->line[5].type = low; break;
+        case 3:  s->line[5].type = high; break;
         }
         wm8753_input_update(s, 5);
         switch ((value >> 0) & 7) {
-        case 4:  s->handler[4].type = low; break;
-        case 5:  s->handler[4].type = high; break;
-        case 7:  s->handler[4].type = intr; break;
-        default: s->handler[4].type = input; break;
+        case 4:  s->line[4].type = low; break;
+        case 5:  s->line[4].type = high; break;
+        case 7:  s->line[4].type = intr; break;
+        default: s->line[4].type = input; break;
         }
         wm8753_input_update(s, 4);
         wm8753_int_update(s);
@@ -619,24 +631,24 @@
 
     case WM8753_GPIO2:		/* GPIO Control (2) */
         switch ((value >> 6) & 7) {
-        case 4:  s->handler[3].type = low; break;
-        case 5:  s->handler[3].type = high; break;
-        case 7:  s->handler[3].type = intr; break;
-        default: s->handler[3].type = input; break;
+        case 4:  s->line[3].type = low; break;
+        case 5:  s->line[3].type = high; break;
+        case 7:  s->line[3].type = intr; break;
+        default: s->line[3].type = input; break;
         }
         wm8753_input_update(s, 3);
         switch ((value >> 3) & 7) {
-        case 0:  s->handler[2].type = low; break;
-        case 1:  s->handler[2].type = high; break;
-        case 3:  s->handler[2].type = intr; break;
-        default: s->handler[2].type = input; break;
+        case 0:  s->line[2].type = low; break;
+        case 1:  s->line[2].type = high; break;
+        case 3:  s->line[2].type = intr; break;
+        default: s->line[2].type = input; break;
         }
         wm8753_input_update(s, 2);
         switch ((value >> 0) & 7) {
-        case 0:  s->handler[1].type = low; break;
-        case 1:  s->handler[1].type = high; break;
-        case 3:  s->handler[1].type = intr; break;
-        default: s->handler[1].type = input; break;
+        case 0:  s->line[1].type = low; break;
+        case 1:  s->line[1].type = high; break;
+        case 3:  s->line[1].type = intr; break;
+        default: s->line[1].type = input; break;
         }
         wm8753_input_update(s, 1);
         wm8753_int_update(s);
@@ -688,52 +700,64 @@
     return 0;
 }
 
-struct i2c_slave_s *wm8753_init(AudioState *audio)
+static int wm8753_rx(i2c_slave *i2c)
 {
-    struct wm8753_s *s = qemu_mallocz(sizeof(struct wm8753_s));
-    s->i2c.opaque = s;
-    s->i2c.tx = wm8753_tx;
-    s->i2c.start = wm8753_start;
+    return 0x00;
+}
 
+static void wm8753_gpio_set(void *opaque, int line, int level)
+{
+    struct wm8753_s *s = (struct wm8753_s *) opaque;
+    if (level)
+        s->intlevel |= 1 << line;
+    else
+        s->intlevel &= ~(1 << line);
+    wm8753_int_update(s);
+}
+
+i2c_slave *wm8753_init(i2c_bus *bus, AudioState *audio)
+{
+    struct wm8753_s *s = (struct wm8753_s *)
+            i2c_slave_init(bus, 0, sizeof(struct wm8753_s));
+    s->i2c.event = wm8753_event;
+    s->i2c.recv = wm8753_rx;
+    s->i2c.send = wm8753_tx;
+    s->gpio_in = qemu_allocate_irqs(wm8753_gpio_set, s, 8);
+
     AUD_register_card(audio, CODEC, &s->card);
     wm8753_reset(&s->i2c);
     return &s->i2c;
 }
 
-void wm8753_fini(struct i2c_slave_s *i2c)
+void wm8753_fini(i2c_slave *i2c)
 {
-    struct wm8753_s *s = (struct wm8753_s *) i2c->opaque;
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
     wm8753_reset(&s->i2c);
     AUD_remove_card(&s->card);
     qemu_free(s);
 }
 
-void wm8753_gpio_set(struct i2c_slave_s *i2c, int line, int level)
+qemu_irq *wm8753_gpio_in_get(i2c_slave *i2c)
 {
-    struct wm8753_s *s = (struct wm8753_s *) i2c->opaque;
-    if (level)
-        s->intlevel |= 1 << line;
-    else
-        s->intlevel &= ~(1 << line);
-    wm8753_int_update(s);
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
+    return s->gpio_in;
 }
 
-void wm8753_gpio_handler_set(struct i2c_slave_s *i2c, int line,
-                gpio_handler_t handler, void *opaque) {
-    struct wm8753_s *s = (struct wm8753_s *) i2c->opaque;
+void wm8753_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler)
+{
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
     if (line >= 8) {
         printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
         return;
     }
 
-    s->handler[line].fn = handler;
-    s->handler[line].opaque = opaque;
+    s->line[line].handler = handler;
 }
 
-void wm8753_data_req_set(struct i2c_slave_s *i2c,
+void wm8753_data_req_set(i2c_slave *i2c,
                 void (*data_req)(void *, int, int), void *opaque)
 {
-    struct wm8753_s *s = (struct wm8753_s *) i2c->opaque;
+    struct wm8753_s *s = (struct wm8753_s *) i2c;
     s->data_req = data_req;
     s->opaque = opaque;
 }

Deleted: trunk/src/host/qemu-neo1973/keymaps/zaurus
===================================================================
--- trunk/src/host/qemu-neo1973/keymaps/zaurus	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/keymaps/zaurus	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,26 +0,0 @@
-# Keymap for the Zaurus series devices
-include common
-slash 0x33 shift
-question 0x34 shift
-exclam 0x02 shift
-quotedbl 0x03 shift
-numbersign 0x04 shift
-dollar 0x05 shift
-percent 0x06 shift
-ampersand 0x07 shift
-apostrophe 0x08 shift
-parenleft 0x09 shift
-parenright 0x0a shift
-asciitilde 0x0b shift
-at 0x0c shift
-BackSpace 0xe
-Delete 0xe altgr
-Tab 0xf
-Caps_Lock 0xf altgr
-asciicircum 0x11 altgr
-equal 0x12 altgr
-plus 0x13 altgr
-bracketleft 0x14 altgr
-bracketright 0x15 altgr
-Page_Up 0xc8 altgr
-Page_Down 0xcd altgr

Modified: trunk/src/host/qemu-neo1973/keymaps.c
===================================================================
--- trunk/src/host/qemu-neo1973/keymaps.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/keymaps.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -84,7 +84,7 @@
 		*end_of_keysym = 0;
 		keysym = get_keysym(line);
 		if (keysym == 0) {
-                    		    fprintf(stderr, "Warning: unknown keysym %s\n", line);
+                    //		    fprintf(stderr, "Warning: unknown keysym %s\n", line);
 		} else {
 		    const char *rest = end_of_keysym + 1;
 		    int keycode = strtol(rest, NULL, 0);

Modified: trunk/src/host/qemu-neo1973/kqemu.c
===================================================================
--- trunk/src/host/qemu-neo1973/kqemu.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/kqemu.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -26,6 +26,9 @@
 #include <sys/mman.h>
 #include <sys/ioctl.h>
 #endif
+#ifdef HOST_SOLARIS
+#include <sys/ioccom.h>
+#endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -174,7 +177,8 @@
     kqemu_fd = open(KQEMU_DEVICE, O_RDWR);
 #endif
     if (kqemu_fd == KQEMU_INVALID_FD) {
-        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated\n", KQEMU_DEVICE);
+        fprintf(stderr, "Could not open '%s' - QEMU acceleration layer not activated: %s\n",
+                KQEMU_DEVICE, strerror(errno));
         return -1;
     }
     version = 0;
@@ -480,7 +484,7 @@
         cpu_x86_set_cpl(env, 0);
         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                                0, 0xffffffff, 
-                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_G_MASK | DESC_P_MASK |
                                DESC_S_MASK |
                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 

Deleted: trunk/src/host/qemu-neo1973/linux-2.6.9-qemu-fast.patch
===================================================================
--- trunk/src/host/qemu-neo1973/linux-2.6.9-qemu-fast.patch	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-2.6.9-qemu-fast.patch	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,70 +0,0 @@
---- linux-2.6.9/arch/i386/Kconfig	2004-10-18 23:53:22.000000000 +0200
-+++ linux-2.6.9-qemu/arch/i386/Kconfig	2004-12-07 21:56:49.000000000 +0100
-@@ -337,6 +337,14 @@ config X86_GENERIC
- 
- endif
- 
-+config QEMU
-+	bool "Kernel to run under QEMU"
-+	depends on EXPERIMENTAL
-+	help
-+	  Select this if you want to boot the kernel inside qemu-fast,
-+	  the non-mmu version of the x86 emulator.  See
-+	  <http://fabrice.bellard.free.fr/qemu/>.  Say N.
-+
- #
- # Define implied options from the CPU selection here
- #
---- linux-2.6.9/include/asm-i386/fixmap.h	2004-10-18 23:53:08.000000000 +0200
-+++ linux-2.6.9-qemu/include/asm-i386/fixmap.h	2004-12-07 23:16:11.000000000 +0100
-@@ -20,7 +20,11 @@
-  * Leave one empty page between vmalloc'ed areas and
-  * the start of the fixmap.
-  */
-+#ifdef CONFIG_QEMU
-+#define __FIXADDR_TOP   0xa7fff000
-+#else
- #define __FIXADDR_TOP	0xfffff000
-+#endif
- 
- #ifndef __ASSEMBLY__
- #include <linux/kernel.h>
---- linux-2.6.9/include/asm-i386/page.h	2004-10-18 23:53:22.000000000 +0200
-+++ linux-2.6.9-qemu/include/asm-i386/page.h	2004-12-07 21:56:49.000000000 +0100
-@@ -121,12 +121,19 @@ extern int sysctl_legacy_va_layout;
- #endif /* __ASSEMBLY__ */
- 
- #ifdef __ASSEMBLY__
-+#ifdef CONFIG_QEMU
-+#define __PAGE_OFFSET		(0x90000000)
-+#else
- #define __PAGE_OFFSET		(0xC0000000)
-+#endif /* QEMU */
-+#else
-+#ifdef CONFIG_QEMU
-+#define __PAGE_OFFSET		(0x90000000UL)
- #else
- #define __PAGE_OFFSET		(0xC0000000UL)
-+#endif /* QEMU */
- #endif
- 
--
- #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
- #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
- #define MAXMEM			(-__PAGE_OFFSET-__VMALLOC_RESERVE)
---- linux-2.6.9/include/asm-i386/param.h	2004-10-18 23:53:24.000000000 +0200
-+++ linux-2.6.9-qemu/include/asm-i386/param.h	2004-12-07 21:56:49.000000000 +0100
-@@ -2,7 +2,12 @@
- #define _ASMi386_PARAM_H
- 
- #ifdef __KERNEL__
--# define HZ		1000		/* Internal kernel timer frequency */
-+# include <linux/config.h>
-+# ifdef CONFIG_QEMU
-+#  define HZ		100
-+# else
-+#  define HZ		1000		/* Internal kernel timer frequency */
-+# endif
- # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
- # define CLOCKS_PER_SEC		(USER_HZ)	/* like times() */
- #endif

Added: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,115 @@
+/* default linux values for the selectors */
+#define __USER_DS	(1)
+
+struct target_pt_regs {
+	target_ulong r0;
+	target_ulong r1;
+	target_ulong r2;
+	target_ulong r3;
+	target_ulong r4;
+	target_ulong r5;
+	target_ulong r6;
+	target_ulong r7;
+	target_ulong r8;
+	target_ulong r19;
+	target_ulong r20;
+	target_ulong r21;
+	target_ulong r22;
+	target_ulong r23;
+	target_ulong r24;
+	target_ulong r25;
+	target_ulong r26;
+	target_ulong r27;
+	target_ulong r28;
+	target_ulong hae;
+/* JRP - These are the values provided to a0-a2 by PALcode */
+	target_ulong trap_a0;
+	target_ulong trap_a1;
+	target_ulong trap_a2;
+/* These are saved by PAL-code: */
+	target_ulong ps;
+	target_ulong pc;
+	target_ulong gp;
+	target_ulong r16;
+	target_ulong r17;
+	target_ulong r18;
+/* Those is needed by qemu to temporary store the user stack pointer */
+        target_ulong usp;
+        target_ulong unique;
+};
+
+#define TARGET_SEMOP           1
+#define TARGET_SEMGET          2
+#define TARGET_SEMCTL          3 
+#define TARGET_MSGSND          11 
+#define TARGET_MSGRCV          12
+#define TARGET_MSGGET          13
+#define TARGET_MSGCTL          14
+#define TARGET_SHMAT           21
+#define TARGET_SHMDT           22
+#define TARGET_SHMGET          23
+#define TARGET_SHMCTL          24
+
+struct target_msgbuf {
+	int mtype;
+	char mtext[1];
+};
+
+struct target_ipc_kludge {
+	unsigned int	msgp;	/* Really (struct msgbuf *) */
+	int msgtyp;
+};	
+
+struct target_ipc_perm {
+	int	key;
+	unsigned short	uid;
+	unsigned short	gid;
+	unsigned short	cuid;
+	unsigned short	cgid;
+	unsigned short	mode;
+	unsigned short	seq;
+};
+
+struct target_msqid_ds {
+	struct target_ipc_perm	msg_perm;
+	unsigned int		msg_first;	/* really struct target_msg* */
+	unsigned int		msg_last;	/* really struct target_msg* */
+	unsigned int		msg_stime;	/* really target_time_t */
+	unsigned int		msg_rtime;	/* really target_time_t */
+	unsigned int		msg_ctime;	/* really target_time_t */
+	unsigned int		wwait;		/* really struct wait_queue* */
+	unsigned int		rwait;		/* really struct wait_queue* */
+	unsigned short		msg_cbytes;
+	unsigned short		msg_qnum;
+	unsigned short		msg_qbytes;
+	unsigned short		msg_lspid;
+	unsigned short		msg_lrpid;
+};
+
+struct target_shmid_ds {
+	struct target_ipc_perm	shm_perm;
+	int			shm_segsz;
+	unsigned int		shm_atime;	/* really target_time_t */
+	unsigned int		shm_dtime;	/* really target_time_t */
+	unsigned int		shm_ctime;	/* really target_time_t */
+	unsigned short		shm_cpid;
+	unsigned short		shm_lpid;
+	short			shm_nattch;
+	unsigned short		shm_npages;
+	unsigned long		*shm_pages;
+	void 			*attaches;	/* really struct shm_desc * */
+};
+
+#define TARGET_IPC_RMID	0
+#define TARGET_IPC_SET	1
+#define TARGET_IPC_STAT	2
+
+union target_semun {
+    int val;
+    unsigned int buf;	/* really struct semid_ds * */
+    unsigned int array; /* really unsigned short * */
+    unsigned int __buf;	/* really struct seminfo * */
+    unsigned int __pad;	/* really void* */
+};
+
+#define UNAME_MACHINE "alpha"

Added: trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/syscall_nr.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,381 @@
+#define TARGET_NR_osf_syscall	  0	/* not implemented */
+#define TARGET_NR_exit		  1
+#define TARGET_NR_fork		  2
+#define TARGET_NR_read		  3
+#define TARGET_NR_write		  4
+#define TARGET_NR_osf_old_open	  5	/* not implemented */
+#define TARGET_NR_close		  6
+#define TARGET_NR_osf_wait4		  7
+#define TARGET_NR_osf_old_creat	  8	/* not implemented */
+#define TARGET_NR_link		  9
+#define TARGET_NR_unlink		 10
+#define TARGET_NR_osf_execve		 11	/* not implemented */
+#define TARGET_NR_chdir		 12
+#define TARGET_NR_fchdir		 13
+#define TARGET_NR_mknod		 14
+#define TARGET_NR_chmod		 15
+#define TARGET_NR_chown		 16
+#define TARGET_NR_brk		 17
+#define TARGET_NR_osf_getfsstat	 18	/* not implemented */
+#define TARGET_NR_lseek		 19
+#define TARGET_NR_getxpid		 20
+#define TARGET_NR_osf_mount		 21
+#define TARGET_NR_umount		 22
+#define TARGET_NR_setuid		 23
+#define TARGET_NR_getxuid		 24
+#define TARGET_NR_exec_with_loader	 25	/* not implemented */
+#define TARGET_NR_ptrace		 26
+#define TARGET_NR_osf_nrecvmsg	 27	/* not implemented */
+#define TARGET_NR_osf_nsendmsg	 28	/* not implemented */
+#define TARGET_NR_osf_nrecvfrom	 29	/* not implemented */
+#define TARGET_NR_osf_naccept	 30	/* not implemented */
+#define TARGET_NR_osf_ngetpeername	 31	/* not implemented */
+#define TARGET_NR_osf_ngetsockname	 32	/* not implemented */
+#define TARGET_NR_access		 33
+#define TARGET_NR_osf_chflags	 34	/* not implemented */
+#define TARGET_NR_osf_fchflags	 35	/* not implemented */
+#define TARGET_NR_sync		 36
+#define TARGET_NR_kill		 37
+#define TARGET_NR_osf_old_stat	 38	/* not implemented */
+#define TARGET_NR_setpgid		 39
+#define TARGET_NR_osf_old_lstat	 40	/* not implemented */
+#define TARGET_NR_dup		 41
+#define TARGET_NR_pipe		 42
+#define TARGET_NR_osf_set_program_attributes	43
+#define TARGET_NR_osf_profil		 44	/* not implemented */
+#define TARGET_NR_open		 45
+#define TARGET_NR_osf_old_sigaction	 46	/* not implemented */
+#define TARGET_NR_getxgid		 47
+#define TARGET_NR_osf_sigprocmask	 48
+#define TARGET_NR_osf_getlogin	 49	/* not implemented */
+#define TARGET_NR_osf_setlogin	 50	/* not implemented */
+#define TARGET_NR_acct		 51
+#define TARGET_NR_sigpending		 52
+
+#define TARGET_NR_ioctl		 54
+#define TARGET_NR_osf_reboot		 55	/* not implemented */
+#define TARGET_NR_osf_revoke		 56	/* not implemented */
+#define TARGET_NR_symlink		 57
+#define TARGET_NR_readlink		 58
+#define TARGET_NR_execve		 59
+#define TARGET_NR_umask		 60
+#define TARGET_NR_chroot		 61
+#define TARGET_NR_osf_old_fstat	 62	/* not implemented */
+#define TARGET_NR_getpgrp		 63
+#define TARGET_NR_getpagesize	 64
+#define TARGET_NR_osf_mremap		 65	/* not implemented */
+#define TARGET_NR_vfork		 66
+#define TARGET_NR_stat		 67
+#define TARGET_NR_lstat		 68
+#define TARGET_NR_osf_sbrk		 69	/* not implemented */
+#define TARGET_NR_osf_sstk		 70	/* not implemented */
+#define TARGET_NR_mmap		 71	/* OSF/1 mmap is superset of Linux */
+#define TARGET_NR_osf_old_vadvise	 72	/* not implemented */
+#define TARGET_NR_munmap		 73
+#define TARGET_NR_mprotect		 74
+#define TARGET_NR_madvise		 75
+#define TARGET_NR_vhangup		 76
+#define TARGET_NR_osf_kmodcall	 77	/* not implemented */
+#define TARGET_NR_osf_mincore	 78	/* not implemented */
+#define TARGET_NR_getgroups		 79
+#define TARGET_NR_setgroups		 80
+#define TARGET_NR_osf_old_getpgrp	 81	/* not implemented */
+#define TARGET_NR_setpgrp		 82	/* BSD alias for setpgid */
+#define TARGET_NR_osf_setitimer	 83
+#define TARGET_NR_osf_old_wait	 84	/* not implemented */
+#define TARGET_NR_osf_table		 85	/* not implemented */
+#define TARGET_NR_osf_getitimer	 86
+#define TARGET_NR_gethostname	 87
+#define TARGET_NR_sethostname	 88
+#define TARGET_NR_getdtablesize	 89
+#define TARGET_NR_dup2		 90
+#define TARGET_NR_fstat		 91
+#define TARGET_NR_fcntl		 92
+#define TARGET_NR_osf_select		 93
+#define TARGET_NR_poll		 94
+#define TARGET_NR_fsync		 95
+#define TARGET_NR_setpriority	 96
+#define TARGET_NR_socket		 97
+#define TARGET_NR_connect		 98
+#define TARGET_NR_accept		 99
+#define TARGET_NR_getpriority	100
+#define TARGET_NR_send		101
+#define TARGET_NR_recv		102
+#define TARGET_NR_sigreturn		103
+#define TARGET_NR_bind		104
+#define TARGET_NR_setsockopt		105
+#define TARGET_NR_listen		106
+#define TARGET_NR_osf_plock		107	/* not implemented */
+#define TARGET_NR_osf_old_sigvec	108	/* not implemented */
+#define TARGET_NR_osf_old_sigblock	109	/* not implemented */
+#define TARGET_NR_osf_old_sigsetmask	110	/* not implemented */
+#define TARGET_NR_sigsuspend		111
+#define TARGET_NR_osf_sigstack	112
+#define TARGET_NR_recvmsg		113
+#define TARGET_NR_sendmsg		114
+#define TARGET_NR_osf_old_vtrace	115	/* not implemented */
+#define TARGET_NR_osf_gettimeofday	116
+#define TARGET_NR_osf_getrusage	117
+#define TARGET_NR_getsockopt		118
+
+#define TARGET_NR_readv		120
+#define TARGET_NR_writev		121
+#define TARGET_NR_osf_settimeofday	122
+#define TARGET_NR_fchown		123
+#define TARGET_NR_fchmod		124
+#define TARGET_NR_recvfrom		125
+#define TARGET_NR_setreuid		126
+#define TARGET_NR_setregid		127
+#define TARGET_NR_rename		128
+#define TARGET_NR_truncate		129
+#define TARGET_NR_ftruncate		130
+#define TARGET_NR_flock		131
+#define TARGET_NR_setgid		132
+#define TARGET_NR_sendto		133
+#define TARGET_NR_shutdown		134
+#define TARGET_NR_socketpair		135
+#define TARGET_NR_mkdir		136
+#define TARGET_NR_rmdir		137
+#define TARGET_NR_osf_utimes		138
+#define TARGET_NR_osf_old_sigreturn	139	/* not implemented */
+#define TARGET_NR_osf_adjtime	140	/* not implemented */
+#define TARGET_NR_getpeername	141
+#define TARGET_NR_osf_gethostid	142	/* not implemented */
+#define TARGET_NR_osf_sethostid	143	/* not implemented */
+#define TARGET_NR_getrlimit		144
+#define TARGET_NR_setrlimit		145
+#define TARGET_NR_osf_old_killpg	146	/* not implemented */
+#define TARGET_NR_setsid		147
+#define TARGET_NR_quotactl		148
+#define TARGET_NR_osf_oldquota	149	/* not implemented */
+#define TARGET_NR_getsockname	150
+
+#define TARGET_NR_osf_pid_block	153	/* not implemented */
+#define TARGET_NR_osf_pid_unblock	154	/* not implemented */
+
+#define TARGET_NR_sigaction		156
+#define TARGET_NR_osf_sigwaitprim	157	/* not implemented */
+#define TARGET_NR_osf_nfssvc		158	/* not implemented */
+#define TARGET_NR_osf_getdirentries	159
+#define TARGET_NR_osf_statfs		160
+#define TARGET_NR_osf_fstatfs	161
+
+#define TARGET_NR_osf_asynch_daemon	163	/* not implemented */
+#define TARGET_NR_osf_getfh		164	/* not implemented */	
+#define TARGET_NR_osf_getdomainname	165
+#define TARGET_NR_setdomainname	166
+
+#define TARGET_NR_osf_exportfs	169	/* not implemented */
+
+#define TARGET_NR_osf_alt_plock	181	/* not implemented */
+
+#define TARGET_NR_osf_getmnt		184	/* not implemented */
+
+#define TARGET_NR_osf_alt_sigpending	187	/* not implemented */
+#define TARGET_NR_osf_alt_setsid	188	/* not implemented */
+
+#define TARGET_NR_osf_swapon		199
+#define TARGET_NR_msgctl		200
+#define TARGET_NR_msgget		201
+#define TARGET_NR_msgrcv		202
+#define TARGET_NR_msgsnd		203
+#define TARGET_NR_semctl		204
+#define TARGET_NR_semget		205
+#define TARGET_NR_semop		206
+#define TARGET_NR_osf_utsname	207
+#define TARGET_NR_lchown		208
+#define TARGET_NR_osf_shmat		209
+#define TARGET_NR_shmctl		210
+#define TARGET_NR_shmdt		211
+#define TARGET_NR_shmget		212
+#define TARGET_NR_osf_mvalid		213	/* not implemented */
+#define TARGET_NR_osf_getaddressconf	214	/* not implemented */
+#define TARGET_NR_osf_msleep		215	/* not implemented */
+#define TARGET_NR_osf_mwakeup	216	/* not implemented */
+#define TARGET_NR_msync		217
+#define TARGET_NR_osf_signal		218	/* not implemented */
+#define TARGET_NR_osf_utc_gettime	219	/* not implemented */
+#define TARGET_NR_osf_utc_adjtime	220	/* not implemented */
+
+#define TARGET_NR_osf_security	222	/* not implemented */
+#define TARGET_NR_osf_kloadcall	223	/* not implemented */
+
+#define TARGET_NR_getpgid		233
+#define TARGET_NR_getsid		234
+#define TARGET_NR_sigaltstack	235
+#define TARGET_NR_osf_waitid		236	/* not implemented */
+#define TARGET_NR_osf_priocntlset	237	/* not implemented */
+#define TARGET_NR_osf_sigsendset	238	/* not implemented */
+#define TARGET_NR_osf_set_speculative	239	/* not implemented */
+#define TARGET_NR_osf_msfs_syscall	240	/* not implemented */
+#define TARGET_NR_osf_sysinfo	241
+#define TARGET_NR_osf_uadmin		242	/* not implemented */
+#define TARGET_NR_osf_fuser		243	/* not implemented */
+#define TARGET_NR_osf_proplist_syscall    244
+#define TARGET_NR_osf_ntp_adjtime	245	/* not implemented */
+#define TARGET_NR_osf_ntp_gettime	246	/* not implemented */
+#define TARGET_NR_osf_pathconf	247	/* not implemented */
+#define TARGET_NR_osf_fpathconf	248	/* not implemented */
+
+#define TARGET_NR_osf_uswitch	250	/* not implemented */
+#define TARGET_NR_osf_usleep_thread	251
+#define TARGET_NR_osf_audcntl	252	/* not implemented */
+#define TARGET_NR_osf_audgen		253	/* not implemented */
+#define TARGET_NR_sysfs		254
+#define TARGET_NR_osf_subsys_info	255	/* not implemented */
+#define TARGET_NR_osf_getsysinfo	256
+#define TARGET_NR_osf_setsysinfo	257
+#define TARGET_NR_osf_afs_syscall	258	/* not implemented */
+#define TARGET_NR_osf_swapctl	259	/* not implemented */
+#define TARGET_NR_osf_memcntl	260	/* not implemented */
+#define TARGET_NR_osf_fdatasync	261	/* not implemented */
+
+
+/*
+ * Linux-specific system calls begin at 300
+ */
+#define TARGET_NR_bdflush		300
+#define TARGET_NR_sethae		301
+#define TARGET_NR_mount		302
+#define TARGET_NR_old_adjtimex	303
+#define TARGET_NR_swapoff		304
+#define TARGET_NR_getdents		305
+#define TARGET_NR_create_module	306
+#define TARGET_NR_init_module	307
+#define TARGET_NR_delete_module	308
+#define TARGET_NR_get_kernel_syms	309
+#define TARGET_NR_syslog		310
+#define TARGET_NR_reboot		311
+#define TARGET_NR_clone		312
+#define TARGET_NR_uselib		313
+#define TARGET_NR_mlock		314
+#define TARGET_NR_munlock		315
+#define TARGET_NR_mlockall		316
+#define TARGET_NR_munlockall		317
+#define TARGET_NR_sysinfo		318
+#define TARGET_NR__sysctl		319
+/* 320 was sys_idle.  */
+#define TARGET_NR_oldumount		321
+#define TARGET_NR_swapon		322
+#define TARGET_NR_times		323
+#define TARGET_NR_personality	324
+#define TARGET_NR_setfsuid		325
+#define TARGET_NR_setfsgid		326
+#define TARGET_NR_ustat		327
+#define TARGET_NR_statfs		328
+#define TARGET_NR_fstatfs		329
+#define TARGET_NR_sched_setparam		330
+#define TARGET_NR_sched_getparam		331
+#define TARGET_NR_sched_setscheduler		332
+#define TARGET_NR_sched_getscheduler		333
+#define TARGET_NR_sched_yield		334
+#define TARGET_NR_sched_get_priority_max	335
+#define TARGET_NR_sched_get_priority_min	336
+#define TARGET_NR_sched_rr_get_interval	337
+#define TARGET_NR_afs_syscall		338
+#define TARGET_NR_uname			339
+#define TARGET_NR_nanosleep			340
+#define TARGET_NR_mremap			341
+#define TARGET_NR_nfsservctl			342
+#define TARGET_NR_setresuid			343
+#define TARGET_NR_getresuid			344
+#define TARGET_NR_pciconfig_read		345
+#define TARGET_NR_pciconfig_write		346
+#define TARGET_NR_query_module		347
+#define TARGET_NR_prctl			348
+#define TARGET_NR_pread64			349
+#define TARGET_NR_pwrite64			350
+#define TARGET_NR_rt_sigreturn		351
+#define TARGET_NR_rt_sigaction		352
+#define TARGET_NR_rt_sigprocmask		353
+#define TARGET_NR_rt_sigpending		354
+#define TARGET_NR_rt_sigtimedwait		355
+#define TARGET_NR_rt_sigqueueinfo		356
+#define TARGET_NR_rt_sigsuspend		357
+#define TARGET_NR_select			358
+#define TARGET_NR_gettimeofday		359
+#define TARGET_NR_settimeofday		360
+#define TARGET_NR_getitimer			361
+#define TARGET_NR_setitimer			362
+#define TARGET_NR_utimes			363
+#define TARGET_NR_getrusage			364
+#define TARGET_NR_wait4			365
+#define TARGET_NR_adjtimex			366
+#define TARGET_NR_getcwd			367
+#define TARGET_NR_capget			368
+#define TARGET_NR_capset			369
+#define TARGET_NR_sendfile			370
+#define TARGET_NR_setresgid			371
+#define TARGET_NR_getresgid			372
+#define TARGET_NR_dipc			373
+#define TARGET_NR_pivot_root			374
+#define TARGET_NR_mincore			375
+#define TARGET_NR_pciconfig_iobase		376
+#define TARGET_NR_getdents64			377
+#define TARGET_NR_gettid			378
+#define TARGET_NR_readahead			379
+/* 380 is unused */
+#define TARGET_NR_tkill			381
+#define TARGET_NR_setxattr			382
+#define TARGET_NR_lsetxattr			383
+#define TARGET_NR_fsetxattr			384
+#define TARGET_NR_getxattr			385
+#define TARGET_NR_lgetxattr			386
+#define TARGET_NR_fgetxattr			387
+#define TARGET_NR_listxattr			388
+#define TARGET_NR_llistxattr			389
+#define TARGET_NR_flistxattr			390
+#define TARGET_NR_removexattr		391
+#define TARGET_NR_lremovexattr		392
+#define TARGET_NR_fremovexattr		393
+#define TARGET_NR_futex			394
+#define TARGET_NR_sched_setaffinity		395     
+#define TARGET_NR_sched_getaffinity		396
+#define TARGET_NR_tuxcall			397
+#define TARGET_NR_io_setup			398
+#define TARGET_NR_io_destroy			399
+#define TARGET_NR_io_getevents		400
+#define TARGET_NR_io_submit			401
+#define TARGET_NR_io_cancel			402
+#define TARGET_NR_exit_group			405
+#define TARGET_NR_lookup_dcookie		406
+#define TARGET_NR_sys_epoll_create		407
+#define TARGET_NR_sys_epoll_ctl		408
+#define TARGET_NR_sys_epoll_wait		409
+#define TARGET_NR_remap_file_pages		410
+#define TARGET_NR_set_tid_address		411
+#define TARGET_NR_restart_syscall		412
+#define TARGET_NR_fadvise64			413
+#define TARGET_NR_timer_create		414
+#define TARGET_NR_timer_settime		415
+#define TARGET_NR_timer_gettime		416
+#define TARGET_NR_timer_getoverrun		417
+#define TARGET_NR_timer_delete		418
+#define TARGET_NR_clock_settime		419
+#define TARGET_NR_clock_gettime		420
+#define TARGET_NR_clock_getres		421
+#define TARGET_NR_clock_nanosleep		422
+#define TARGET_NR_semtimedop			423
+#define TARGET_NR_tgkill			424
+#define TARGET_NR_stat64			425
+#define TARGET_NR_lstat64			426
+#define TARGET_NR_fstat64			427
+#define TARGET_NR_vserver			428
+#define TARGET_NR_mbind			429
+#define TARGET_NR_get_mempolicy		430
+#define TARGET_NR_set_mempolicy		431
+#define TARGET_NR_mq_open			432
+#define TARGET_NR_mq_unlink			433
+#define TARGET_NR_mq_timedsend		434
+#define TARGET_NR_mq_timedreceive		435
+#define TARGET_NR_mq_notify			436
+#define TARGET_NR_mq_getsetattr		437
+#define TARGET_NR_waitid			438
+#define TARGET_NR_add_key			439
+#define TARGET_NR_request_key		440
+#define TARGET_NR_keyctl			441
+#define TARGET_NR_ioprio_set			442
+#define TARGET_NR_ioprio_get			443
+#define TARGET_NR_inotify_init		444
+#define TARGET_NR_inotify_add_watch		445
+#define TARGET_NR_inotify_rm_watch		446

Added: trunk/src/host/qemu-neo1973/linux-user/alpha/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/alpha/termbits.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/alpha/termbits.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,265 @@
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define TARGET_NCCS 19
+struct target_termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_cc[TARGET_NCCS];		/* control characters */
+	cc_t c_line;			/* line discipline (== c_cc[19]) */
+	speed_t c_ispeed;		/* input speed */
+	speed_t c_ospeed;		/* output speed */
+};
+
+/* c_cc characters */
+#define TARGET_VEOF 0
+#define TARGET_VEOL 1
+#define TARGET_VEOL2 2
+#define TARGET_VERASE 3
+#define TARGET_VWERASE 4
+#define TARGET_VKILL 5
+#define TARGET_VREPRINT 6
+#define TARGET_VSWTC 7
+#define TARGET_VINTR 8
+#define TARGET_VQUIT 9
+#define TARGET_VSUSP 10
+#define TARGET_VSTART 12
+#define TARGET_VSTOP 13
+#define TARGET_VLNEXT 14
+#define TARGET_VDISCARD 15
+#define TARGET_VMIN 16
+#define TARGET_VTIME 17
+
+/* c_iflag bits */
+#define TARGET_IGNBRK	0000001
+#define TARGET_BRKINT	0000002
+#define TARGET_IGNPAR	0000004
+#define TARGET_PARMRK	0000010
+#define TARGET_INPCK	0000020
+#define TARGET_ISTRIP	0000040
+#define TARGET_INLCR	0000100
+#define TARGET_IGNCR	0000200
+#define TARGET_ICRNL	0000400
+#define TARGET_IXON	0001000
+#define TARGET_IXOFF	0002000
+#define TARGET_IXANY	0004000
+#define TARGET_IUCLC	0010000
+#define TARGET_IMAXBEL	0020000
+#define TARGET_IUTF8	0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST	0000001
+#define TARGET_ONLCR	0000002
+#define TARGET_OLCUC	0000004
+
+#define TARGET_OCRNL	0000010
+#define TARGET_ONOCR	0000020
+#define TARGET_ONLRET	0000040
+
+#define TARGET_OFILL	00000100
+#define TARGET_OFDEL	00000200
+#define TARGET_NLDLY	00001400
+#define   TARGET_NL0	00000000
+#define   TARGET_NL1	00000400
+#define   TARGET_NL2	00001000
+#define   TARGET_NL3	00001400
+#define TARGET_TABDLY	00006000
+#define   TARGET_TAB0	00000000
+#define   TARGET_TAB1	00002000
+#define   TARGET_TAB2	00004000
+#define   TARGET_TAB3	00006000
+#define TARGET_CRDLY	00030000
+#define   TARGET_CR0	00000000
+#define   TARGET_CR1	00010000
+#define   TARGET_CR2	00020000
+#define   TARGET_CR3	00030000
+#define TARGET_FFDLY	00040000
+#define   TARGET_FF0	00000000
+#define   TARGET_FF1	00040000
+#define TARGET_BSDLY	00100000
+#define   TARGET_BS0	00000000
+#define   TARGET_BS1	00100000
+#define TARGET_VTDLY	00200000
+#define   TARGET_VT0	00000000
+#define   TARGET_VT1	00200000
+#define TARGET_XTABS	01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD	0000037
+#define  TARGET_B0	0000000		/* hang up */
+#define  TARGET_B50	0000001
+#define  TARGET_B75	0000002
+#define  TARGET_B110	0000003
+#define  TARGET_B134	0000004
+#define  TARGET_B150	0000005
+#define  TARGET_B200	0000006
+#define  TARGET_B300	0000007
+#define  TARGET_B600	0000010
+#define  TARGET_B1200	0000011
+#define  TARGET_B1800	0000012
+#define  TARGET_B2400	0000013
+#define  TARGET_B4800	0000014
+#define  TARGET_B9600	0000015
+#define  TARGET_B19200	0000016
+#define  TARGET_B38400	0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CBAUDEX 0000000
+#define  TARGET_B57600   00020
+#define  TARGET_B115200  00021
+#define  TARGET_B230400  00022
+#define  TARGET_B460800  00023
+#define  TARGET_B500000  00024
+#define  TARGET_B576000  00025
+#define  TARGET_B921600  00026
+#define TARGET_B1000000  00027
+#define TARGET_B1152000  00030
+#define TARGET_B1500000  00031
+#define TARGET_B2000000  00032
+#define TARGET_B2500000  00033
+#define TARGET_B3000000  00034
+#define TARGET_B3500000  00035
+#define TARGET_B4000000  00036
+
+#define TARGET_CSIZE	00001400
+#define   TARGET_CS5	00000000
+#define   TARGET_CS6	00000400
+#define   TARGET_CS7	00001000
+#define   TARGET_CS8	00001400
+
+#define TARGET_CSTOPB	00002000
+#define TARGET_CREAD	00004000
+#define TARGET_PARENB	00010000
+#define TARGET_PARODD	00020000
+#define TARGET_HUPCL	00040000
+
+#define TARGET_CLOCAL	00100000
+#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define TARGET_CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG	0x00000080
+#define TARGET_ICANON	0x00000100
+#define TARGET_XCASE	0x00004000
+#define TARGET_ECHO	0x00000008
+#define TARGET_ECHOE	0x00000002
+#define TARGET_ECHOK	0x00000004
+#define TARGET_ECHONL	0x00000010
+#define TARGET_NOFLSH	0x80000000
+#define TARGET_TOSTOP	0x00400000
+#define TARGET_ECHOCTL	0x00000040
+#define TARGET_ECHOPRT	0x00000020
+#define TARGET_ECHOKE	0x00000001
+#define TARGET_FLUSHO	0x00800000
+#define TARGET_PENDIN	0x20000000
+#define TARGET_IEXTEN	0x00000400
+
+#define TARGET_FIOCLEX		_IO('f', 1)
+#define TARGET_FIONCLEX	_IO('f', 2)
+#define TARGET_FIOASYNC	_IOW('f', 125, int)
+#define TARGET_FIONBIO		_IOW('f', 126, int)
+#define TARGET_FIONREAD	_IOR('f', 127, int)
+#define TARGET_TIOCINQ		FIONREAD
+#define TARGET_FIOQSIZE	_IOR('f', 128, loff_t)
+
+#define TARGET_TIOCGETP	_IOR('t', 8, struct sgttyb)
+#define TARGET_TIOCSETP	_IOW('t', 9, struct sgttyb)
+#define TARGET_TIOCSETN	_IOW('t', 10, struct sgttyb)	/* TIOCSETP wo flush */
+
+#define TARGET_TIOCSETC	_IOW('t', 17, struct tchars)
+#define TARGET_TIOCGETC	_IOR('t', 18, struct tchars)
+#define TARGET_TCGETS		_IOR('t', 19, struct termios)
+#define TARGET_TCSETS		_IOW('t', 20, struct termios)
+#define TARGET_TCSETSW		_IOW('t', 21, struct termios)
+#define TARGET_TCSETSF		_IOW('t', 22, struct termios)
+
+#define TARGET_TCGETA		_IOR('t', 23, struct termio)
+#define TARGET_TCSETA		_IOW('t', 24, struct termio)
+#define TARGET_TCSETAW		_IOW('t', 25, struct termio)
+#define TARGET_TCSETAF		_IOW('t', 28, struct termio)
+
+#define TARGET_TCSBRK		_IO('t', 29)
+#define TARGET_TCXONC		_IO('t', 30)
+#define TARGET_TCFLSH		_IO('t', 31)
+
+#define TARGET_TIOCSWINSZ	_IOW('t', 103, struct winsize)
+#define TARGET_TIOCGWINSZ	_IOR('t', 104, struct winsize)
+#define	TARGET_TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
+#define	TARGET_TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
+#define TARGET_TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TARGET_TIOCGLTC	_IOR('t', 116, struct ltchars)
+#define TARGET_TIOCSLTC	_IOW('t', 117, struct ltchars)
+#define TARGET_TIOCSPGRP	_IOW('t', 118, int)
+#define TARGET_TIOCGPGRP	_IOR('t', 119, int)
+
+#define TARGET_TIOCEXCL	0x540C
+#define TARGET_TIOCNXCL	0x540D
+#define TARGET_TIOCSCTTY	0x540E
+
+#define TARGET_TIOCSTI		0x5412
+#define TARGET_TIOCMGET	0x5415
+#define TARGET_TIOCMBIS	0x5416
+#define TARGET_TIOCMBIC	0x5417
+#define TARGET_TIOCMSET	0x5418
+# define TARGET_TIOCM_LE	0x001
+# define TARGET_TIOCM_DTR	0x002
+# define TARGET_TIOCM_RTS	0x004
+# define TARGET_TIOCM_ST	0x008
+# define TARGET_TIOCM_SR	0x010
+# define TARGET_TIOCM_CTS	0x020
+# define TARGET_TIOCM_CAR	0x040
+# define TARGET_TIOCM_RNG	0x080
+# define TARGET_TIOCM_DSR	0x100
+# define TARGET_TIOCM_CD	TIOCM_CAR
+# define TARGET_TIOCM_RI	TIOCM_RNG
+# define TARGET_TIOCM_OUT1	0x2000
+# define TARGET_TIOCM_OUT2	0x4000
+# define TARGET_TIOCM_LOOP	0x8000
+
+#define TARGET_TIOCGSOFTCAR	0x5419
+#define TARGET_TIOCSSOFTCAR	0x541A
+#define TARGET_TIOCLINUX	0x541C
+#define TARGET_TIOCCONS	0x541D
+#define TARGET_TIOCGSERIAL	0x541E
+#define TARGET_TIOCSSERIAL	0x541F
+#define TARGET_TIOCPKT		0x5420
+# define TARGET_TIOCPKT_DATA		 0
+# define TARGET_TIOCPKT_FLUSHREAD	 1
+# define TARGET_TIOCPKT_FLUSHWRITE	 2
+# define TARGET_TIOCPKT_STOP		 4
+# define TARGET_TIOCPKT_START		 8
+# define TARGET_TIOCPKT_NOSTOP		16
+# define TARGET_TIOCPKT_DOSTOP		32
+
+
+#define TARGET_TIOCNOTTY	0x5422
+#define TARGET_TIOCSETD	0x5423
+#define TARGET_TIOCGETD	0x5424
+#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */
+#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */
+#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TARGET_TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TARGET_TIOCSERCONFIG	0x5453
+#define TARGET_TIOCSERGWILD	0x5454
+#define TARGET_TIOCSERSWILD	0x5455
+#define TARGET_TIOCGLCKTRMIOS	0x5456
+#define TARGET_TIOCSLCKTRMIOS	0x5457
+#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP	0x545E  /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP	0x545F  /* Set Hayes ESP configuration */
+

Deleted: trunk/src/host/qemu-neo1973/linux-user/arm-semi.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/arm-semi.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/arm-semi.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,235 +0,0 @@
-/*
- *  Arm "Angel" semihosting syscalls
- * 
- *  Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program 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 General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "qemu.h"
-
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
-
-#define SYS_OPEN        0x01
-#define SYS_CLOSE       0x02
-#define SYS_WRITEC      0x03
-#define SYS_WRITE0      0x04
-#define SYS_WRITE       0x05
-#define SYS_READ        0x06
-#define SYS_READC       0x07
-#define SYS_ISTTY       0x09
-#define SYS_SEEK        0x0a
-#define SYS_FLEN        0x0c
-#define SYS_TMPNAM      0x0d
-#define SYS_REMOVE      0x0e
-#define SYS_RENAME      0x0f
-#define SYS_CLOCK       0x10
-#define SYS_TIME        0x11
-#define SYS_SYSTEM      0x12
-#define SYS_ERRNO       0x13
-#define SYS_GET_CMDLINE 0x15
-#define SYS_HEAPINFO    0x16
-#define SYS_EXIT        0x18
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-int open_modeflags[12] = {
-    O_RDONLY,
-    O_RDONLY | O_BINARY,
-    O_RDWR,
-    O_RDWR | O_BINARY,
-    O_WRONLY | O_CREAT | O_TRUNC,
-    O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
-    O_RDWR | O_CREAT | O_TRUNC,
-    O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
-    O_WRONLY | O_CREAT | O_APPEND,
-    O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
-    O_RDWR | O_CREAT | O_APPEND,
-    O_RDWR | O_CREAT | O_APPEND | O_BINARY
-};
-
-static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
-{
-  if (code == (uint32_t)-1)
-      ts->swi_errno = errno;
-  return code;
-}
-
-#define ARG(n) tget32(args + (n) * 4)
-#define SET_ARG(n, val) tput32(args + (n) * 4,val)
-uint32_t do_arm_semihosting(CPUState *env)
-{
-    target_ulong args;
-    char * s;
-    int nr;
-    uint32_t ret;
-    TaskState *ts = env->opaque;
-
-    nr = env->regs[0];
-    args = env->regs[1];
-    switch (nr) {
-    case SYS_OPEN:
-        s = (char *)g2h(ARG(0));
-        if (ARG(1) >= 12)
-          return (uint32_t)-1;
-        if (strcmp(s, ":tt") == 0) {
-            if (ARG(1) < 4)
-                return STDIN_FILENO;
-            else
-                return STDOUT_FILENO;
-        }
-        return set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
-    case SYS_CLOSE:
-        return set_swi_errno(ts, close(ARG(0)));
-    case SYS_WRITEC:
-        {
-          char c = tget8(args);
-          /* Write to debug console.  stderr is near enough.  */
-          return write(STDERR_FILENO, &c, 1);
-        }
-    case SYS_WRITE0:
-        s = lock_user_string(args);
-        ret = write(STDERR_FILENO, s, strlen(s));
-        unlock_user(s, args, 0);
-        return ret;
-    case SYS_WRITE:
-        ret = set_swi_errno(ts, write(ARG(0), g2h(ARG(1)), ARG(2)));
-        if (ret == (uint32_t)-1)
-            return -1;
-        return ARG(2) - ret;
-    case SYS_READ:
-        ret = set_swi_errno(ts, read(ARG(0), g2h(ARG(1)), ARG(2)));
-        if (ret == (uint32_t)-1)
-            return -1;
-        return ARG(2) - ret;
-    case SYS_READC:
-       /* XXX: Read from debug cosole. Not implemented.  */
-        return 0;
-    case SYS_ISTTY:
-        return isatty(ARG(0));
-    case SYS_SEEK:
-        ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
-	if (ret == (uint32_t)-1)
-	  return -1;
-	return 0;
-    case SYS_FLEN:
-        {
-            struct stat buf;
-            ret = set_swi_errno(ts, fstat(ARG(0), &buf));
-            if (ret == (uint32_t)-1)
-                return -1;
-            return buf.st_size;
-        }
-    case SYS_TMPNAM:
-        /* XXX: Not implemented.  */
-        return -1;
-    case SYS_REMOVE:
-        return set_swi_errno(ts, remove((char *)g2h(ARG(0))));
-    case SYS_RENAME:
-        return set_swi_errno(ts, rename((char *)g2h(ARG(0)),
-                             (char *)g2h(ARG(2))));
-    case SYS_CLOCK:
-        return clock() / (CLOCKS_PER_SEC / 100);
-    case SYS_TIME:
-        return set_swi_errno(ts, time(NULL));
-    case SYS_SYSTEM:
-        return set_swi_errno(ts, system((char *)g2h(ARG(0))));
-    case SYS_ERRNO:
-        return ts->swi_errno;
-    case SYS_GET_CMDLINE:
-        /* Build a commandline from the original argv.  */
-        {
-            char **arg = ts->info->host_argv;
-            int len = ARG(1);
-            /* lock the buffer on the ARM side */
-            char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
-
-            s = cmdline_buffer;
-            while (*arg && len > 2) {
-                int n = strlen(*arg);
-
-                if (s != cmdline_buffer) {
-                    *(s++) = ' ';
-                    len--;
-                }
-                if (n >= len)
-                    n = len - 1;
-                memcpy(s, *arg, n);
-                s += n;
-                len -= n;
-                arg++;
-            }
-            /* Null terminate the string.  */
-            *s = 0;
-            len = s - cmdline_buffer;
-
-            /* Unlock the buffer on the ARM side.  */
-            unlock_user(cmdline_buffer, ARG(0), len);
-
-            /* Adjust the commandline length argument.  */
-            SET_ARG(1, len);
-
-            /* Return success if commandline fit into buffer.  */
-            return *arg ? -1 : 0;
-        }
-    case SYS_HEAPINFO:
-        {
-            uint32_t *ptr;
-            uint32_t limit;
-
-            /* Some C llibraries assume the heap immediately follows .bss, so
-               allocate it using sbrk.  */
-            if (!ts->heap_limit) {
-                long ret;
-
-                ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
-                /* Try a big heap, and reduce the size if that fails.  */
-                for (;;) {
-                    ret = do_brk(limit);
-                    if (ret != -1)
-                        break;
-                    limit = (ts->heap_base >> 1) + (limit >> 1);
-                }
-                ts->heap_limit = limit;
-            }
-              
-            page_unprotect_range (ARG(0), 32);
-            ptr = (uint32_t *)g2h(ARG(0));
-            ptr[0] = tswap32(ts->heap_base);
-            ptr[1] = tswap32(ts->heap_limit);
-            ptr[2] = tswap32(ts->stack_base);
-            ptr[3] = tswap32(0); /* Stack limit.  */
-            return 0;
-        }
-    case SYS_EXIT:
-        exit(0);
-    default:
-        fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-        cpu_dump_state(env, stderr, fprintf, 0);
-        abort();
-    }
-}
-

Modified: trunk/src/host/qemu-neo1973/linux-user/elfload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/elfload.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/elfload.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -44,6 +44,23 @@
   return global_env->cpuid_features;
 }
 
+#ifdef TARGET_X86_64
+#define ELF_START_MMAP 0x2aaaaab000ULL
+#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
+
+#define ELF_CLASS      ELFCLASS64
+#define ELF_DATA       ELFDATA2LSB
+#define ELF_ARCH       EM_X86_64
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+    regs->rax = 0;
+    regs->rsp = infop->start_stack;
+    regs->rip = infop->entry;
+}
+
+#else
+
 #define ELF_START_MMAP 0x80000000
 
 /*
@@ -72,6 +89,7 @@
        A value of 0 tells we have no such handler.  */
     regs->edx = 0;
 }
+#endif
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
@@ -177,9 +195,20 @@
 
 #define ELF_START_MMAP 0x80000000
 
+#ifdef TARGET_PPC64
+
+#define elf_check_arch(x) ( (x) == EM_PPC64 )
+
+#define ELF_CLASS	ELFCLASS64
+
+#else
+
 #define elf_check_arch(x) ( (x) == EM_PPC )
 
 #define ELF_CLASS	ELFCLASS32
+
+#endif
+
 #ifdef TARGET_WORDS_BIGENDIAN
 #define ELF_DATA	ELFDATA2MSB
 #else
@@ -222,9 +251,18 @@
 {
     target_ulong pos = infop->start_stack;
     target_ulong tmp;
+#ifdef TARGET_PPC64
+    target_ulong entry, toc;
+#endif
 
     _regs->msr = 1 << MSR_PR; /* Set user mode */
     _regs->gpr[1] = infop->start_stack;
+#ifdef TARGET_PPC64
+    entry = ldq_raw(infop->entry) + infop->load_addr;
+    toc = ldq_raw(infop->entry + 8) + infop->load_addr;
+    _regs->gpr[2] = toc;
+    infop->entry = entry;
+#endif
     _regs->nip = infop->entry;
     /* Note that isn't exactly what regular kernel does
      * but this is what the ABI wants and is needed to allow
@@ -313,6 +351,31 @@
 
 #endif
 
+#ifdef TARGET_ALPHA
+
+#define ELF_START_MMAP (0x30000000000ULL)
+
+#define elf_check_arch(x) ( (x) == ELF_ARCH )
+
+#define ELF_CLASS      ELFCLASS64
+#define ELF_DATA       ELFDATA2MSB
+#define ELF_ARCH       EM_ALPHA
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+    regs->pc = infop->entry;
+    regs->ps = 8;
+    regs->usp = infop->start_stack;
+    regs->unique = infop->start_data; /* ? */
+    printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n",
+           regs->unique, infop->start_data);
+}
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE        8192
+
+#endif /* TARGET_ALPHA */
+
 #ifndef ELF_PLATFORM
 #define ELF_PLATFORM (NULL)
 #endif
@@ -431,11 +494,11 @@
     bswaptls(&shdr->sh_entsize);
 }
 
-static void bswap_sym(Elf32_Sym *sym)
+static void bswap_sym(struct elf_sym *sym)
 {
     bswap32s(&sym->st_name);
-    bswap32s(&sym->st_value);
-    bswap32s(&sym->st_size);
+    bswaptls(&sym->st_value);
+    bswaptls(&sym->st_size);
     bswap16s(&sym->st_shndx);
 }
 #endif
@@ -892,6 +955,7 @@
     unsigned long elf_entry, interp_load_addr = 0;
     int status;
     unsigned long start_code, end_code, end_data;
+    unsigned long reloc_func_desc = 0;
     unsigned long elf_stack;
     char passed_fileno[6];
 
@@ -1156,6 +1220,7 @@
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
+                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1188,6 +1253,7 @@
 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
 					    &interp_load_addr);
 	}
+        reloc_func_desc = interp_load_addr;
 
 	close(interpreter_fd);
 	free(elf_interpreter);

Modified: trunk/src/host/qemu-neo1973/linux-user/flatload.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/flatload.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/flatload.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -393,6 +393,7 @@
     int i, rev, relocs = 0;
     target_ulong fpos;
     target_ulong start_code, end_code;
+    target_ulong indx_len;
 
     hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
 
@@ -443,6 +444,11 @@
     if (extra < bss_len + stack_len)
         extra = bss_len + stack_len;
 
+    /* Add space for library base pointers.  Make sure this does not
+       misalign the  doesn't misalign the data segment.  */
+    indx_len = MAX_SHARED_LIBS * sizeof(target_ulong);
+    indx_len = (indx_len + 15) & ~(target_ulong)15;
+
     /*
      * there are a couple of cases here,  the separate code/data
      * case,  and then the fully copied to RAM case which lumps
@@ -462,8 +468,7 @@
             return -1;
         }
 
-        realdatastart = target_mmap(0, data_len + extra +
-                                    MAX_SHARED_LIBS * sizeof(target_ulong),
+        realdatastart = target_mmap(0, data_len + extra + indx_len,
                                     PROT_READ|PROT_WRITE|PROT_EXEC,
                                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
@@ -471,7 +476,7 @@
             fprintf(stderr, "Unable to allocate RAM for process data\n");
             return realdatastart;
         }
-        datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong);
+        datapos = realdatastart + indx_len;
 
         DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
                         (int)(data_len + bss_len + stack_len), (int)datapos);
@@ -498,8 +503,7 @@
 
     } else {
 
-        textpos = target_mmap(0, text_len + data_len + extra +
-                              MAX_SHARED_LIBS * sizeof(target_ulong),
+        textpos = target_mmap(0, text_len + data_len + extra + indx_len,
                               PROT_READ | PROT_EXEC | PROT_WRITE,
                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
         if (textpos == -1 ) {
@@ -508,9 +512,8 @@
         }
 
         realdatastart = textpos + ntohl(hdr->data_start);
-        datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong);
-        reloc = (textpos + ntohl(hdr->reloc_start) +
-                 MAX_SHARED_LIBS * sizeof(target_ulong));
+        datapos = realdatastart + indx_len;
+        reloc = (textpos + ntohl(hdr->reloc_start) + indx_len);
         memp = textpos;
 
 #ifdef CONFIG_BINFMT_ZFLAT
@@ -756,6 +759,13 @@
     p = copy_strings(p, bprm->argc, bprm->argv);
     /* Align stack.  */
     sp = p & ~(target_ulong)(sizeof(target_ulong) - 1);
+    /* Enforce final stack alignment of 16 bytes.  This is sufficient
+       for all current targets, and excess alignment is harmless.  */
+    stack_len = bprm->envc + bprm->argc + 2;
+    stack_len += 3;	/* argc, arvg, argp */
+    stack_len *= sizeof(target_ulong);
+    if ((sp + stack_len) & 15)
+        sp -= 16 - ((sp + stack_len) & 15);
     sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
     
     /* Fake some return addresses to ensure the call chain will

Added: trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,221 @@
+/* default linux values for the selectors */
+#define __USER_CS	(0x23)
+#define __USER_DS	(0x2B)
+
+struct target_pt_regs {
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	int  xds;
+	int  xes;
+	long orig_eax;
+	long eip;
+	int  xcs;
+	long eflags;
+	long esp;
+	int  xss;
+};
+
+/* ioctls */
+
+#define TARGET_LDT_ENTRIES      8192
+#define TARGET_LDT_ENTRY_SIZE	8
+
+#define TARGET_GDT_ENTRY_TLS_ENTRIES   3
+#define TARGET_GDT_ENTRY_TLS_MIN       6
+#define TARGET_GDT_ENTRY_TLS_MAX       (TARGET_GDT_ENTRY_TLS_MIN + TARGET_GDT_ENTRY_TLS_ENTRIES - 1)
+
+struct target_modify_ldt_ldt_s {
+    unsigned int  entry_number;
+    target_ulong base_addr;
+    unsigned int limit;
+    unsigned int flags;
+};
+
+/* vm86 defines */
+
+#define TARGET_BIOSSEG		0x0f000
+
+#define TARGET_CPU_086		0
+#define TARGET_CPU_186		1
+#define TARGET_CPU_286		2
+#define TARGET_CPU_386		3
+#define TARGET_CPU_486		4
+#define TARGET_CPU_586		5
+
+#define TARGET_VM86_SIGNAL	0	/* return due to signal */
+#define TARGET_VM86_UNKNOWN	1	/* unhandled GP fault - IO-instruction or similar */
+#define TARGET_VM86_INTx	2	/* int3/int x instruction (ARG = x) */
+#define TARGET_VM86_STI	3	/* sti/popf/iret instruction enabled virtual interrupts */
+
+/*
+ * Additional return values when invoking new vm86()
+ */
+#define TARGET_VM86_PICRETURN	4	/* return due to pending PIC request */
+#define TARGET_VM86_TRAP	6	/* return due to DOS-debugger request */
+
+/*
+ * function codes when invoking new vm86()
+ */
+#define TARGET_VM86_PLUS_INSTALL_CHECK	0
+#define TARGET_VM86_ENTER		1
+#define TARGET_VM86_ENTER_NO_BYPASS	2
+#define	TARGET_VM86_REQUEST_IRQ	3
+#define TARGET_VM86_FREE_IRQ		4
+#define TARGET_VM86_GET_IRQ_BITS	5
+#define TARGET_VM86_GET_AND_RESET_IRQ	6
+
+/*
+ * This is the stack-layout seen by the user space program when we have
+ * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout
+ * is 'kernel_vm86_regs' (see below).
+ */
+
+struct target_vm86_regs {
+/*
+ * normal regs, with special meaning for the segment descriptors..
+ */
+	target_long ebx;
+	target_long ecx;
+	target_long edx;
+	target_long esi;
+	target_long edi;
+	target_long ebp;
+	target_long eax;
+	target_long __null_ds;
+	target_long __null_es;
+	target_long __null_fs;
+	target_long __null_gs;
+	target_long orig_eax;
+	target_long eip;
+	unsigned short cs, __csh;
+	target_long eflags;
+	target_long esp;
+	unsigned short ss, __ssh;
+/*
+ * these are specific to v86 mode:
+ */
+	unsigned short es, __esh;
+	unsigned short ds, __dsh;
+	unsigned short fs, __fsh;
+	unsigned short gs, __gsh;
+};
+
+struct target_revectored_struct {
+	target_ulong __map[8];			/* 256 bits */
+};
+
+struct target_vm86_struct {
+	struct target_vm86_regs regs;
+	target_ulong flags;
+	target_ulong screen_bitmap;
+	target_ulong cpu_type;
+	struct target_revectored_struct int_revectored;
+	struct target_revectored_struct int21_revectored;
+};
+
+/*
+ * flags masks
+ */
+#define TARGET_VM86_SCREEN_BITMAP	0x0001
+
+struct target_vm86plus_info_struct {
+        target_ulong flags;
+#define TARGET_force_return_for_pic (1 << 0)
+#define TARGET_vm86dbg_active       (1 << 1)  /* for debugger */
+#define TARGET_vm86dbg_TFpendig     (1 << 2)  /* for debugger */
+#define TARGET_is_vm86pus           (1 << 31) /* for vm86 internal use */
+	unsigned char vm86dbg_intxxtab[32];   /* for debugger */
+};
+
+struct target_vm86plus_struct {
+	struct target_vm86_regs regs;
+	target_ulong flags;
+	target_ulong screen_bitmap;
+	target_ulong cpu_type;
+	struct target_revectored_struct int_revectored;
+	struct target_revectored_struct int21_revectored;
+	struct target_vm86plus_info_struct vm86plus;
+};
+
+/* ipcs */
+
+#define TARGET_SEMOP           1
+#define TARGET_SEMGET          2
+#define TARGET_SEMCTL          3 
+#define TARGET_MSGSND          11 
+#define TARGET_MSGRCV          12
+#define TARGET_MSGGET          13
+#define TARGET_MSGCTL          14
+#define TARGET_SHMAT           21
+#define TARGET_SHMDT           22
+#define TARGET_SHMGET          23
+#define TARGET_SHMCTL          24
+
+struct target_msgbuf {
+	int mtype;
+	char mtext[1];
+};
+
+struct target_ipc_kludge {
+	unsigned int	msgp;	/* Really (struct msgbuf *) */
+	int msgtyp;
+};	
+
+struct target_ipc_perm {
+	int	key;
+	unsigned short	uid;
+	unsigned short	gid;
+	unsigned short	cuid;
+	unsigned short	cgid;
+	unsigned short	mode;
+	unsigned short	seq;
+};
+
+struct target_msqid_ds {
+	struct target_ipc_perm	msg_perm;
+	unsigned int		msg_first;	/* really struct target_msg* */
+	unsigned int		msg_last;	/* really struct target_msg* */
+	unsigned int		msg_stime;	/* really target_time_t */
+	unsigned int		msg_rtime;	/* really target_time_t */
+	unsigned int		msg_ctime;	/* really target_time_t */
+	unsigned int		wwait;		/* really struct wait_queue* */
+	unsigned int		rwait;		/* really struct wait_queue* */
+	unsigned short		msg_cbytes;
+	unsigned short		msg_qnum;
+	unsigned short		msg_qbytes;
+	unsigned short		msg_lspid;
+	unsigned short		msg_lrpid;
+};
+
+struct target_shmid_ds {
+	struct target_ipc_perm	shm_perm;
+	int			shm_segsz;
+	unsigned int		shm_atime;	/* really target_time_t */
+	unsigned int		shm_dtime;	/* really target_time_t */
+	unsigned int		shm_ctime;	/* really target_time_t */
+	unsigned short		shm_cpid;
+	unsigned short		shm_lpid;
+	short			shm_nattch;
+	unsigned short		shm_npages;
+	unsigned long		*shm_pages;
+	void 			*attaches;	/* really struct shm_desc * */
+};
+
+#define TARGET_IPC_RMID	0
+#define TARGET_IPC_SET	1
+#define TARGET_IPC_STAT	2
+
+union target_semun {
+    int val;
+    unsigned int buf;	/* really struct semid_ds * */
+    unsigned int array; /* really unsigned short * */
+    unsigned int __buf;	/* really struct seminfo * */
+    unsigned int __pad;	/* really void* */
+};
+
+#define UNAME_MACHINE "i686"

Added: trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/syscall_nr.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,274 @@
+/*
+ * This file contains the system call numbers.
+ */
+
+#define TARGET_NR_restart_syscall      0
+#define TARGET_NR_exit		  1
+#define TARGET_NR_fork		  2
+#define TARGET_NR_read		  3
+#define TARGET_NR_write		  4
+#define TARGET_NR_open		  5
+#define TARGET_NR_close		  6
+#define TARGET_NR_waitpid		  7
+#define TARGET_NR_creat		  8
+#define TARGET_NR_link		  9
+#define TARGET_NR_unlink		 10
+#define TARGET_NR_execve		 11
+#define TARGET_NR_chdir		 12
+#define TARGET_NR_time		 13
+#define TARGET_NR_mknod		 14
+#define TARGET_NR_chmod		 15
+#define TARGET_NR_lchown		 16
+#define TARGET_NR_break		 17
+#define TARGET_NR_oldstat		 18
+#define TARGET_NR_lseek		 19
+#define TARGET_NR_getpid		 20
+#define TARGET_NR_mount		 21
+#define TARGET_NR_umount		 22
+#define TARGET_NR_setuid		 23
+#define TARGET_NR_getuid		 24
+#define TARGET_NR_stime		 25
+#define TARGET_NR_ptrace		 26
+#define TARGET_NR_alarm		 27
+#define TARGET_NR_oldfstat		 28
+#define TARGET_NR_pause		 29
+#define TARGET_NR_utime		 30
+#define TARGET_NR_stty		 31
+#define TARGET_NR_gtty		 32
+#define TARGET_NR_access		 33
+#define TARGET_NR_nice		 34
+#define TARGET_NR_ftime		 35
+#define TARGET_NR_sync		 36
+#define TARGET_NR_kill		 37
+#define TARGET_NR_rename		 38
+#define TARGET_NR_mkdir		 39
+#define TARGET_NR_rmdir		 40
+#define TARGET_NR_dup		 41
+#define TARGET_NR_pipe		 42
+#define TARGET_NR_times		 43
+#define TARGET_NR_prof		 44
+#define TARGET_NR_brk		 45
+#define TARGET_NR_setgid		 46
+#define TARGET_NR_getgid		 47
+#define TARGET_NR_signal		 48
+#define TARGET_NR_geteuid		 49
+#define TARGET_NR_getegid		 50
+#define TARGET_NR_acct		 51
+#define TARGET_NR_umount2		 52
+#define TARGET_NR_lock		 53
+#define TARGET_NR_ioctl		 54
+#define TARGET_NR_fcntl		 55
+#define TARGET_NR_mpx		 56
+#define TARGET_NR_setpgid		 57
+#define TARGET_NR_ulimit		 58
+#define TARGET_NR_oldolduname	 59
+#define TARGET_NR_umask		 60
+#define TARGET_NR_chroot		 61
+#define TARGET_NR_ustat		 62
+#define TARGET_NR_dup2		 63
+#define TARGET_NR_getppid		 64
+#define TARGET_NR_getpgrp		 65
+#define TARGET_NR_setsid		 66
+#define TARGET_NR_sigaction		 67
+#define TARGET_NR_sgetmask		 68
+#define TARGET_NR_ssetmask		 69
+#define TARGET_NR_setreuid		 70
+#define TARGET_NR_setregid		 71
+#define TARGET_NR_sigsuspend		 72
+#define TARGET_NR_sigpending		 73
+#define TARGET_NR_sethostname	 74
+#define TARGET_NR_setrlimit		 75
+#define TARGET_NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
+#define TARGET_NR_getrusage		 77
+#define TARGET_NR_gettimeofday	 78
+#define TARGET_NR_settimeofday	 79
+#define TARGET_NR_getgroups		 80
+#define TARGET_NR_setgroups		 81
+#define TARGET_NR_select		 82
+#define TARGET_NR_symlink		 83
+#define TARGET_NR_oldlstat		 84
+#define TARGET_NR_readlink		 85
+#define TARGET_NR_uselib		 86
+#define TARGET_NR_swapon		 87
+#define TARGET_NR_reboot		 88
+#define TARGET_NR_readdir		 89
+#define TARGET_NR_mmap		 90
+#define TARGET_NR_munmap		 91
+#define TARGET_NR_truncate		 92
+#define TARGET_NR_ftruncate		 93
+#define TARGET_NR_fchmod		 94
+#define TARGET_NR_fchown		 95
+#define TARGET_NR_getpriority	 96
+#define TARGET_NR_setpriority	 97
+#define TARGET_NR_profil		 98
+#define TARGET_NR_statfs		 99
+#define TARGET_NR_fstatfs		100
+#define TARGET_NR_ioperm		101
+#define TARGET_NR_socketcall		102
+#define TARGET_NR_syslog		103
+#define TARGET_NR_setitimer		104
+#define TARGET_NR_getitimer		105
+#define TARGET_NR_stat		106
+#define TARGET_NR_lstat		107
+#define TARGET_NR_fstat		108
+#define TARGET_NR_olduname		109
+#define TARGET_NR_iopl		110
+#define TARGET_NR_vhangup		111
+#define TARGET_NR_idle		112
+#define TARGET_NR_vm86old		113
+#define TARGET_NR_wait4		114
+#define TARGET_NR_swapoff		115
+#define TARGET_NR_sysinfo		116
+#define TARGET_NR_ipc		117
+#define TARGET_NR_fsync		118
+#define TARGET_NR_sigreturn		119
+#define TARGET_NR_clone		120
+#define TARGET_NR_setdomainname	121
+#define TARGET_NR_uname		122
+#define TARGET_NR_modify_ldt		123
+#define TARGET_NR_adjtimex		124
+#define TARGET_NR_mprotect		125
+#define TARGET_NR_sigprocmask	126
+#define TARGET_NR_create_module	127
+#define TARGET_NR_init_module	128
+#define TARGET_NR_delete_module	129
+#define TARGET_NR_get_kernel_syms	130
+#define TARGET_NR_quotactl		131
+#define TARGET_NR_getpgid		132
+#define TARGET_NR_fchdir		133
+#define TARGET_NR_bdflush		134
+#define TARGET_NR_sysfs		135
+#define TARGET_NR_personality	136
+#define TARGET_NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define TARGET_NR_setfsuid		138
+#define TARGET_NR_setfsgid		139
+#define TARGET_NR__llseek		140
+#define TARGET_NR_getdents		141
+#define TARGET_NR__newselect		142
+#define TARGET_NR_flock		143
+#define TARGET_NR_msync		144
+#define TARGET_NR_readv		145
+#define TARGET_NR_writev		146
+#define TARGET_NR_getsid		147
+#define TARGET_NR_fdatasync		148
+#define TARGET_NR__sysctl		149
+#define TARGET_NR_mlock		150
+#define TARGET_NR_munlock		151
+#define TARGET_NR_mlockall		152
+#define TARGET_NR_munlockall		153
+#define TARGET_NR_sched_setparam		154
+#define TARGET_NR_sched_getparam		155
+#define TARGET_NR_sched_setscheduler		156
+#define TARGET_NR_sched_getscheduler		157
+#define TARGET_NR_sched_yield		158
+#define TARGET_NR_sched_get_priority_max	159
+#define TARGET_NR_sched_get_priority_min	160
+#define TARGET_NR_sched_rr_get_interval	161
+#define TARGET_NR_nanosleep		162
+#define TARGET_NR_mremap		163
+#define TARGET_NR_setresuid		164
+#define TARGET_NR_getresuid		165
+#define TARGET_NR_vm86		166
+#define TARGET_NR_query_module	167
+#define TARGET_NR_poll		168
+#define TARGET_NR_nfsservctl		169
+#define TARGET_NR_setresgid		170
+#define TARGET_NR_getresgid		171
+#define TARGET_NR_prctl              172
+#define TARGET_NR_rt_sigreturn	173
+#define TARGET_NR_rt_sigaction	174
+#define TARGET_NR_rt_sigprocmask	175
+#define TARGET_NR_rt_sigpending	176
+#define TARGET_NR_rt_sigtimedwait	177
+#define TARGET_NR_rt_sigqueueinfo	178
+#define TARGET_NR_rt_sigsuspend	179
+#define TARGET_NR_pread		180
+#define TARGET_NR_pwrite		181
+#define TARGET_NR_chown		182
+#define TARGET_NR_getcwd		183
+#define TARGET_NR_capget		184
+#define TARGET_NR_capset		185
+#define TARGET_NR_sigaltstack	186
+#define TARGET_NR_sendfile		187
+#define TARGET_NR_getpmsg		188	/* some people actually want streams */
+#define TARGET_NR_putpmsg		189	/* some people actually want streams */
+#define TARGET_NR_vfork		190
+#define TARGET_NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define TARGET_NR_mmap2		192
+#define TARGET_NR_truncate64		193
+#define TARGET_NR_ftruncate64	194
+#define TARGET_NR_stat64		195
+#define TARGET_NR_lstat64		196
+#define TARGET_NR_fstat64		197
+#define TARGET_NR_lchown32		198
+#define TARGET_NR_getuid32		199
+#define TARGET_NR_getgid32		200
+#define TARGET_NR_geteuid32		201
+#define TARGET_NR_getegid32		202
+#define TARGET_NR_setreuid32		203
+#define TARGET_NR_setregid32		204
+#define TARGET_NR_getgroups32	205
+#define TARGET_NR_setgroups32	206
+#define TARGET_NR_fchown32		207
+#define TARGET_NR_setresuid32	208
+#define TARGET_NR_getresuid32	209
+#define TARGET_NR_setresgid32	210
+#define TARGET_NR_getresgid32	211
+#define TARGET_NR_chown32		212
+#define TARGET_NR_setuid32		213
+#define TARGET_NR_setgid32		214
+#define TARGET_NR_setfsuid32		215
+#define TARGET_NR_setfsgid32		216
+#define TARGET_NR_pivot_root		217
+#define TARGET_NR_mincore		218
+#define TARGET_NR_madvise		219
+#define TARGET_NR_madvise1		219	/* delete when C lib stub is removed */
+#define TARGET_NR_getdents64		220
+#define TARGET_NR_fcntl64		221
+/* 223 is unused */
+#define TARGET_NR_gettid		224
+#define TARGET_NR_readahead		225
+#define TARGET_NR_setxattr		226
+#define TARGET_NR_lsetxattr		227
+#define TARGET_NR_fsetxattr		228
+#define TARGET_NR_getxattr		229
+#define TARGET_NR_lgetxattr		230
+#define TARGET_NR_fgetxattr		231
+#define TARGET_NR_listxattr		232
+#define TARGET_NR_llistxattr		233
+#define TARGET_NR_flistxattr		234
+#define TARGET_NR_removexattr	235
+#define TARGET_NR_lremovexattr	236
+#define TARGET_NR_fremovexattr	237
+#define TARGET_NR_tkill		238
+#define TARGET_NR_sendfile64		239
+#define TARGET_NR_futex		240
+#define TARGET_NR_sched_setaffinity	241
+#define TARGET_NR_sched_getaffinity	242
+#define TARGET_NR_set_thread_area	243
+#define TARGET_NR_get_thread_area	244
+#define TARGET_NR_io_setup		245
+#define TARGET_NR_io_destroy		246
+#define TARGET_NR_io_getevents	247
+#define TARGET_NR_io_submit		248
+#define TARGET_NR_io_cancel		249
+#define TARGET_NR_fadvise64		250
+
+#define TARGET_NR_exit_group		252
+#define TARGET_NR_lookup_dcookie	253
+#define TARGET_NR_epoll_create	254
+#define TARGET_NR_epoll_ctl		255
+#define TARGET_NR_epoll_wait		256
+#define TARGET_NR_remap_file_pages	257
+#define TARGET_NR_set_tid_address	258
+#define TARGET_NR_timer_create	259
+#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1)
+#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2)
+#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3)
+#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4)
+#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5)
+#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6)
+#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7)
+#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8)
+
+#define TARGET_NR_utimes		271

Added: trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/i386/termbits.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,214 @@
+/* from asm/termbits.h */
+
+#define TARGET_NCCS 19
+
+struct target_termios {
+    unsigned int c_iflag;               /* input mode flags */
+    unsigned int c_oflag;               /* output mode flags */
+    unsigned int c_cflag;               /* control mode flags */
+    unsigned int c_lflag;               /* local mode flags */
+    unsigned char c_line;                    /* line discipline */
+    unsigned char c_cc[TARGET_NCCS];                /* control characters */
+};
+
+/* c_iflag bits */
+#define TARGET_IGNBRK  0000001
+#define TARGET_BRKINT  0000002
+#define TARGET_IGNPAR  0000004
+#define TARGET_PARMRK  0000010
+#define TARGET_INPCK   0000020
+#define TARGET_ISTRIP  0000040
+#define TARGET_INLCR   0000100
+#define TARGET_IGNCR   0000200
+#define TARGET_ICRNL   0000400
+#define TARGET_IUCLC   0001000
+#define TARGET_IXON    0002000
+#define TARGET_IXANY   0004000
+#define TARGET_IXOFF   0010000
+#define TARGET_IMAXBEL 0020000
+
+/* c_oflag bits */
+#define TARGET_OPOST   0000001
+#define TARGET_OLCUC   0000002
+#define TARGET_ONLCR   0000004
+#define TARGET_OCRNL   0000010
+#define TARGET_ONOCR   0000020
+#define TARGET_ONLRET  0000040
+#define TARGET_OFILL   0000100
+#define TARGET_OFDEL   0000200
+#define TARGET_NLDLY   0000400
+#define   TARGET_NL0   0000000
+#define   TARGET_NL1   0000400
+#define TARGET_CRDLY   0003000
+#define   TARGET_CR0   0000000
+#define   TARGET_CR1   0001000
+#define   TARGET_CR2   0002000
+#define   TARGET_CR3   0003000
+#define TARGET_TABDLY  0014000
+#define   TARGET_TAB0  0000000
+#define   TARGET_TAB1  0004000
+#define   TARGET_TAB2  0010000
+#define   TARGET_TAB3  0014000
+#define   TARGET_XTABS 0014000
+#define TARGET_BSDLY   0020000
+#define   TARGET_BS0   0000000
+#define   TARGET_BS1   0020000
+#define TARGET_VTDLY   0040000
+#define   TARGET_VT0   0000000
+#define   TARGET_VT1   0040000
+#define TARGET_FFDLY   0100000
+#define   TARGET_FF0   0000000
+#define   TARGET_FF1   0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD   0010017
+#define  TARGET_B0     0000000         /* hang up */
+#define  TARGET_B50    0000001
+#define  TARGET_B75    0000002
+#define  TARGET_B110   0000003
+#define  TARGET_B134   0000004
+#define  TARGET_B150   0000005
+#define  TARGET_B200   0000006
+#define  TARGET_B300   0000007
+#define  TARGET_B600   0000010
+#define  TARGET_B1200  0000011
+#define  TARGET_B1800  0000012
+#define  TARGET_B2400  0000013
+#define  TARGET_B4800  0000014
+#define  TARGET_B9600  0000015
+#define  TARGET_B19200 0000016
+#define  TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE   0000060
+#define   TARGET_CS5   0000000
+#define   TARGET_CS6   0000020
+#define   TARGET_CS7   0000040
+#define   TARGET_CS8   0000060
+#define TARGET_CSTOPB  0000100
+#define TARGET_CREAD   0000200
+#define TARGET_PARENB  0000400
+#define TARGET_PARODD  0001000
+#define TARGET_HUPCL   0002000
+#define TARGET_CLOCAL  0004000
+#define TARGET_CBAUDEX 0010000
+#define  TARGET_B57600  0010001
+#define  TARGET_B115200 0010002
+#define  TARGET_B230400 0010003
+#define  TARGET_B460800 0010004
+#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */
+#define TARGET_CRTSCTS   020000000000          /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG    0000001
+#define TARGET_ICANON  0000002
+#define TARGET_XCASE   0000004
+#define TARGET_ECHO    0000010
+#define TARGET_ECHOE   0000020
+#define TARGET_ECHOK   0000040
+#define TARGET_ECHONL  0000100
+#define TARGET_NOFLSH  0000200
+#define TARGET_TOSTOP  0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE  0004000
+#define TARGET_FLUSHO  0010000
+#define TARGET_PENDIN  0040000
+#define TARGET_IEXTEN  0100000
+
+/* c_cc character offsets */
+#define TARGET_VINTR	0
+#define TARGET_VQUIT	1
+#define TARGET_VERASE	2
+#define TARGET_VKILL	3
+#define TARGET_VEOF	4
+#define TARGET_VTIME	5
+#define TARGET_VMIN	6
+#define TARGET_VSWTC	7
+#define TARGET_VSTART	8
+#define TARGET_VSTOP	9
+#define TARGET_VSUSP	10
+#define TARGET_VEOL	11
+#define TARGET_VREPRINT	12
+#define TARGET_VDISCARD	13
+#define TARGET_VWERASE	14
+#define TARGET_VLNEXT	15
+#define TARGET_VEOL2	16
+
+/* ioctls */
+
+#define TARGET_TCGETS		0x5401
+#define TARGET_TCSETS		0x5402
+#define TARGET_TCSETSW		0x5403
+#define TARGET_TCSETSF		0x5404
+#define TARGET_TCGETA		0x5405
+#define TARGET_TCSETA		0x5406
+#define TARGET_TCSETAW		0x5407
+#define TARGET_TCSETAF		0x5408
+#define TARGET_TCSBRK		0x5409
+#define TARGET_TCXONC		0x540A
+#define TARGET_TCFLSH		0x540B
+
+#define TARGET_TIOCEXCL	0x540C
+#define TARGET_TIOCNXCL	0x540D
+#define TARGET_TIOCSCTTY	0x540E
+#define TARGET_TIOCGPGRP	0x540F
+#define TARGET_TIOCSPGRP	0x5410
+#define TARGET_TIOCOUTQ	0x5411
+#define TARGET_TIOCSTI		0x5412
+#define TARGET_TIOCGWINSZ	0x5413
+#define TARGET_TIOCSWINSZ	0x5414
+#define TARGET_TIOCMGET	0x5415
+#define TARGET_TIOCMBIS	0x5416
+#define TARGET_TIOCMBIC	0x5417
+#define TARGET_TIOCMSET	0x5418
+#define TARGET_TIOCGSOFTCAR	0x5419
+#define TARGET_TIOCSSOFTCAR	0x541A
+#define TARGET_FIONREAD	0x541B
+#define TARGET_TIOCINQ		TARGET_FIONREAD
+#define TARGET_TIOCLINUX	0x541C
+#define TARGET_TIOCCONS	0x541D
+#define TARGET_TIOCGSERIAL	0x541E
+#define TARGET_TIOCSSERIAL	0x541F
+#define TARGET_TIOCPKT		0x5420
+#define TARGET_FIONBIO		0x5421
+#define TARGET_TIOCNOTTY	0x5422
+#define TARGET_TIOCSETD	0x5423
+#define TARGET_TIOCGETD	0x5424
+#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */
+#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */
+#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */
+#define TARGET_FIOCLEX		0x5451
+#define TARGET_FIOASYNC	0x5452
+#define TARGET_TIOCSERCONFIG	0x5453
+#define TARGET_TIOCSERGWILD	0x5454
+#define TARGET_TIOCSERSWILD	0x5455
+#define TARGET_TIOCGLCKTRMIOS	0x5456
+#define TARGET_TIOCSLCKTRMIOS	0x5457
+#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA		 0
+#define TARGET_TIOCPKT_FLUSHREAD	 1
+#define TARGET_TIOCPKT_FLUSHWRITE	 2
+#define TARGET_TIOCPKT_STOP		 4
+#define TARGET_TIOCPKT_START		 8
+#define TARGET_TIOCPKT_NOSTOP		16
+#define TARGET_TIOCPKT_DOSTOP		32
+
+#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+

Modified: trunk/src/host/qemu-neo1973/linux-user/main.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/main.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/main.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -194,9 +194,12 @@
             queue_signal(info.si_signo, &info);
             break;
         case EXCP0D_GPF:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_fault(env);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SI_KERNEL;
@@ -215,9 +218,12 @@
             queue_signal(info.si_signo, &info);
             break;
         case EXCP00_DIVZ:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 /* division by zero */
                 info.si_signo = SIGFPE;
                 info.si_errno = 0;
@@ -228,9 +234,12 @@
             break;
         case EXCP01_SSTP:
         case EXCP03_INT3:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGTRAP;
                 info.si_errno = 0;
                 if (trapnr == EXCP01_SSTP) {
@@ -245,9 +254,12 @@
             break;
         case EXCP04_INTO:
         case EXCP05_BOUND:
+#ifndef TARGET_X86_64
             if (env->eflags & VM_MASK) {
                 handle_vm86_trap(env, trapnr);
-            } else {
+            } else
+#endif
+            {
                 info.si_signo = SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SI_KERNEL;
@@ -670,18 +682,23 @@
 {
     cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
 }
-  
-uint32_t cpu_ppc_load_decr (CPUState *env)
+
+void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
+__attribute__ (( alias ("cpu_ppc_store_tbu") ));
+
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
+__attribute__ (( alias ("cpu_ppc_load_tbu") ));
+
+void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
 {
-    /* TO FIX */
-    return -1;
+    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
 }
- 
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
 {
-    /* TO FIX */
+    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
- 
+
 void cpu_loop(CPUPPCState *env)
 {
     target_siginfo_t info;
@@ -738,10 +755,10 @@
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
         case EXCP_DSI:
-            fprintf(stderr, "Invalid data memory access: 0x%08x\n",
+            fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
                     env->spr[SPR_DAR]);
             if (loglevel) {
-                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
+                fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
                         env->spr[SPR_DAR]);
             }
             switch (env->error_code & 0xFF000000) {
@@ -1297,6 +1314,7 @@
 	MIPS_SYS(sys_add_key	, 5)
 	MIPS_SYS(sys_request_key	, 4)
 	MIPS_SYS(sys_keyctl	, 5)
+	MIPS_SYS(sys_set_thread_area, 1)
 };
 
 #undef MIPS_SYS
@@ -1528,16 +1546,107 @@
 }
 #endif /* TARGET_M68K */
 
+#ifdef TARGET_ALPHA
+void cpu_loop (CPUState *env)
+{
+    int trapnr;
+    target_siginfo_t info;
+    
+    while (1) {
+        trapnr = cpu_alpha_exec (env);
+        
+        switch (trapnr) {
+        case EXCP_RESET:
+            fprintf(stderr, "Reset requested. Exit\n");
+            exit(1);
+            break;
+        case EXCP_MCHK:
+            fprintf(stderr, "Machine check exception. Exit\n");
+            exit(1);
+            break;
+        case EXCP_ARITH:
+            fprintf(stderr, "Arithmetic trap.\n");
+            exit(1);
+            break;
+        case EXCP_HW_INTERRUPT:
+            fprintf(stderr, "External interrupt. Exit\n"); 
+            exit(1);
+            break;
+        case EXCP_DFAULT:
+            fprintf(stderr, "MMU data fault\n");
+            exit(1);
+            break;
+        case EXCP_DTB_MISS_PAL:
+            fprintf(stderr, "MMU data TLB miss in PALcode\n");
+            exit(1);
+            break;
+        case EXCP_ITB_MISS:
+            fprintf(stderr, "MMU instruction TLB miss\n");
+            exit(1);
+            break;
+        case EXCP_ITB_ACV:
+            fprintf(stderr, "MMU instruction access violation\n");
+            exit(1);
+            break;
+        case EXCP_DTB_MISS_NATIVE:
+            fprintf(stderr, "MMU data TLB miss\n");
+            exit(1);
+            break;
+        case EXCP_UNALIGN:
+            fprintf(stderr, "Unaligned access\n");
+            exit(1);
+            break;
+        case EXCP_OPCDEC:
+            fprintf(stderr, "Invalid instruction\n");
+            exit(1);
+            break;
+        case EXCP_FEN:
+            fprintf(stderr, "Floating-point not allowed\n");
+            exit(1);
+            break;
+        case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+            fprintf(stderr, "Call to PALcode\n");
+            call_pal(env, (trapnr >> 6) | 0x80);
+            break;
+        case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
+            fprintf(stderr, "Priviledged call to PALcode\n");
+            exit(1);
+            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(info.si_signo, &info);
+                  }
+            }
+            break;
+        default:
+            printf ("Unhandled trap: 0x%x\n", trapnr);
+            cpu_dump_state(env, stderr, fprintf, 0);
+            exit (1);
+        }
+        process_pending_signals (env);
+    }
+}
+#endif /* TARGET_ALPHA */
+
 void usage(void)
 {
-    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2005 Fabrice Bellard\n"
-           "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] program [arguments...]\n"
+    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
+           "usage: qemu-" TARGET_ARCH " [-h] [-g] [-d opts] [-L path] [-s size] [-cpu model] program [arguments...]\n"
            "Linux CPU emulator (compiled for %s emulation)\n"
            "\n"
            "-h           print this help\n"
            "-g port      wait gdb connection to port\n"
            "-L path      set the elf interpreter prefix (default=%s)\n"
            "-s size      set the stack size in bytes (default=%ld)\n"
+           "-cpu model   select CPU (-cpu ? for list)\n"
            "\n"
            "debug options:\n"
 #ifdef USE_CODE_COPY
@@ -1561,6 +1670,7 @@
 int main(int argc, char **argv)
 {
     const char *filename;
+    const char *cpu_model;
     struct target_pt_regs regs1, *regs = &regs1;
     struct image_info info1, *info = &info1;
     TaskState ts1, *ts = &ts1;
@@ -1575,6 +1685,7 @@
     /* init debug */
     cpu_set_log_filename(DEBUG_LOGFILE);
 
+    cpu_model = NULL;
     optind = 1;
     for(;;) {
         if (optind >= argc)
@@ -1625,6 +1736,20 @@
             gdbstub_port = atoi(argv[optind++]);
 	} else if (!strcmp(r, "r")) {
 	    qemu_uname_release = argv[optind++];
+        } else if (!strcmp(r, "cpu")) {
+            cpu_model = argv[optind++];
+            if (strcmp(cpu_model, "?") == 0) {
+#if defined(TARGET_PPC)
+                ppc_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_ARM)
+                arm_cpu_list();
+#elif defined(TARGET_MIPS)
+                mips_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_SPARC)
+                sparc_cpu_list(stdout, &fprintf);
+#endif
+                _exit(1);
+            }
         } else 
 #ifdef USE_CODE_COPY
         if (!strcmp(r, "no-code-copy")) {
@@ -1696,6 +1821,17 @@
     env->eflags |= IF_MASK;
     
     /* linux register setup */
+#if defined(TARGET_X86_64)
+    env->regs[R_EAX] = regs->rax;
+    env->regs[R_EBX] = regs->rbx;
+    env->regs[R_ECX] = regs->rcx;
+    env->regs[R_EDX] = regs->rdx;
+    env->regs[R_ESI] = regs->rsi;
+    env->regs[R_EDI] = regs->rdi;
+    env->regs[R_EBP] = regs->rbp;
+    env->regs[R_ESP] = regs->rsp;
+    env->eip = regs->rip;
+#else
     env->regs[R_EAX] = regs->eax;
     env->regs[R_EBX] = regs->ebx;
     env->regs[R_ECX] = regs->ecx;
@@ -1705,6 +1841,7 @@
     env->regs[R_EBP] = regs->ebp;
     env->regs[R_ESP] = regs->esp;
     env->eip = regs->eip;
+#endif
 
     /* linux interrupt setup */
     env->idt.base = h2g(idt_table);
@@ -1750,7 +1887,9 @@
 #elif defined(TARGET_ARM)
     {
         int i;
-        cpu_arm_set_model(env, ARM_CPUID_ARM1026);
+        if (cpu_model == NULL)
+            cpu_model = "arm926";
+        cpu_arm_set_model(env, cpu_model);
         cpsr_write(env, regs->uregs[16], 0xffffffff);
         for(i = 0; i < 16; i++) {
             env->regs[i] = regs->uregs[i];
@@ -1763,6 +1902,20 @@
 #elif defined(TARGET_SPARC)
     {
         int i;
+        const sparc_def_t *def;
+#ifdef TARGET_SPARC64
+        if (cpu_model == NULL)
+            cpu_model = "TI UltraSparc II";
+#else
+        if (cpu_model == NULL)
+            cpu_model = "Fujitsu MB86904";
+#endif
+        sparc_find_by_name(cpu_model, &def);
+        if (def == NULL) {
+            fprintf(stderr, "Unable to find Sparc CPU definition\n");
+            exit(1);
+        }
+        cpu_sparc_register(env, def);
 	env->pc = regs->pc;
 	env->npc = regs->npc;
         env->y = regs->y;
@@ -1777,15 +1930,9 @@
         int i;
 
         /* Choose and initialise CPU */
-        /* XXX: CPU model (or PVR) should be provided on command line */
-        //        ppc_find_by_name("750gx", &def);
-        //        ppc_find_by_name("750fx", &def);
-        //        ppc_find_by_name("750p", &def);
-        ppc_find_by_name("750", &def);
-        //        ppc_find_by_name("G3", &def);
-        //        ppc_find_by_name("604r", &def);
-        //        ppc_find_by_name("604e", &def);
-        //        ppc_find_by_name("604", &def);
+        if (cpu_model == NULL)
+            cpu_model = "750";
+        ppc_find_by_name(cpu_model, &def);
         if (def == NULL) {
             cpu_abort(env,
                       "Unable to find PowerPC CPU definition\n");
@@ -1796,6 +1943,9 @@
             if (i != 12 && i != 6 && i != 13)
                 env->msr[i] = (regs->msr >> i) & 1;
         }
+#if defined(TARGET_PPC64)
+        msr_sf = 1;
+#endif
         env->nip = regs->nip;
         for(i = 0; i < 32; i++) {
             env->gpr[i] = regs->gpr[i];
@@ -1832,15 +1982,24 @@
     }
 #elif defined(TARGET_MIPS)
     {
+        mips_def_t *def;
         int i;
 
+        /* Choose and initialise CPU */
+        if (cpu_model == NULL)
+            cpu_model = "24Kf";
+        mips_find_by_name(cpu_model, &def);
+        if (def == NULL)
+            cpu_abort(env, "Unable to find MIPS CPU definition\n");
+        cpu_mips_register(env, def);
+
         for(i = 0; i < 32; i++) {
             env->gpr[i] = regs->regs[i];
         }
         env->PC = regs->cp0_epc;
-#ifdef MIPS_USES_FPU
-        env->CP0_Status |= (1 << CP0St_CU1);
-#endif
+        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+            env->CP0_Status |= (1 << CP0St_CU1);
+        }
     }
 #elif defined(TARGET_SH4)
     {
@@ -1851,6 +2010,18 @@
         }
         env->pc = regs->pc;
     }
+#elif defined(TARGET_ALPHA)
+    {
+        int i;
+
+        for(i = 0; i < 28; i++) {
+            env->ir[i] = ((target_ulong *)regs)[i];
+        }
+        env->ipr[IPR_USP] = regs->usp;
+        env->ir[30] = regs->usp;
+        env->pc = regs->pc;
+        env->unique = regs->unique;
+    }
 #else
 #error unsupported target CPU
 #endif

Modified: trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/mips/syscall_nr.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -285,4 +285,4 @@
 #define TARGET_NR_add_key			(TARGET_NR_Linux + 280)
 #define TARGET_NR_request_key		(TARGET_NR_Linux + 281)
 #define TARGET_NR_keyctl			(TARGET_NR_Linux + 282)
-
+#define TARGET_NR_set_thread_area	(TARGET_NR_Linux + 283)

Modified: trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc/termbits.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -7,8 +7,8 @@
     unsigned int c_oflag;               /* output mode flags */
     unsigned int c_cflag;               /* control mode flags */
     unsigned int c_lflag;               /* local mode flags */
+    unsigned char c_cc[TARGET_NCCS];                /* control characters */
     unsigned char c_line;                    /* line discipline */
-    unsigned char c_cc[TARGET_NCCS];                /* control characters */
     unsigned int c_ispeed;		/* input speed */
     unsigned int c_ospeed;		/* output speed */
 };

Added: trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,130 @@
+/*
+ *  PPC emulation for qemu: syscall definitions.
+ * 
+ *  Copyright (c) 2003 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* XXX: ABSOLUTELY BUGGY:
+ * for now, this is quite just a cut-and-paste from i386 target...
+ */
+
+/* default linux values for the selectors */
+#define __USER_DS	(1)
+
+struct target_pt_regs {
+	unsigned long gpr[32];
+	unsigned long nip;
+	unsigned long msr;
+	unsigned long orig_gpr3;	/* Used for restarting system calls */
+	unsigned long ctr;
+	unsigned long link;
+	unsigned long xer;
+	unsigned long ccr;
+	unsigned long mq;		/* 601 only (not used at present) */
+					/* Used on APUS to hold IPL value. */
+	unsigned long trap;		/* Reason for being here */
+	unsigned long dar;		/* Fault registers */
+	unsigned long dsisr;
+	unsigned long result; 		/* Result of a system call */
+};
+
+/* ioctls */
+struct target_revectored_struct {
+	target_ulong __map[8];			/* 256 bits */
+};
+
+/*
+ * flags masks
+ */
+
+/* ipcs */
+
+#define TARGET_SEMOP           1
+#define TARGET_SEMGET          2
+#define TARGET_SEMCTL          3 
+#define TARGET_MSGSND          11 
+#define TARGET_MSGRCV          12
+#define TARGET_MSGGET          13
+#define TARGET_MSGCTL          14
+#define TARGET_SHMAT           21
+#define TARGET_SHMDT           22
+#define TARGET_SHMGET          23
+#define TARGET_SHMCTL          24
+
+struct target_msgbuf {
+	int mtype;
+	char mtext[1];
+};
+
+struct target_ipc_kludge {
+	unsigned int	msgp;	/* Really (struct msgbuf *) */
+	int msgtyp;
+};	
+
+struct target_ipc_perm {
+	int	key;
+	unsigned short	uid;
+	unsigned short	gid;
+	unsigned short	cuid;
+	unsigned short	cgid;
+	unsigned short	mode;
+	unsigned short	seq;
+};
+
+struct target_msqid_ds {
+	struct target_ipc_perm	msg_perm;
+	unsigned int		msg_first;	/* really struct target_msg* */
+	unsigned int		msg_last;	/* really struct target_msg* */
+	unsigned int		msg_stime;	/* really target_time_t */
+	unsigned int		msg_rtime;	/* really target_time_t */
+	unsigned int		msg_ctime;	/* really target_time_t */
+	unsigned int		wwait;		/* really struct wait_queue* */
+	unsigned int		rwait;		/* really struct wait_queue* */
+	unsigned short		msg_cbytes;
+	unsigned short		msg_qnum;
+	unsigned short		msg_qbytes;
+	unsigned short		msg_lspid;
+	unsigned short		msg_lrpid;
+};
+
+struct target_shmid_ds {
+	struct target_ipc_perm	shm_perm;
+	int			shm_segsz;
+	unsigned int		shm_atime;	/* really target_time_t */
+	unsigned int		shm_dtime;	/* really target_time_t */
+	unsigned int		shm_ctime;	/* really target_time_t */
+	unsigned short		shm_cpid;
+	unsigned short		shm_lpid;
+	short			shm_nattch;
+	unsigned short		shm_npages;
+	unsigned long		*shm_pages;
+	void 			*attaches;	/* really struct shm_desc * */
+};
+
+#define TARGET_IPC_RMID	0
+#define TARGET_IPC_SET	1
+#define TARGET_IPC_STAT	2
+
+union target_semun {
+    int val;
+    unsigned int buf;	/* really struct semid_ds * */
+    unsigned int array; /* really unsigned short * */
+    unsigned int __buf;	/* really struct seminfo * */
+    unsigned int __pad;	/* really void* */
+};
+
+#define UNAME_MACHINE "ppc"

Added: trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall_nr.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc64/syscall_nr.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,258 @@
+/*
+ * This file contains the system call numbers.
+ */
+#define TARGET_NR_restart_syscall          0
+#define TARGET_NR_exit                     1
+#define TARGET_NR_fork                     2
+#define TARGET_NR_read                     3
+#define TARGET_NR_write                    4
+#define TARGET_NR_open                     5
+#define TARGET_NR_close                    6
+#define TARGET_NR_waitpid                  7
+#define TARGET_NR_creat                    8
+#define TARGET_NR_link                     9
+#define TARGET_NR_unlink                  10
+#define TARGET_NR_execve                  11
+#define TARGET_NR_chdir                   12
+#define TARGET_NR_time                    13
+#define TARGET_NR_mknod                   14
+#define TARGET_NR_chmod                   15
+#define TARGET_NR_lchown32                16
+#define TARGET_NR_break                   17
+#define TARGET_NR_oldstat                 18
+#define TARGET_NR_lseek                   19
+#define TARGET_NR_getpid                  20
+#define TARGET_NR_mount                   21
+#define TARGET_NR_umount                  22
+#define TARGET_NR_setuid32                23
+#define TARGET_NR_getuid32                24
+#define TARGET_NR_stime                   25
+#define TARGET_NR_ptrace                  26
+#define TARGET_NR_alarm                   27
+#define TARGET_NR_oldfstat                28
+#define TARGET_NR_pause                   29
+#define TARGET_NR_utime                   30
+#define TARGET_NR_stty                    31
+#define TARGET_NR_gtty                    32
+#define TARGET_NR_access                  33
+#define TARGET_NR_nice                    34
+#define TARGET_NR_ftime                   35
+#define TARGET_NR_sync                    36
+#define TARGET_NR_kill                    37
+#define TARGET_NR_rename                  38
+#define TARGET_NR_mkdir                   39
+#define TARGET_NR_rmdir                   40
+#define TARGET_NR_dup                     41
+#define TARGET_NR_pipe                    42
+#define TARGET_NR_times                   43
+#define TARGET_NR_prof                    44
+#define TARGET_NR_brk                     45
+#define TARGET_NR_setgid32                46
+#define TARGET_NR_getgid32                47
+#define TARGET_NR_signal                  48
+#define TARGET_NR_geteuid32               49
+#define TARGET_NR_getegid32               50
+#define TARGET_NR_acct                    51
+#define TARGET_NR_umount2                 52
+#define TARGET_NR_lock                    53
+#define TARGET_NR_ioctl                   54
+#define TARGET_NR_fcntl                   55
+#define TARGET_NR_mpx                     56
+#define TARGET_NR_setpgid                 57
+#define TARGET_NR_ulimit                  58
+#define TARGET_NR_oldolduname             59
+#define TARGET_NR_umask                   60
+#define TARGET_NR_chroot                  61
+#define TARGET_NR_ustat                   62
+#define TARGET_NR_dup2                    63
+#define TARGET_NR_getppid                 64
+#define TARGET_NR_getpgrp                 65
+#define TARGET_NR_setsid                  66
+#define TARGET_NR_sigaction               67
+#define TARGET_NR_sgetmask                68
+#define TARGET_NR_ssetmask                69
+#define TARGET_NR_setreuid32              70
+#define TARGET_NR_setregid32              71
+#define TARGET_NR_sigsuspend              72
+#define TARGET_NR_sigpending              73
+#define TARGET_NR_sethostname             74
+#define TARGET_NR_setrlimit               75
+#define TARGET_NR_getrlimit               76
+#define TARGET_NR_getrusage               77
+#define TARGET_NR_gettimeofday            78
+#define TARGET_NR_settimeofday            79
+#define TARGET_NR_getgroups32             80
+#define TARGET_NR_setgroups32             81
+#define TARGET_NR_select                  82
+#define TARGET_NR_symlink                 83
+#define TARGET_NR_oldlstat                84
+#define TARGET_NR_readlink                85
+#define TARGET_NR_uselib                  86
+#define TARGET_NR_swapon                  87
+#define TARGET_NR_reboot                  88
+#define TARGET_NR_readdir                 89
+#define TARGET_NR_mmap                    90
+#define TARGET_NR_munmap                  91
+#define TARGET_NR_truncate                92
+#define TARGET_NR_ftruncate               93
+#define TARGET_NR_fchmod                  94
+#define TARGET_NR_fchown32                95
+#define TARGET_NR_getpriority             96
+#define TARGET_NR_setpriority             97
+#define TARGET_NR_profil                  98
+#define TARGET_NR_statfs                  99
+#define TARGET_NR_fstatfs                100
+#define TARGET_NR_ioperm                 101
+#define TARGET_NR_socketcall             102
+#define TARGET_NR_syslog                 103
+#define TARGET_NR_setitimer              104
+#define TARGET_NR_getitimer              105
+#define TARGET_NR_stat                   106
+#define TARGET_NR_lstat                  107
+#define TARGET_NR_fstat                  108
+#define TARGET_NR_olduname               109
+#define TARGET_NR_iopl                   110
+#define TARGET_NR_vhangup                111
+#define TARGET_NR_idle                   112
+#define TARGET_NR_vm86                   113
+#define TARGET_NR_wait4                  114
+#define TARGET_NR_swapoff                115
+#define TARGET_NR_sysinfo                116
+#define TARGET_NR_ipc                    117
+#define TARGET_NR_fsync                  118
+#define TARGET_NR_sigreturn              119
+#define TARGET_NR_clone                  120
+#define TARGET_NR_setdomainname          121
+#define TARGET_NR_uname                  122
+#define TARGET_NR_modify_ldt             123
+#define TARGET_NR_adjtimex               124
+#define TARGET_NR_mprotect               125
+#define TARGET_NR_sigprocmask            126
+#define TARGET_NR_create_module          127
+#define TARGET_NR_init_module            128
+#define TARGET_NR_delete_module          129
+#define TARGET_NR_get_kernel_syms        130
+#define TARGET_NR_quotactl               131
+#define TARGET_NR_getpgid                132
+#define TARGET_NR_fchdir                 133
+#define TARGET_NR_bdflush                134
+#define TARGET_NR_sysfs                  135
+#define TARGET_NR_personality            136
+#define TARGET_NR_afs_syscall            137 /* Syscall for Andrew File System */
+#define TARGET_NR_setfsuid32             138
+#define TARGET_NR_setfsgid32             139
+#define TARGET_NR__llseek                140
+#define TARGET_NR_getdents               141
+#define TARGET_NR__newselect             142
+#define TARGET_NR_flock                  143
+#define TARGET_NR_msync                  144
+#define TARGET_NR_readv                  145
+#define TARGET_NR_writev                 146
+#define TARGET_NR_getsid                 147
+#define TARGET_NR_fdatasync              148
+#define TARGET_NR__sysctl                149
+#define TARGET_NR_mlock                  150
+#define TARGET_NR_munlock                151
+#define TARGET_NR_mlockall               152
+#define TARGET_NR_munlockall             153
+#define TARGET_NR_sched_setparam         154
+#define TARGET_NR_sched_getparam         155
+#define TARGET_NR_sched_setscheduler     156
+#define TARGET_NR_sched_getscheduler     157
+#define TARGET_NR_sched_yield            158
+#define TARGET_NR_sched_get_priority_max 159
+#define TARGET_NR_sched_get_priority_min 160
+#define TARGET_NR_sched_rr_get_interval  161
+#define TARGET_NR_nanosleep              162
+#define TARGET_NR_mremap                 163
+#define TARGET_NR_setresuid32            164
+#define TARGET_NR_getresuid32            165
+#define TARGET_NR_query_module           166
+#define TARGET_NR_poll                   167
+#define TARGET_NR_nfsservctl             168
+#define TARGET_NR_setresgid32            169
+#define TARGET_NR_getresgid32            170
+#define TARGET_NR_prctl                  171
+#define TARGET_NR_rt_sigreturn           172
+#define TARGET_NR_rt_sigaction           173
+#define TARGET_NR_rt_sigprocmask         174
+#define TARGET_NR_rt_sigpending          175
+#define TARGET_NR_rt_sigtimedwait        176
+#define TARGET_NR_rt_sigqueueinfo        177
+#define TARGET_NR_rt_sigsuspend          178
+#define TARGET_NR_pread64                179
+#define TARGET_NR_pwrite64               180
+#define TARGET_NR_chown32                181
+#define TARGET_NR_getcwd                 182
+#define TARGET_NR_capget                 183
+#define TARGET_NR_capset                 184
+#define TARGET_NR_sigaltstack            185
+#define TARGET_NR_sendfile               186
+#define TARGET_NR_getpmsg                187     /* some people actually want streams */
+#define TARGET_NR_putpmsg                188     /* some people actually want streams */
+#define TARGET_NR_vfork                  189
+#define TARGET_NR_ugetrlimit             190     /* SuS compliant getrlimit */
+#define TARGET_NR_readahead              191
+#define TARGET_NR_mmap2                  192
+#define TARGET_NR_truncate64             193
+#define TARGET_NR_ftruncate64            194
+#define TARGET_NR_stat64                 195
+#define TARGET_NR_lstat64                196
+#define TARGET_NR_fstat64                197
+#define TARGET_NR_pciconfig_read         198
+#define TARGET_NR_pciconfig_write        199
+#define TARGET_NR_pciconfig_iobase       200
+#define TARGET_NR_multiplexer            201
+#define TARGET_NR_getdents64             202
+#define TARGET_NR_pivot_root             203
+#define TARGET_NR_fcntl64                204
+#define TARGET_NR_madvise                205
+#define TARGET_NR_mincore                206
+#define TARGET_NR_gettid                 207
+#define TARGET_NR_tkill                  208
+#define TARGET_NR_setxattr               209
+#define TARGET_NR_lsetxattr              210
+#define TARGET_NR_fsetxattr              211
+#define TARGET_NR_getxattr               212
+#define TARGET_NR_lgetxattr              213
+#define TARGET_NR_fgetxattr              214
+#define TARGET_NR_listxattr              215
+#define TARGET_NR_llistxattr             216
+#define TARGET_NR_flistxattr             217
+#define TARGET_NR_removexattr            218
+#define TARGET_NR_lremovexattr           219
+#define TARGET_NR_fremovexattr           220
+#define TARGET_NR_futex                  221
+#define TARGET_NR_sched_setaffinity      222
+#define TARGET_NR_sched_getaffinity      223
+/* 224 currently unused */
+#define TARGET_NR_tuxcall                225
+#define TARGET_NR_sendfile64             226
+#define TARGET_NR_io_setup               227
+#define TARGET_NR_io_destroy             228
+#define TARGET_NR_io_getevents           229
+#define TARGET_NR_io_submit              230
+#define TARGET_NR_io_cancel              231
+#define TARGET_NR_set_tid_address        232
+#define TARGET_NR_fadvise64              233
+#define TARGET_NR_exit_group             234
+#define TARGET_NR_lookup_dcookie         235
+#define TARGET_NR_epoll_create           236
+#define TARGET_NR_epoll_ctl              237
+#define TARGET_NR_epoll_wait             238
+#define TARGET_NR_remap_file_pages       239
+#define TARGET_NR_timer_create           240
+#define TARGET_NR_timer_settime          241
+#define TARGET_NR_timer_gettime          242
+#define TARGET_NR_timer_getoverrun       243
+#define TARGET_NR_timer_delete           244
+#define TARGET_NR_clock_settime          245
+#define TARGET_NR_clock_gettime          246
+#define TARGET_NR_clock_getres           247
+#define TARGET_NR_clock_nanosleep        248
+#define TARGET_NR_swapcontext            249
+#define TARGET_NR_tgkill                 250
+#define TARGET_NR_utimes                 251
+#define TARGET_NR_statfs64               252
+#define TARGET_NR_fstatfs64              253
+#define TARGET_NR_fadvise64_64           254

Added: trunk/src/host/qemu-neo1973/linux-user/ppc64/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/ppc64/termbits.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/ppc64/termbits.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,235 @@
+/* from asm/termbits.h */
+
+#define TARGET_NCCS 19
+
+struct target_termios {
+    unsigned int c_iflag;               /* input mode flags */
+    unsigned int c_oflag;               /* output mode flags */
+    unsigned int c_cflag;               /* control mode flags */
+    unsigned int c_lflag;               /* local mode flags */
+    unsigned char c_cc[TARGET_NCCS];                /* control characters */
+    unsigned char c_line;                    /* line discipline */
+    unsigned int c_ispeed;		/* input speed */
+    unsigned int c_ospeed;		/* output speed */
+};
+
+/* c_cc character offsets */
+#define TARGET_VINTR 	0
+#define TARGET_VQUIT 	1
+#define TARGET_VERASE 	2
+#define TARGET_VKILL	3
+#define TARGET_VEOF	4
+#define TARGET_VMIN	5
+#define TARGET_VEOL	6
+#define TARGET_VTIME	7
+#define TARGET_VEOL2	8
+#define TARGET_VSWTC	9
+
+#define TARGET_VWERASE 	10
+#define TARGET_VREPRINT	11
+#define TARGET_VSUSP 		12
+#define TARGET_VSTART		13
+#define TARGET_VSTOP		14
+#define TARGET_VLNEXT		15
+#define TARGET_VDISCARD	16
+
+#define TARGET_IGNBRK	0000001
+#define TARGET_BRKINT	0000002
+#define TARGET_IGNPAR	0000004
+#define TARGET_PARMRK	0000010
+#define TARGET_INPCK	0000020
+#define TARGET_ISTRIP	0000040
+#define TARGET_INLCR	0000100
+#define TARGET_IGNCR	0000200
+#define TARGET_ICRNL	0000400
+#define TARGET_IXON	0001000
+#define TARGET_IXOFF	0002000
+#define TARGET_IXANY	0004000
+#define TARGET_IUCLC	0010000
+#define TARGET_IMAXBEL	0020000
+
+/* c_oflag bits */
+#define TARGET_OPOST	0000001
+#define TARGET_ONLCR	0000002
+#define TARGET_OLCUC	0000004
+
+#define TARGET_OCRNL	0000010
+#define TARGET_ONOCR	0000020
+#define TARGET_ONLRET	0000040
+
+#define TARGET_OFILL	00000100
+#define TARGET_OFDEL	00000200
+#define TARGET_NLDLY	00001400
+#define   TARGET_NL0	00000000
+#define   TARGET_NL1	00000400
+#define   TARGET_NL2	00001000
+#define   TARGET_NL3	00001400
+#define TARGET_TABDLY	00006000
+#define   TARGET_TAB0	00000000
+#define   TARGET_TAB1	00002000
+#define   TARGET_TAB2	00004000
+#define   TARGET_TAB3	00006000
+#define TARGET_CRDLY	00030000
+#define   TARGET_CR0	00000000
+#define   TARGET_CR1	00010000
+#define   TARGET_CR2	00020000
+#define   TARGET_CR3	00030000
+#define TARGET_FFDLY	00040000
+#define   TARGET_FF0	00000000
+#define   TARGET_FF1	00040000
+#define TARGET_BSDLY	00100000
+#define   TARGET_BS0	00000000
+#define   TARGET_BS1	00100000
+#define TARGET_VTDLY	00200000
+#define   TARGET_VT0	00000000
+#define   TARGET_VT1	00200000
+#define TARGET_XTABS	01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD	0000377
+#define  TARGET_B0	0000000		/* hang up */
+#define  TARGET_B50	0000001
+#define  TARGET_B75	0000002
+#define  TARGET_B110	0000003
+#define  TARGET_B134	0000004
+#define  TARGET_B150	0000005
+#define  TARGET_B200	0000006
+#define  TARGET_B300	0000007
+#define  TARGET_B600	0000010
+#define  TARGET_B1200	0000011
+#define  TARGET_B1800	0000012
+#define  TARGET_B2400	0000013
+#define  TARGET_B4800	0000014
+#define  TARGET_B9600	0000015
+#define  TARGET_B19200	0000016
+#define  TARGET_B38400	0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CBAUDEX 0000000
+#define  TARGET_B57600   00020
+#define  TARGET_B115200  00021
+#define  TARGET_B230400  00022
+#define  TARGET_B460800  00023
+#define  TARGET_B500000  00024
+#define  TARGET_B576000  00025
+#define  TARGET_B921600  00026
+#define TARGET_B1000000  00027
+#define TARGET_B1152000  00030
+#define TARGET_B1500000  00031
+#define TARGET_B2000000  00032
+#define TARGET_B2500000  00033
+#define TARGET_B3000000  00034
+#define TARGET_B3500000  00035
+#define TARGET_B4000000  00036
+
+#define TARGET_CSIZE	00001400
+#define   TARGET_CS5	00000000
+#define   TARGET_CS6	00000400
+#define   TARGET_CS7	00001000
+#define   TARGET_CS8	00001400
+
+#define TARGET_CSTOPB	00002000
+#define TARGET_CREAD	00004000
+#define TARGET_PARENB	00010000
+#define TARGET_PARODD	00020000
+#define TARGET_HUPCL	00040000
+
+#define TARGET_CLOCAL	00100000
+#define TARGET_CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG	0x00000080
+#define TARGET_ICANON	0x00000100
+#define TARGET_XCASE	0x00004000
+#define TARGET_ECHO	0x00000008
+#define TARGET_ECHOE	0x00000002
+#define TARGET_ECHOK	0x00000004
+#define TARGET_ECHONL	0x00000010
+#define TARGET_NOFLSH	0x80000000
+#define TARGET_TOSTOP	0x00400000
+#define TARGET_ECHOCTL	0x00000040
+#define TARGET_ECHOPRT	0x00000020
+#define TARGET_ECHOKE	0x00000001
+#define TARGET_FLUSHO	0x00800000
+#define TARGET_PENDIN	0x20000000
+#define TARGET_IEXTEN	0x00000400
+
+/* ioctls */
+
+#define TARGET_FIOCLEX		TARGET_IO('f', 1)
+#define TARGET_FIONCLEX	        TARGET_IO('f', 2)
+#define TARGET_FIOASYNC	        TARGET_IOW('f', 125, int)
+#define TARGET_FIONBIO		TARGET_IOW('f', 126, int)
+#define TARGET_FIONREAD	        TARGET_IOR('f', 127, int)
+#define TARGET_TIOCINQ		TARGET_FIONREAD
+//#define TARGET_FIOQSIZE	        TARGET_IOR('f', 128, loff_t)
+
+#define TARGET_TCGETS		TARGET_IOR('t', 19, struct target_termios)
+#define TARGET_TCSETS		TARGET_IOW('t', 20, struct target_termios)
+#define TARGET_TCSETSW		TARGET_IOW('t', 21, struct target_termios)
+#define TARGET_TCSETSF		TARGET_IOW('t', 22, struct target_termios)
+
+#define TARGET_TCGETA		TARGET_IOR('t', 23, struct target_termio)
+#define TARGET_TCSETA		TARGET_IOW('t', 24, struct target_termio)
+#define TARGET_TCSETAW		TARGET_IOW('t', 25, struct target_termio)
+#define TARGET_TCSETAF		TARGET_IOW('t', 28, struct target_termio)
+
+#define TARGET_TCSBRK		TARGET_IO('t', 29)
+#define TARGET_TCXONC		TARGET_IO('t', 30)
+#define TARGET_TCFLSH		TARGET_IO('t', 31)
+
+#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct target_winsize)
+#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct target_winsize)
+#define	TARGET_TIOCSTART	TARGET_IO('t', 110)		/* start output, like ^Q */
+#define	TARGET_TIOCSTOP	TARGET_IO('t', 111)		/* stop output, like ^S */
+#define TARGET_TIOCOUTQ        TARGET_IOR('t', 115, int)     /* output queue size */
+
+#define TARGET_TIOCGLTC	TARGET_IOR('t', 116, struct target_ltchars)
+#define TARGET_TIOCSLTC	TARGET_IOW('t', 117, struct target_ltchars)
+#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int)
+#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int)
+
+#define TARGET_TIOCEXCL	0x540C
+#define TARGET_TIOCNXCL	0x540D
+#define TARGET_TIOCSCTTY	0x540E
+
+#define TARGET_TIOCSTI		0x5412
+#define TARGET_TIOCMGET	0x5415
+#define TARGET_TIOCMBIS	0x5416
+#define TARGET_TIOCMBIC	0x5417
+#define TARGET_TIOCMSET	0x5418
+
+#define TARGET_TIOCGSOFTCAR	0x5419
+#define TARGET_TIOCSSOFTCAR	0x541A
+#define TARGET_TIOCLINUX	0x541C
+#define TARGET_TIOCCONS	0x541D
+#define TARGET_TIOCGSERIAL	0x541E
+#define TARGET_TIOCSSERIAL	0x541F
+#define TARGET_TIOCPKT		0x5420
+
+#define TARGET_TIOCNOTTY	0x5422
+#define TARGET_TIOCSETD	0x5423
+#define TARGET_TIOCGETD	0x5424
+#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */
+#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */
+#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TARGET_TIOCSERCONFIG	0x5453
+#define TARGET_TIOCSERGWILD	0x5454
+#define TARGET_TIOCSERSWILD	0x5455
+#define TARGET_TIOCGLCKTRMIOS	0x5456
+#define TARGET_TIOCSLCKTRMIOS	0x5457
+#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+

Modified: trunk/src/host/qemu-neo1973/linux-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -68,7 +68,7 @@
     uint32_t heap_limit;
     int swi_errno;
 #endif
-#ifdef TARGET_I386
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
     target_ulong target_v86;
     struct vm86_saved_state vm86_saved_regs;
     struct target_vm86plus_struct vm86plus;

Modified: trunk/src/host/qemu-neo1973/linux-user/signal.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/signal.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/signal.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -422,7 +422,7 @@
     struct sigaction act1;
     int host_sig;
 
-    if (sig < 1 || sig > TARGET_NSIG)
+    if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP)
         return -EINVAL;
     k = &sigact_table[sig - 1];
 #if defined(DEBUG_SIGNAL)
@@ -690,7 +690,11 @@
 		err |= __put_user(frame->retcode, &frame->pretcode);
 		/* This is popl %eax ; movl $,%eax ; int $0x80 */
 		err |= __put_user(0xb858, (short *)(frame->retcode+0));
+#if defined(TARGET_X86_64)
+#warning "Fix this !"
+#else
 		err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
+#endif
 		err |= __put_user(0x80cd, (short *)(frame->retcode+6));
 	}
 
@@ -2048,7 +2052,7 @@
         host_to_target_sigset_internal(&target_old_set, &old_set);
 
         /* if the CPU is in VM86 mode, we restore the 32 bit values */
-#ifdef TARGET_I386
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
         {
             CPUX86State *env = cpu_env;
             if (env->eflags & VM_MASK)

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -28,10 +28,13 @@
 #include <fcntl.h>
 #include <time.h>
 #include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
+#include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <sys/swap.h>
@@ -42,6 +45,7 @@
 #include <sys/poll.h>
 #include <sys/times.h>
 #include <sys/shm.h>
+#include <sys/sem.h>
 #include <sys/statfs.h>
 #include <utime.h>
 #include <sys/sysinfo.h>
@@ -70,7 +74,7 @@
 //#define DEBUG
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
-    || defined(TARGET_M68K)
+    || defined(TARGET_M68K) || defined(TARGET_SH4)
 /* 16 bit uid wrappers emulation */
 #define USE_UID16
 #endif
@@ -139,6 +143,7 @@
 #define __NR_sys_getdents __NR_getdents
 #define __NR_sys_getdents64 __NR_getdents64
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define __NR_sys_syslog __NR_syslog
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -158,9 +163,13 @@
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
 #endif
+#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
+_syscall1(int,set_tid_address,int *,tidptr)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -856,7 +865,7 @@
                            target_ulong target_addrlen)
 {
     socklen_t addrlen = tget32(target_addrlen);
-    void *addr = alloca(target_addrlen);
+    void *addr = alloca(addrlen);
     long ret;
 
     ret = get_errno(getpeername(fd, addr, &addrlen));
@@ -871,7 +880,7 @@
                            target_ulong target_addrlen)
 {
     socklen_t addrlen = tget32(target_addrlen);
-    void *addr = alloca(target_addrlen);
+    void *addr = alloca(addrlen);
     long ret;
 
     ret = get_errno(getsockname(fd, addr, &addrlen));
@@ -1114,6 +1123,12 @@
     uint32_t	size;
 } shm_regions[N_SHM_REGIONS];
 
+union semun {
+	int val;
+	struct senid_ds *buf;
+	unsigned short *array;
+};
+
 /* ??? This only works with linear mappings.  */
 static long do_ipc(long call, long first, long second, long third,
 		   long ptr, long fifth)
@@ -1128,6 +1143,52 @@
     call &= 0xffff;
 
     switch (call) {
+    case IPCOP_semop:
+        ret = get_errno(semop(first,(struct sembuf *) ptr, second));
+        break;
+
+    case IPCOP_semget:
+        ret = get_errno(semget(first, second, third));
+        break;
+
+    case IPCOP_semctl:
+        ret = get_errno(semctl(first, second, third, ((union semun*)ptr)->val));
+
+        break;
+
+    case IPCOP_semtimedop:
+        gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
+        ret = -ENOSYS;
+        break;
+
+	case IPCOP_msgget:
+		ret = get_errno(msgget(first, second));
+		break;
+
+	case IPCOP_msgsnd:
+		ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third));
+		break;
+
+	case IPCOP_msgctl:
+		ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr));
+		break;
+
+	case IPCOP_msgrcv:
+		{
+			struct ipc_kludge
+			{
+				void *__unbounded msgp;
+				long int msgtyp;
+			};
+
+			struct ipc_kludge *foo = (struct ipc_kludge *) ptr;
+			struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
+
+			ret = get_errno(msgrcv(first, msgp, second, 0, third));
+
+		}
+		break;
+
     case IPCOP_shmat:
 	/* SHM_* flags are the same on all linux platforms */
 	ret = get_errno((long) shmat(first, (void *) ptr, second));
@@ -1664,8 +1725,7 @@
         ts->next = first_task_state;
         first_task_state = ts;
         /* we create a new CPU instance. */
-        new_env = cpu_init();
-        memcpy(new_env, env, sizeof(CPUState));
+        new_env = cpu_copy(env);
 #if defined(TARGET_I386)
         if (!newsp)
             newsp = env->regs[R_ESP];
@@ -1705,6 +1765,16 @@
 	  newsp = env->gregs[15];
 	new_env->gregs[15] = newsp;
 	/* XXXXX */
+#elif defined(TARGET_ALPHA)
+       if (!newsp)
+         newsp = env->ir[30];
+       new_env->ir[30] = newsp;
+        /* ? */
+        {
+            int i;
+            for (i = 7; i < 30; i++)
+                new_env->ir[i] = 0;
+        }
 #else
 #error unsupported target CPU
 #endif
@@ -1733,6 +1803,13 @@
 
     switch(cmd) {
     case TARGET_F_GETLK:
+        lock_user_struct(target_fl, arg, 1);
+        fl.l_type = tswap16(target_fl->l_type);
+        fl.l_whence = tswap16(target_fl->l_whence);
+        fl.l_start = tswapl(target_fl->l_start);
+        fl.l_len = tswapl(target_fl->l_len);
+        fl.l_pid = tswapl(target_fl->l_pid);
+        unlock_user_struct(target_fl, arg, 0);
         ret = fcntl(fd, cmd, &fl);
         if (ret == 0) {
             lock_user_struct(target_fl, arg, 0);
@@ -1758,6 +1835,13 @@
         break;
         
     case TARGET_F_GETLK64:
+        lock_user_struct(target_fl64, arg, 1);
+        fl64.l_type = tswap16(target_fl64->l_type) >> 1;
+        fl64.l_whence = tswap16(target_fl64->l_whence);
+        fl64.l_start = tswapl(target_fl64->l_start);
+        fl64.l_len = tswapl(target_fl64->l_len);
+        fl64.l_pid = tswap16(target_fl64->l_pid);
+        unlock_user_struct(target_fl64, arg, 0);
         ret = fcntl(fd, cmd >> 1, &fl64);
         if (ret == 0) {
             lock_user_struct(target_fl64, arg, 0);
@@ -1983,6 +2067,7 @@
     case TARGET_NR_fork:
         ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
         break;
+#ifdef TARGET_NR_waitpid
     case TARGET_NR_waitpid:
         {
             int status;
@@ -1991,11 +2076,14 @@
                 tput32(arg2, status);
         }
         break;
+#endif
+#ifdef TARGET_NR_creat /* not on alpha */
     case TARGET_NR_creat:
         p = lock_user_string(arg1);
         ret = get_errno(creat(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#endif
     case TARGET_NR_link:
         {
             void * p2;
@@ -2103,17 +2191,34 @@
     case TARGET_NR_lseek:
         ret = get_errno(lseek(arg1, arg2, arg3));
         break;
+#ifdef TARGET_NR_getxpid
+    case TARGET_NR_getxpid:
+#else
     case TARGET_NR_getpid:
+#endif
         ret = get_errno(getpid());
         break;
     case TARGET_NR_mount:
-        /* need to look at the data field */
-        goto unimplemented;
+		{
+			/* need to look at the data field */
+			void *p2, *p3;
+			p = lock_user_string(arg1);
+			p2 = lock_user_string(arg2);
+			p3 = lock_user_string(arg3);
+			ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, (const void *)arg5));
+			unlock_user(p, arg1, 0);
+			unlock_user(p2, arg2, 0);
+			unlock_user(p3, arg3, 0);
+			break;
+		}
+#ifdef TARGET_NR_umount
     case TARGET_NR_umount:
         p = lock_user_string(arg1);
         ret = get_errno(umount(p));
         unlock_user(p, arg1, 0);
         break;
+#endif
+#ifdef TARGET_NR_stime /* not on alpha */
     case TARGET_NR_stime:
         {
             time_t host_time;
@@ -2121,18 +2226,24 @@
             ret = get_errno(stime(&host_time));
         }
         break;
+#endif
     case TARGET_NR_ptrace:
         goto unimplemented;
+#ifdef TARGET_NR_alarm /* not on alpha */
     case TARGET_NR_alarm:
         ret = alarm(arg1);
         break;
+#endif
 #ifdef TARGET_NR_oldfstat
     case TARGET_NR_oldfstat:
         goto unimplemented;
 #endif
+#ifdef TARGET_NR_pause /* not on alpha */
     case TARGET_NR_pause:
         ret = get_errno(pause());
         break;
+#endif
+#ifdef TARGET_NR_utime
     case TARGET_NR_utime:
         {
             struct utimbuf tbuf, *host_tbuf;
@@ -2151,6 +2262,7 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#endif
     case TARGET_NR_utimes:
         {
             struct timeval *tvp, tv[2];
@@ -2180,9 +2292,11 @@
         ret = get_errno(access(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#ifdef TARGET_NR_nice /* not on alpha */
     case TARGET_NR_nice:
         ret = get_errno(nice(arg1));
         break;
+#endif
 #ifdef TARGET_NR_ftime
     case TARGET_NR_ftime:
         goto unimplemented;
@@ -2247,19 +2361,22 @@
     case TARGET_NR_prof:
         goto unimplemented;
 #endif
+#ifdef TARGET_NR_signal
     case TARGET_NR_signal:
         goto unimplemented;
-
+#endif
     case TARGET_NR_acct:
         p = lock_user_string(arg1);
         ret = get_errno(acct(path(p)));
         unlock_user(p, arg1, 0);
         break;
+#ifdef TARGET_NR_umount2 /* not on alpha */
     case TARGET_NR_umount2:
         p = lock_user_string(arg1);
         ret = get_errno(umount2(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#endif
 #ifdef TARGET_NR_lock
     case TARGET_NR_lock:
         goto unimplemented;
@@ -2298,15 +2415,18 @@
     case TARGET_NR_dup2:
         ret = get_errno(dup2(arg1, arg2));
         break;
+#ifdef TARGET_NR_getppid /* not on alpha */
     case TARGET_NR_getppid:
         ret = get_errno(getppid());
         break;
+#endif
     case TARGET_NR_getpgrp:
         ret = get_errno(getpgrp());
         break;
     case TARGET_NR_setsid:
         ret = get_errno(setsid());
         break;
+#ifdef TARGET_NR_sigaction
     case TARGET_NR_sigaction:
         {
 	#if !defined(TARGET_MIPS)
@@ -2361,6 +2481,7 @@
 	#endif
         }
         break;
+#endif
     case TARGET_NR_rt_sigaction:
         {
             struct target_sigaction *act;
@@ -2381,6 +2502,7 @@
                 unlock_user_struct(oact, arg3, 1);
         }
         break;
+#ifdef TARGET_NR_sgetmask /* not on alpha */
     case TARGET_NR_sgetmask:
         {
             sigset_t cur_set;
@@ -2390,6 +2512,8 @@
             ret = target_set;
         }
         break;
+#endif
+#ifdef TARGET_NR_ssetmask /* not on alpha */
     case TARGET_NR_ssetmask:
         {
             sigset_t set, oset, cur_set;
@@ -2402,6 +2526,8 @@
             ret = target_set;
         }
         break;
+#endif
+#ifdef TARGET_NR_sigprocmask
     case TARGET_NR_sigprocmask:
         {
             int how = arg1;
@@ -2438,6 +2564,7 @@
             }
         }
         break;
+#endif
     case TARGET_NR_rt_sigprocmask:
         {
             int how = arg1;
@@ -2474,6 +2601,7 @@
             }
         }
         break;
+#ifdef TARGET_NR_sigpending
     case TARGET_NR_sigpending:
         {
             sigset_t set;
@@ -2485,6 +2613,7 @@
             }
         }
         break;
+#endif
     case TARGET_NR_rt_sigpending:
         {
             sigset_t set;
@@ -2496,6 +2625,7 @@
             }
         }
         break;
+#ifdef TARGET_NR_sigsuspend
     case TARGET_NR_sigsuspend:
         {
             sigset_t set;
@@ -2505,6 +2635,7 @@
             ret = get_errno(sigsuspend(&set));
         }
         break;
+#endif
     case TARGET_NR_rt_sigsuspend:
         {
             sigset_t set;
@@ -2546,10 +2677,12 @@
             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
         }
         break;
+#ifdef TARGET_NR_sigreturn
     case TARGET_NR_sigreturn:
         /* NOTE: ret is eax, so not transcoding must be done */
         ret = do_sigreturn(cpu_env);
         break;
+#endif
     case TARGET_NR_rt_sigreturn:
         /* NOTE: ret is eax, so not transcoding must be done */
         ret = do_rt_sigreturn(cpu_env);
@@ -2655,17 +2788,24 @@
             unlock_user(p, arg1, 0);
         }
         break;
+#ifdef TARGET_NR_uselib
     case TARGET_NR_uselib:
         goto unimplemented;
+#endif
+#ifdef TARGET_NR_swapon
     case TARGET_NR_swapon:
         p = lock_user_string(arg1);
         ret = get_errno(swapon(p, arg2));
         unlock_user(p, arg1, 0);
         break;
+#endif
     case TARGET_NR_reboot:
         goto unimplemented;
+#ifdef TARGET_NR_readdir
     case TARGET_NR_readdir:
         goto unimplemented;
+#endif
+#ifdef TARGET_NR_mmap
     case TARGET_NR_mmap:
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K)
         {
@@ -2690,6 +2830,7 @@
                                     arg6));
 #endif
         break;
+#endif
 #ifdef TARGET_NR_mmap2
     case TARGET_NR_mmap2:
 #if defined(TARGET_SPARC) || defined(TARGET_MIPS)
@@ -2709,25 +2850,37 @@
     case TARGET_NR_mprotect:
         ret = get_errno(target_mprotect(arg1, arg2, arg3));
         break;
+#ifdef TARGET_NR_mremap
     case TARGET_NR_mremap:
         ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
         break;
+#endif
         /* ??? msync/mlock/munlock are broken for softmmu.  */
+#ifdef TARGET_NR_msync
     case TARGET_NR_msync:
         ret = get_errno(msync(g2h(arg1), arg2, arg3));
         break;
+#endif
+#ifdef TARGET_NR_mlock
     case TARGET_NR_mlock:
         ret = get_errno(mlock(g2h(arg1), arg2));
         break;
+#endif
+#ifdef TARGET_NR_munlock
     case TARGET_NR_munlock:
         ret = get_errno(munlock(g2h(arg1), arg2));
         break;
+#endif
+#ifdef TARGET_NR_mlockall
     case TARGET_NR_mlockall:
         ret = get_errno(mlockall(arg1));
         break;
+#endif
+#ifdef TARGET_NR_munlockall
     case TARGET_NR_munlockall:
         ret = get_errno(munlockall());
         break;
+#endif
     case TARGET_NR_truncate:
         p = lock_user_string(arg1);
         ret = get_errno(truncate(p, arg2));
@@ -2805,10 +2958,11 @@
     case TARGET_NR_ioperm:
         goto unimplemented;
 #endif
+#ifdef TARGET_NR_socketcall
     case TARGET_NR_socketcall:
         ret = do_socketcall(arg1, arg2);
         break;
-
+#endif
 #ifdef TARGET_NR_accept
     case TARGET_NR_accept:
         ret = do_accept(arg1, arg2, arg3);
@@ -2846,12 +3000,12 @@
 #endif
 #ifdef TARGET_NR_recv
     case TARGET_NR_recv:
-        ret = do_recvfrom(arg1, arg1, arg3, arg4, 0, 0);
+        ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
         break;
 #endif
 #ifdef TARGET_NR_recvfrom
     case TARGET_NR_recvfrom:
-        ret = do_recvfrom(arg1, arg1, arg3, arg4, arg5, arg6);
+        ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
         break;
 #endif
 #ifdef TARGET_NR_recvmsg
@@ -2894,9 +3048,13 @@
         ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
         break;
 #endif
-        
+
     case TARGET_NR_syslog:
-        goto unimplemented;
+        p = lock_user_string(arg2);
+        ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
+        unlock_user(p, arg2, 0);
+        break;
+
     case TARGET_NR_setitimer:
         {
             struct itimerval value, ovalue, *pvalue;
@@ -3013,11 +3171,13 @@
             }
         }
         break;
+#ifdef TARGET_NR_swapoff
     case TARGET_NR_swapoff:
         p = lock_user_string(arg1);
         ret = get_errno(swapoff(p));
         unlock_user(p, arg1, 0);
         break;
+#endif
     case TARGET_NR_sysinfo:
         {
             struct target_sysinfo *target_value;
@@ -3045,9 +3205,11 @@
             }
         }
         break;
+#ifdef TARGET_NR_ipc
     case TARGET_NR_ipc:
 	ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
 	break;
+#endif
     case TARGET_NR_fsync:
         ret = get_errno(fsync(arg1));
         break;
@@ -3088,18 +3250,24 @@
     case TARGET_NR_modify_ldt:
         ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3));
         break;
+#if !defined(TARGET_X86_64)
     case TARGET_NR_vm86old:
         goto unimplemented;
     case TARGET_NR_vm86:
         ret = do_vm86(cpu_env, arg1, arg2);
         break;
 #endif
+#endif
     case TARGET_NR_adjtimex:
         goto unimplemented;
+#ifdef TARGET_NR_create_module
     case TARGET_NR_create_module:
+#endif
     case TARGET_NR_init_module:
     case TARGET_NR_delete_module:
+#ifdef TARGET_NR_get_kernel_syms
     case TARGET_NR_get_kernel_syms:
+#endif
         goto unimplemented;
     case TARGET_NR_quotactl:
         goto unimplemented;
@@ -3109,15 +3277,22 @@
     case TARGET_NR_fchdir:
         ret = get_errno(fchdir(arg1));
         break;
+#ifdef TARGET_NR_bdflush /* not on x86_64 */
     case TARGET_NR_bdflush:
         goto unimplemented;
+#endif
+#ifdef TARGET_NR_sysfs
     case TARGET_NR_sysfs:
         goto unimplemented;
+#endif
     case TARGET_NR_personality:
         ret = get_errno(personality(arg1));
         break;
+#ifdef TARGET_NR_afs_syscall
     case TARGET_NR_afs_syscall:
         goto unimplemented;
+#endif
+#ifdef TARGET_NR__llseek /* Not on alpha */
     case TARGET_NR__llseek:
         {
 #if defined (__x86_64__)
@@ -3130,6 +3305,7 @@
 #endif
         }
         break;
+#endif
     case TARGET_NR_getdents:
 #if TARGET_LONG_SIZE != 4
         goto unimplemented;
@@ -3169,7 +3345,7 @@
 		    strncpy(tde->d_name, de->d_name, tnamelen);
                     de = (struct dirent *)((char *)de + reclen);
                     len -= reclen;
-                    tde = (struct dirent *)((char *)tde + treclen);
+                    tde = (struct target_dirent *)((char *)tde + treclen);
 		    count1 += treclen;
                 }
 		ret = count1;
@@ -3231,9 +3407,12 @@
         }
         break;
 #endif /* TARGET_NR_getdents64 */
+#ifdef TARGET_NR__newselect
     case TARGET_NR__newselect:
         ret = do_select(arg1, arg2, arg3, arg4, arg5);
         break;
+#endif
+#ifdef TARGET_NR_poll
     case TARGET_NR_poll:
         {
             struct target_pollfd *target_pfd;
@@ -3259,6 +3438,7 @@
             unlock_user(target_pfd, arg1, ret);
         }
         break;
+#endif
     case TARGET_NR_flock:
         /* NOTE: the flock constant seems to be the same for every
            Linux platform */
@@ -3289,9 +3469,11 @@
     case TARGET_NR_getsid:
         ret = get_errno(getsid(arg1));
         break;
+#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
     case TARGET_NR_fdatasync:
         ret = get_errno(fdatasync(arg1));
         break;
+#endif
     case TARGET_NR__sysctl:
         /* We don't implement this, but ENODIR is always a safe
            return value. */
@@ -3360,12 +3542,30 @@
             }
         }
         break;
+#ifdef TARGET_NR_query_module
     case TARGET_NR_query_module:
         goto unimplemented;
+#endif
+#ifdef TARGET_NR_nfsservctl
     case TARGET_NR_nfsservctl:
         goto unimplemented;
+#endif
     case TARGET_NR_prctl:
-        goto unimplemented;
+        switch (arg1)
+            {
+            case PR_GET_PDEATHSIG:
+                {
+                    int deathsig;
+                    ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
+                    if (!is_error(ret) && arg2)
+                        tput32(arg2, deathsig);
+                }
+                break;
+            default:
+                ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
+                break;
+            }
+        break;
 #ifdef TARGET_NR_pread
     case TARGET_NR_pread:
         page_unprotect_range(arg2, arg3);
@@ -3784,15 +3984,51 @@
 #if TARGET_LONG_BITS == 32
     case TARGET_NR_fcntl64:
     {
+	int cmd;
 	struct flock64 fl;
 	struct target_flock64 *target_fl;
 #ifdef TARGET_ARM
 	struct target_eabi_flock64 *target_efl;
 #endif
 
+        switch(arg2){
+        case TARGET_F_GETLK64:
+            cmd = F_GETLK64;
+            break;
+        case TARGET_F_SETLK64:
+            cmd = F_SETLK64;
+            break;
+        case TARGET_F_SETLKW64:
+            cmd = F_SETLK64;
+            break;
+        default:
+            cmd = arg2;
+            break;
+        }
+
         switch(arg2) {
-        case F_GETLK64:
-            ret = get_errno(fcntl(arg1, arg2, &fl));
+        case TARGET_F_GETLK64:
+#ifdef TARGET_ARM
+            if (((CPUARMState *)cpu_env)->eabi) {
+                lock_user_struct(target_efl, arg3, 1);
+                fl.l_type = tswap16(target_efl->l_type);
+                fl.l_whence = tswap16(target_efl->l_whence);
+                fl.l_start = tswap64(target_efl->l_start);
+                fl.l_len = tswap64(target_efl->l_len);
+                fl.l_pid = tswapl(target_efl->l_pid);
+                unlock_user_struct(target_efl, arg3, 0);
+            } else
+#endif
+            {
+                lock_user_struct(target_fl, arg3, 1);
+                fl.l_type = tswap16(target_fl->l_type);
+                fl.l_whence = tswap16(target_fl->l_whence);
+                fl.l_start = tswap64(target_fl->l_start);
+                fl.l_len = tswap64(target_fl->l_len);
+                fl.l_pid = tswapl(target_fl->l_pid);
+                unlock_user_struct(target_fl, arg3, 0);
+            }
+            ret = get_errno(fcntl(arg1, cmd, &fl));
 	    if (ret == 0) {
 #ifdef TARGET_ARM
                 if (((CPUARMState *)cpu_env)->eabi) {
@@ -3817,8 +4053,8 @@
 	    }
 	    break;
 
-        case F_SETLK64:
-        case F_SETLKW64:
+        case TARGET_F_SETLK64:
+        case TARGET_F_SETLKW64:
 #ifdef TARGET_ARM
             if (((CPUARMState *)cpu_env)->eabi) {
                 lock_user_struct(target_efl, arg3, 1);
@@ -3839,10 +4075,10 @@
                 fl.l_pid = tswapl(target_fl->l_pid);
                 unlock_user_struct(target_fl, arg3, 0);
             }
-            ret = get_errno(fcntl(arg1, arg2, &fl));
+            ret = get_errno(fcntl(arg1, cmd, &fl));
 	    break;
         default:
-            ret = get_errno(do_fcntl(arg1, arg2, arg3));
+            ret = get_errno(do_fcntl(arg1, cmd, arg3));
             break;
         }
 	break;
@@ -3866,8 +4102,10 @@
     case TARGET_NR_gettid:
         ret = get_errno(gettid());
         break;
+#ifdef TARGET_NR_readahead
     case TARGET_NR_readahead:
         goto unimplemented;
+#endif
 #ifdef TARGET_NR_setxattr
     case TARGET_NR_setxattr:
     case TARGET_NR_lsetxattr:
@@ -3885,6 +4123,15 @@
 #endif
 #ifdef TARGET_NR_set_thread_area
     case TARGET_NR_set_thread_area:
+#ifdef TARGET_MIPS
+      ((CPUMIPSState *) cpu_env)->tls_value = arg1;
+      ret = 0;
+      break;
+#else
+      goto unimplemented_nowarn;
+#endif
+#endif
+#ifdef TARGET_NR_get_thread_area
     case TARGET_NR_get_thread_area:
         goto unimplemented_nowarn;
 #endif
@@ -3892,10 +4139,40 @@
     case TARGET_NR_getdomainname:
         goto unimplemented_nowarn;
 #endif
+
+#ifdef TARGET_NR_clock_gettime
+    case TARGET_NR_clock_gettime:
+    {
+        struct timespec ts;
+        ret = get_errno(clock_gettime(arg1, &ts));
+        if (!is_error(ret)) {
+            host_to_target_timespec(arg2, &ts);
+        }
+        break;
+    }
+#endif
+#ifdef TARGET_NR_clock_getres
+    case TARGET_NR_clock_getres:
+    {
+        struct timespec ts;
+        ret = get_errno(clock_getres(arg1, &ts));
+        if (!is_error(ret)) {
+            host_to_target_timespec(arg2, &ts);
+        }
+        break;
+    }
+#endif
+
+#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
+    case TARGET_NR_set_tid_address:
+      ret = get_errno(set_tid_address((int *) arg1));
+      break;
+#endif
+
     default:
     unimplemented:
         gemu_log("qemu: Unsupported syscall: %d\n", num);
-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_getdomainname)
+#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname)
     unimplemented_nowarn:
 #endif
         ret = -ENOSYS;

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall_defs.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -49,7 +49,7 @@
 #define TARGET_IOC_TYPEBITS	8
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
-    || defined(TARGET_M68K)
+    || defined(TARGET_M68K) || defined(TARGET_ALPHA)
 
 #define TARGET_IOC_SIZEBITS	14
 #define TARGET_IOC_DIRBITS	2
@@ -294,7 +294,7 @@
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact);
 
-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K)
+#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined (TARGET_SH4) || defined(TARGET_M68K) || defined(TARGET_ALPHA)
 
 #if defined(TARGET_SPARC)
 #define TARGET_SA_NOCLDSTOP    8u
@@ -1203,6 +1203,50 @@
 
 	int64_t  	st_blocks;
 };
+
+#elif defined(TARGET_ALPHA)
+
+struct target_stat {
+       unsigned int    st_dev;
+       unsigned int    st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_rdev;
+       target_long     st_size;
+       target_ulong    target_st_atime;
+       target_ulong    target_st_mtime;
+       target_ulong    target_st_ctime;
+       unsigned int    st_blksize;
+       unsigned int    st_blocks;
+       unsigned int    st_flags;
+       unsigned int    st_gen;
+};
+
+struct target_stat64 {
+       target_ulong    st_dev;
+       target_ulong    st_ino;
+       target_ulong    st_rdev;
+       target_long     st_size;
+       target_ulong    st_blocks;
+
+       unsigned int    st_mode;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned int    st_blksize;
+       unsigned int    st_nlink;
+       unsigned int    __pad0;
+
+       target_ulong    target_st_atime;
+       target_ulong    target_st_atime_nsec; 
+       target_ulong    target_st_mtime;
+       target_ulong    target_st_mtime_nsec;
+       target_ulong    target_st_ctime;
+       target_ulong    target_st_ctime_nsec;
+       target_long     __unused[3];
+};
+
 #else
 #error unsupported CPU
 #endif

Added: trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,92 @@
+#define __USER_CS	(0x33)
+#define __USER_DS	(0x2B)
+
+struct target_pt_regs {
+	target_ulong r15;
+	target_ulong r14;
+	target_ulong r13;
+	target_ulong r12;
+	target_ulong rbp;
+	target_ulong rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+ 	target_ulong r11;
+	target_ulong r10;
+	target_ulong r9;
+	target_ulong r8;
+	target_ulong rax;
+	target_ulong rcx;
+	target_ulong rdx;
+	target_ulong rsi;
+	target_ulong rdi;
+	target_ulong orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+	target_ulong rip;
+	target_ulong cs;
+	target_ulong eflags;
+	target_ulong rsp;
+	target_ulong ss;
+/* top of stack page */
+};
+
+/* Maximum number of LDT entries supported. */
+#define TARGET_LDT_ENTRIES	8192
+/* The size of each LDT entry. */
+#define TARGET_LDT_ENTRY_SIZE	8
+
+#define TARGET_GDT_ENTRY_TLS_ENTRIES 3
+#define TARGET_GDT_ENTRY_TLS_MIN 12
+#define TARGET_GDT_ENTRY_TLS_MAX 14
+
+#if 0 // Redefine this
+struct target_modify_ldt_ldt_s {
+	unsigned int  entry_number;
+	target_ulong  base_addr;
+	unsigned int  limit;
+	unsigned int  seg_32bit:1;
+	unsigned int  contents:2;
+	unsigned int  read_exec_only:1;
+	unsigned int  limit_in_pages:1;
+	unsigned int  seg_not_present:1;
+	unsigned int  useable:1;
+	unsigned int  lm:1;
+};
+#else
+struct target_modify_ldt_ldt_s {
+	unsigned int  entry_number;
+	target_ulong  base_addr;
+	unsigned int  limit;
+        unsigned int flags;
+};
+#endif
+
+struct target_ipc64_perm
+{
+	int		key;
+	uint32_t	uid;
+	uint32_t	gid;
+	uint32_t	cuid;
+	uint32_t	cgid;
+	unsigned short		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned short		__pad2;
+	target_ulong		__unused1;
+	target_ulong		__unused2;
+};
+
+struct target_msqid64_ds {
+	struct target_ipc64_perm msg_perm;
+	unsigned int msg_stime;	/* last msgsnd time */
+	unsigned int msg_rtime;	/* last msgrcv time */
+	unsigned int msg_ctime;	/* last change time */
+	target_ulong  msg_cbytes;	/* current number of bytes on queue */
+	target_ulong  msg_qnum;	/* number of messages in queue */
+	target_ulong  msg_qbytes;	/* max number of bytes on queue */
+	unsigned int msg_lspid;	/* pid of last msgsnd */
+	unsigned int msg_lrpid;	/* last receive pid */
+	target_ulong  __unused4;
+	target_ulong  __unused5;
+};
+
+#define UNAME_MACHINE "x86_64"

Added: trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/syscall_nr.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,280 @@
+#define TARGET_NR_read                                0
+#define TARGET_NR_write                               1
+#define TARGET_NR_open                                2
+#define TARGET_NR_close                               3
+#define TARGET_NR_stat                                4
+#define TARGET_NR_fstat                               5
+#define TARGET_NR_lstat                               6
+#define TARGET_NR_poll                                7
+#define TARGET_NR_lseek                               8
+#define TARGET_NR_mmap                                9
+#define TARGET_NR_mprotect                           10
+#define TARGET_NR_munmap                             11
+#define TARGET_NR_brk                                12
+#define TARGET_NR_rt_sigaction                       13
+#define TARGET_NR_rt_sigprocmask                     14
+#define TARGET_NR_rt_sigreturn                       15
+#define TARGET_NR_ioctl                              16
+#define TARGET_NR_pread64                            17
+#define TARGET_NR_pwrite64                           18
+#define TARGET_NR_readv                              19
+#define TARGET_NR_writev                             20
+#define TARGET_NR_access                             21
+#define TARGET_NR_pipe                               22
+#define TARGET_NR_select                             23
+#define TARGET_NR_sched_yield                        24
+#define TARGET_NR_mremap                             25
+#define TARGET_NR_msync                              26
+#define TARGET_NR_mincore                            27
+#define TARGET_NR_madvise                            28
+#define TARGET_NR_shmget                             29
+#define TARGET_NR_shmat                              30
+#define TARGET_NR_shmctl                             31
+#define TARGET_NR_dup                                32
+#define TARGET_NR_dup2                               33
+#define TARGET_NR_pause                              34
+#define TARGET_NR_nanosleep                          35
+#define TARGET_NR_getitimer                          36
+#define TARGET_NR_alarm                              37
+#define TARGET_NR_setitimer                          38
+#define TARGET_NR_getpid                             39
+#define TARGET_NR_sendfile                           40
+#define TARGET_NR_socket                             41
+#define TARGET_NR_connect                            42
+#define TARGET_NR_accept                             43
+#define TARGET_NR_sendto                             44
+#define TARGET_NR_recvfrom                           45
+#define TARGET_NR_sendmsg                            46
+#define TARGET_NR_recvmsg                            47
+#define TARGET_NR_shutdown                           48
+#define TARGET_NR_bind                               49
+#define TARGET_NR_listen                             50
+#define TARGET_NR_getsockname                        51
+#define TARGET_NR_getpeername                        52
+#define TARGET_NR_socketpair                         53
+#define TARGET_NR_setsockopt                         54
+#define TARGET_NR_getsockopt                         55
+#define TARGET_NR_clone                              56
+#define TARGET_NR_fork                               57
+#define TARGET_NR_vfork                              58
+#define TARGET_NR_execve                             59
+#define TARGET_NR_exit                               60
+#define TARGET_NR_wait4                              61
+#define TARGET_NR_kill                               62
+#define TARGET_NR_uname                              63
+#define TARGET_NR_semget                             64
+#define TARGET_NR_semop                              65
+#define TARGET_NR_semctl                             66
+#define TARGET_NR_shmdt                              67
+#define TARGET_NR_msgget                             68
+#define TARGET_NR_msgsnd                             69
+#define TARGET_NR_msgrcv                             70
+#define TARGET_NR_msgctl                             71
+#define TARGET_NR_fcntl                              72
+#define TARGET_NR_flock                              73
+#define TARGET_NR_fsync                              74
+#define TARGET_NR_fdatasync                          75
+#define TARGET_NR_truncate                           76
+#define TARGET_NR_ftruncate                          77
+#define TARGET_NR_getdents                           78
+#define TARGET_NR_getcwd                             79
+#define TARGET_NR_chdir                              80
+#define TARGET_NR_fchdir                             81
+#define TARGET_NR_rename                             82
+#define TARGET_NR_mkdir                              83
+#define TARGET_NR_rmdir                              84
+#define TARGET_NR_creat                              85
+#define TARGET_NR_link                               86
+#define TARGET_NR_unlink                             87
+#define TARGET_NR_symlink                            88
+#define TARGET_NR_readlink                           89
+#define TARGET_NR_chmod                              90
+#define TARGET_NR_fchmod                             91
+#define TARGET_NR_chown                              92
+#define TARGET_NR_fchown                             93
+#define TARGET_NR_lchown                             94
+#define TARGET_NR_umask                              95
+#define TARGET_NR_gettimeofday                       96
+#define TARGET_NR_getrlimit                          97
+#define TARGET_NR_getrusage                          98
+#define TARGET_NR_sysinfo                            99
+#define TARGET_NR_times                             100
+#define TARGET_NR_ptrace                            101
+#define TARGET_NR_getuid                            102
+#define TARGET_NR_syslog                            103
+#define TARGET_NR_getgid                            104
+#define TARGET_NR_setuid                            105
+#define TARGET_NR_setgid                            106
+#define TARGET_NR_geteuid                           107
+#define TARGET_NR_getegid                           108
+#define TARGET_NR_setpgid                           109
+#define TARGET_NR_getppid                           110
+#define TARGET_NR_getpgrp                           111
+#define TARGET_NR_setsid                            112
+#define TARGET_NR_setreuid                          113
+#define TARGET_NR_setregid                          114
+#define TARGET_NR_getgroups                         115
+#define TARGET_NR_setgroups                         116
+#define TARGET_NR_setresuid                         117
+#define TARGET_NR_getresuid                         118
+#define TARGET_NR_setresgid                         119
+#define TARGET_NR_getresgid                         120
+#define TARGET_NR_getpgid                           121
+#define TARGET_NR_setfsuid                          122
+#define TARGET_NR_setfsgid                          123
+#define TARGET_NR_getsid                            124
+#define TARGET_NR_capget                            125
+#define TARGET_NR_capset                            126
+#define TARGET_NR_rt_sigpending                     127
+#define TARGET_NR_rt_sigtimedwait                   128
+#define TARGET_NR_rt_sigqueueinfo                   129
+#define TARGET_NR_rt_sigsuspend                     130
+#define TARGET_NR_sigaltstack                       131
+#define TARGET_NR_utime                             132
+#define TARGET_NR_mknod                             133
+#define TARGET_NR_uselib                            134
+#define TARGET_NR_personality                       135
+#define TARGET_NR_ustat                             136
+#define TARGET_NR_statfs                            137
+#define TARGET_NR_fstatfs                           138
+#define TARGET_NR_sysfs                             139
+#define TARGET_NR_getpriority                       140
+#define TARGET_NR_setpriority                       141
+#define TARGET_NR_sched_setparam                    142
+#define TARGET_NR_sched_getparam                    143
+#define TARGET_NR_sched_setscheduler                144
+#define TARGET_NR_sched_getscheduler                145
+#define TARGET_NR_sched_get_priority_max            146
+#define TARGET_NR_sched_get_priority_min            147
+#define TARGET_NR_sched_rr_get_interval             148
+#define TARGET_NR_mlock                             149
+#define TARGET_NR_munlock                           150
+#define TARGET_NR_mlockall                          151
+#define TARGET_NR_munlockall                        152
+#define TARGET_NR_vhangup                           153
+#define TARGET_NR_modify_ldt                        154
+#define TARGET_NR_pivot_root                        155
+#define TARGET_NR__sysctl                           156
+#define TARGET_NR_prctl                             157
+#define TARGET_NR_arch_prctl                        158
+#define TARGET_NR_adjtimex                          159
+#define TARGET_NR_setrlimit                         160
+#define TARGET_NR_chroot                            161
+#define TARGET_NR_sync                              162
+#define TARGET_NR_acct                              163
+#define TARGET_NR_settimeofday                      164
+#define TARGET_NR_mount                             165
+#define TARGET_NR_umount2                           166
+#define TARGET_NR_swapon                            167
+#define TARGET_NR_swapoff                           168
+#define TARGET_NR_reboot                            169
+#define TARGET_NR_sethostname                       170
+#define TARGET_NR_setdomainname                     171
+#define TARGET_NR_iopl                              172
+#define TARGET_NR_ioperm                            173
+#define TARGET_NR_create_module                     174
+#define TARGET_NR_init_module                       175
+#define TARGET_NR_delete_module                     176
+#define TARGET_NR_get_kernel_syms                   177
+#define TARGET_NR_query_module                      178
+#define TARGET_NR_quotactl                          179
+#define TARGET_NR_nfsservctl                        180
+#define TARGET_NR_getpmsg                           181	/* reserved for LiS/STREAMS */
+#define TARGET_NR_putpmsg                           182	/* reserved for LiS/STREAMS */
+#define TARGET_NR_afs_syscall                       183	/* reserved for AFS */ 
+#define TARGET_NR_tuxcall      		184 /* reserved for tux */
+#define TARGET_NR_security			185
+#define TARGET_NR_gettid		186
+#define TARGET_NR_readahead		187
+#define TARGET_NR_setxattr		188
+#define TARGET_NR_lsetxattr		189
+#define TARGET_NR_fsetxattr		190
+#define TARGET_NR_getxattr		191
+#define TARGET_NR_lgetxattr		192
+#define TARGET_NR_fgetxattr		193
+#define TARGET_NR_listxattr		194
+#define TARGET_NR_llistxattr		195
+#define TARGET_NR_flistxattr		196
+#define TARGET_NR_removexattr	197
+#define TARGET_NR_lremovexattr	198
+#define TARGET_NR_fremovexattr	199
+#define TARGET_NR_tkill	200
+#define TARGET_NR_time      201
+#define TARGET_NR_futex     202
+#define TARGET_NR_sched_setaffinity    203
+#define TARGET_NR_sched_getaffinity     204
+#define TARGET_NR_set_thread_area	205
+#define TARGET_NR_io_setup	206
+#define TARGET_NR_io_destroy	207
+#define TARGET_NR_io_getevents	208
+#define TARGET_NR_io_submit	209
+#define TARGET_NR_io_cancel	210
+#define TARGET_NR_get_thread_area	211
+#define TARGET_NR_lookup_dcookie	212
+#define TARGET_NR_epoll_create	213
+#define TARGET_NR_epoll_ctl_old	214
+#define TARGET_NR_epoll_wait_old	215
+#define TARGET_NR_remap_file_pages	216
+#define TARGET_NR_getdents64	217
+#define TARGET_NR_set_tid_address	218
+#define TARGET_NR_restart_syscall	219
+#define TARGET_NR_semtimedop		220
+#define TARGET_NR_fadvise64		221
+#define TARGET_NR_timer_create		222
+#define TARGET_NR_timer_settime		223
+#define TARGET_NR_timer_gettime		224
+#define TARGET_NR_timer_getoverrun		225
+#define TARGET_NR_timer_delete	226
+#define TARGET_NR_clock_settime	227
+#define TARGET_NR_clock_gettime	228
+#define TARGET_NR_clock_getres	229
+#define TARGET_NR_clock_nanosleep	230
+#define TARGET_NR_exit_group		231
+#define TARGET_NR_epoll_wait		232
+#define TARGET_NR_epoll_ctl		233
+#define TARGET_NR_tgkill		234
+#define TARGET_NR_utimes		235
+#define TARGET_NR_vserver		236
+#define TARGET_NR_mbind 		237
+#define TARGET_NR_set_mempolicy 	238
+#define TARGET_NR_get_mempolicy 	239
+#define TARGET_NR_mq_open 		240
+#define TARGET_NR_mq_unlink 		241
+#define TARGET_NR_mq_timedsend 	242
+#define TARGET_NR_mq_timedreceive	243
+#define TARGET_NR_mq_notify 		244
+#define TARGET_NR_mq_getsetattr 	245
+#define TARGET_NR_kexec_load 	246
+#define TARGET_NR_waitid		247
+#define TARGET_NR_add_key		248
+#define TARGET_NR_request_key	249
+#define TARGET_NR_keyctl		250
+#define TARGET_NR_ioprio_set		251
+#define TARGET_NR_ioprio_get		252
+#define TARGET_NR_inotify_init	253
+#define TARGET_NR_inotify_add_watch	254
+#define TARGET_NR_inotify_rm_watch	255
+#define TARGET_NR_migrate_pages	256
+#define TARGET_NR_openat		257
+#define TARGET_NR_mkdirat		258
+#define TARGET_NR_mknodat		259
+#define TARGET_NR_fchownat		260
+#define TARGET_NR_futimesat		261
+#define TARGET_NR_newfstatat		262
+#define TARGET_NR_unlinkat		263
+#define TARGET_NR_renameat		264
+#define TARGET_NR_linkat		265
+#define TARGET_NR_symlinkat		266
+#define TARGET_NR_readlinkat		267
+#define TARGET_NR_fchmodat		268
+#define TARGET_NR_faccessat		269
+#define TARGET_NR_pselect6		270
+#define TARGET_NR_ppoll		271
+#define TARGET_NR_unshare		272
+#define TARGET_NR_set_robust_list	273
+#define TARGET_NR_get_robust_list	274
+#define TARGET_NR_splice		275
+#define TARGET_NR_tee		276
+#define TARGET_NR_sync_file_range	277
+#define TARGET_NR_vmsplice		278
+#define TARGET_NR_move_pages		279

Added: trunk/src/host/qemu-neo1973/linux-user/x86_64/termbits.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/x86_64/termbits.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/linux-user/x86_64/termbits.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,247 @@
+#define TARGET_NCCS 19
+
+typedef unsigned char	target_cc_t;
+typedef unsigned int	target_speed_t;
+typedef unsigned int	target_tcflag_t;
+struct target_termios {
+	target_tcflag_t c_iflag;		/* input mode flags */
+	target_tcflag_t c_oflag;		/* output mode flags */
+	target_tcflag_t c_cflag;		/* control mode flags */
+	target_tcflag_t c_lflag;		/* local mode flags */
+	target_cc_t c_line;			/* line discipline */
+	target_cc_t c_cc[TARGET_NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VTIME 5
+#define TARGET_VMIN 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+#define TARGET_VEOL 11
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOL2 16
+
+/* c_iflag bits */
+#define TARGET_IGNBRK	0000001
+#define TARGET_BRKINT	0000002
+#define TARGET_IGNPAR	0000004
+#define TARGET_PARMRK	0000010
+#define TARGET_INPCK	0000020
+#define TARGET_ISTRIP	0000040
+#define TARGET_INLCR	0000100
+#define TARGET_IGNCR	0000200
+#define TARGET_ICRNL	0000400
+#define TARGET_IUCLC	0001000
+#define TARGET_IXON	0002000
+#define TARGET_IXANY	0004000
+#define TARGET_IXOFF	0010000
+#define TARGET_IMAXBEL	0020000
+#define TARGET_IUTF8	0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST	0000001
+#define TARGET_OLCUC	0000002
+#define TARGET_ONLCR	0000004
+#define TARGET_OCRNL	0000010
+#define TARGET_ONOCR	0000020
+#define TARGET_ONLRET	0000040
+#define TARGET_OFILL	0000100
+#define TARGET_OFDEL	0000200
+#define TARGET_NLDLY	0000400
+#define   TARGET_NL0	0000000
+#define   TARGET_NL1	0000400
+#define TARGET_CRDLY	0003000
+#define   TARGET_CR0	0000000
+#define   TARGET_CR1	0001000
+#define   TARGET_CR2	0002000
+#define   TARGET_CR3	0003000
+#define TARGET_TABDLY	0014000
+#define   TARGET_TAB0	0000000
+#define   TARGET_TAB1	0004000
+#define   TARGET_TAB2	0010000
+#define   TARGET_TAB3	0014000
+#define   TARGET_XTABS	0014000
+#define TARGET_BSDLY	0020000
+#define   TARGET_BS0	0000000
+#define   TARGET_BS1	0020000
+#define TARGET_VTDLY	0040000
+#define   TARGET_VT0	0000000
+#define   TARGET_VT1	0040000
+#define TARGET_FFDLY	0100000
+#define   TARGET_FF0	0000000
+#define   TARGET_FF1	0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD	0010017
+#define  TARGET_B0	0000000		/* hang up */
+#define  TARGET_B50	0000001
+#define  TARGET_B75	0000002
+#define  TARGET_B110	0000003
+#define  TARGET_B134	0000004
+#define  TARGET_B150	0000005
+#define  TARGET_B200	0000006
+#define  TARGET_B300	0000007
+#define  TARGET_B600	0000010
+#define  TARGET_B1200	0000011
+#define  TARGET_B1800	0000012
+#define  TARGET_B2400	0000013
+#define  TARGET_B4800	0000014
+#define  TARGET_B9600	0000015
+#define  TARGET_B19200	0000016
+#define  TARGET_B38400	0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE	0000060
+#define   TARGET_CS5	0000000
+#define   TARGET_CS6	0000020
+#define   TARGET_CS7	0000040
+#define   TARGET_CS8	0000060
+#define TARGET_CSTOPB	0000100
+#define TARGET_CREAD	0000200
+#define TARGET_PARENB	0000400
+#define TARGET_PARODD	0001000
+#define TARGET_HUPCL	0002000
+#define TARGET_CLOCAL	0004000
+#define TARGET_CBAUDEX 0010000
+#define	   TARGET_BOTHER 0010000		/* non standard rate */
+#define    TARGET_B57600 0010001
+#define   TARGET_B115200 0010002
+#define   TARGET_B230400 0010003
+#define   TARGET_B460800 0010004
+#define   TARGET_B500000 0010005
+#define   TARGET_B576000 0010006
+#define   TARGET_B921600 0010007
+#define  TARGET_B1000000 0010010
+#define  TARGET_B1152000 0010011
+#define  TARGET_B1500000 0010012
+#define  TARGET_B2000000 0010013
+#define  TARGET_B2500000 0010014
+#define  TARGET_B3000000 0010015
+#define  TARGET_B3500000 0010016
+#define  TARGET_B4000000 0010017
+#define TARGET_CIBAUD	  002003600000	/* input baud rate */
+#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define TARGET_CRTSCTS	  020000000000		/* flow control */
+
+#define TARGET_IBSHIFT	  8		/* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define TARGET_ISIG	0000001
+#define TARGET_ICANON	0000002
+#define TARGET_XCASE	0000004
+#define TARGET_ECHO	0000010
+#define TARGET_ECHOE	0000020
+#define TARGET_ECHOK	0000040
+#define TARGET_ECHONL	0000100
+#define TARGET_NOFLSH	0000200
+#define TARGET_TOSTOP	0000400
+#define TARGET_ECHOCTL	0001000
+#define TARGET_ECHOPRT	0002000
+#define TARGET_ECHOKE	0004000
+#define TARGET_FLUSHO	0010000
+#define TARGET_PENDIN	0040000
+#define TARGET_IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TARGET_TCOOFF		0
+#define	TARGET_TCOON		1
+#define	TARGET_TCIOFF		2
+#define	TARGET_TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TARGET_TCIFLUSH	0
+#define	TARGET_TCOFLUSH	1
+#define	TARGET_TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TARGET_TCSANOW		0
+#define	TARGET_TCSADRAIN	1
+#define	TARGET_TCSAFLUSH	2
+
+#define TARGET_TCGETS		0x5401
+#define TARGET_TCSETS		0x5402
+#define TARGET_TCSETSW		0x5403
+#define TARGET_TCSETSF		0x5404
+#define TARGET_TCGETA		0x5405
+#define TARGET_TCSETA		0x5406
+#define TARGET_TCSETAW		0x5407
+#define TARGET_TCSETAF		0x5408
+#define TARGET_TCSBRK		0x5409
+#define TARGET_TCXONC		0x540A
+#define TARGET_TCFLSH		0x540B
+#define TARGET_TIOCEXCL	0x540C
+#define TARGET_TIOCNXCL	0x540D
+#define TARGET_TIOCSCTTY	0x540E
+#define TARGET_TIOCGPGRP	0x540F
+#define TARGET_TIOCSPGRP	0x5410
+#define TARGET_TIOCOUTQ	0x5411
+#define TARGET_TIOCSTI		0x5412
+#define TARGET_TIOCGWINSZ	0x5413
+#define TARGET_TIOCSWINSZ	0x5414
+#define TARGET_TIOCMGET	0x5415
+#define TARGET_TIOCMBIS	0x5416
+#define TARGET_TIOCMBIC	0x5417
+#define TARGET_TIOCMSET	0x5418
+#define TARGET_TIOCGSOFTCAR	0x5419
+#define TARGET_TIOCSSOFTCAR	0x541A
+#define TARGET_FIONREAD	0x541B
+#define TARGET_TIOCINQ		FIONREAD
+#define TARGET_TIOCLINUX	0x541C
+#define TARGET_TIOCCONS	0x541D
+#define TARGET_TIOCGSERIAL	0x541E
+#define TARGET_TIOCSSERIAL	0x541F
+#define TARGET_TIOCPKT		0x5420
+#define TARGET_FIONBIO		0x5421
+#define TARGET_TIOCNOTTY	0x5422
+#define TARGET_TIOCSETD	0x5423
+#define TARGET_TIOCGETD	0x5424
+#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */
+#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */
+#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TARGET_TCGETS2		_IOR('T',0x2A, struct termios2)
+#define TARGET_TCSETS2		_IOW('T',0x2B, struct termios2)
+#define TARGET_TCSETSW2	_IOW('T',0x2C, struct termios2)
+#define TARGET_TCSETSF2	_IOW('T',0x2D, struct termios2)
+#define TARGET_TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */
+#define TARGET_FIOCLEX		0x5451
+#define TARGET_FIOASYNC	0x5452
+#define TARGET_TIOCSERCONFIG	0x5453
+#define TARGET_TIOCSERGWILD	0x5454
+#define TARGET_TIOCSERSWILD	0x5455
+#define TARGET_TIOCGLCKTRMIOS	0x5456
+#define TARGET_TIOCSLCKTRMIOS	0x5457
+#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+#define TARGET_FIOQSIZE       0x5460
+
+/* Used for packet mode */
+#define TARGET_TIOCPKT_DATA		 0
+#define TARGET_TIOCPKT_FLUSHREAD	 1
+#define TARGET_TIOCPKT_FLUSHWRITE	 2
+#define TARGET_TIOCPKT_STOP		 4
+#define TARGET_TIOCPKT_START		 8
+#define TARGET_TIOCPKT_NOSTOP		16
+#define TARGET_TIOCPKT_DOSTOP		32
+
+#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */

Modified: trunk/src/host/qemu-neo1973/loader.c
===================================================================
--- trunk/src/host/qemu-neo1973/loader.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/loader.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -23,6 +23,7 @@
  */
 #include "vl.h"
 #include "disas.h"
+#include "uboot_image.h"
 
 /* return the size or -1 if error */
 int get_image_size(const char *filename)
@@ -195,7 +196,7 @@
 
 /* return < 0 if error, otherwise the number of bytes loaded in memory */
 int load_elf(const char *filename, int64_t virt_to_phys_addend,
-             uint64_t *pentry)
+             uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr)
 {
     int fd, data_order, host_data_order, must_swab, ret;
     uint8_t e_ident[EI_NIDENT];
@@ -229,9 +230,11 @@
 
     lseek(fd, 0, SEEK_SET);
     if (e_ident[EI_CLASS] == ELFCLASS64) {
-        ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry);
+        ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry,
+                         lowaddr, highaddr);
     } else {
-        ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry);
+        ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry,
+                         lowaddr, highaddr);
     }
 
     close(fd);
@@ -241,3 +244,80 @@
     close(fd);
     return -1;
 }
+
+static void bswap_uboot_header(uboot_image_header_t *hdr)
+{
+#ifndef WORDS_BIGENDIAN
+    bswap32s(&hdr->ih_magic);
+    bswap32s(&hdr->ih_hcrc);
+    bswap32s(&hdr->ih_time);
+    bswap32s(&hdr->ih_size);
+    bswap32s(&hdr->ih_load);
+    bswap32s(&hdr->ih_ep);
+    bswap32s(&hdr->ih_dcrc);
+#endif
+}
+
+/* Load a U-Boot image.  */
+int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
+{
+    
+    int fd;
+    int size;
+    uboot_image_header_t h;
+    uboot_image_header_t *hdr = &h;
+    uint8_t *data = NULL;
+
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if (fd < 0)
+        return -1;
+
+    size = read(fd, hdr, sizeof(uboot_image_header_t));
+    if (size < 0)
+        goto fail;
+
+    bswap_uboot_header(hdr);
+
+    if (hdr->ih_magic != IH_MAGIC)
+        goto fail;
+
+    /* TODO: Implement Multi-File images.  */
+    if (hdr->ih_type == IH_TYPE_MULTI) {
+        fprintf(stderr, "Unable to load multi-file u-boot images\n");
+        goto fail;
+    }
+
+    /* TODO: Implement compressed images.  */
+    if (hdr->ih_comp != IH_COMP_NONE) {
+        fprintf(stderr, "Unable to load compressed u-boot images\n");
+        goto fail;
+    }
+
+    /* TODO: Check CPU type.  */
+    if (is_linux) {
+        if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
+            *is_linux = 1;
+        else
+            *is_linux = 0;
+    }
+
+    *ep = hdr->ih_ep;
+    data = qemu_malloc(hdr->ih_size);
+    if (!data)
+        goto fail;
+
+    if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
+        fprintf(stderr, "Error reading file\n");
+        goto fail;
+    }
+
+    cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
+
+    return hdr->ih_size;
+
+fail:
+    if (data)
+        qemu_free(data);
+    close(fd);
+    return -1;
+}

Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/monitor.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,7 +54,8 @@
     const char *help;
 } term_cmd_t;
 
-static CharDriverState *monitor_hd;
+#define MAX_MON 4
+static CharDriverState *monitor_hd[MAX_MON];
 static int hide_banner;
 
 static term_cmd_t term_cmds[];
@@ -69,8 +70,11 @@
 
 void term_flush(void)
 {
+    int i;
     if (term_outbuf_index > 0) {
-        qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
+        for (i = 0; i < MAX_MON; i++)
+            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+                qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
         term_outbuf_index = 0;
     }
 }
@@ -231,6 +235,12 @@
   term_printf("%s\n", QEMU_VERSION);
 }
 
+static void do_info_name(void)
+{
+    if (qemu_name)
+        term_printf("%s\n", qemu_name);
+}
+
 static void do_info_block(void)
 {
     bdrv_info();
@@ -327,6 +337,17 @@
     }
 }
 
+#if defined(TARGET_PPC)
+/* XXX: not implemented in other targets */
+static void do_info_cpu_stats (void)
+{
+    CPUState *env;
+
+    env = mon_get_cpu();
+    cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
+}
+#endif
+
 static void do_quit(void)
 {
     exit(0);
@@ -409,14 +430,14 @@
 }
 
 #ifdef CONFIG_GDBSTUB
-static void do_gdbserver(int has_port, int port)
+static void do_gdbserver(const char *port)
 {
-    if (!has_port)
+    if (!port)
         port = DEFAULT_GDBSTUB_PORT;
     if (gdbserver_start(port) < 0) {
-        qemu_printf("Could not open gdbserver socket on port %d\n", port);
+        qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
     } else {
-        qemu_printf("Waiting gdb connection on port %d\n", port);
+        qemu_printf("Waiting gdb connection on port '%s'\n", port);
     }
 }
 #endif
@@ -1184,9 +1205,9 @@
     { "q|quit", "", do_quit,
       "", "quit the emulator" },
     { "eject", "-fB", do_eject,
-      "[-f] device", "eject a removable media (use -f to force it)" },
+      "[-f] device", "eject a removable medium (use -f to force it)" },
     { "change", "BF", do_change,
-      "device filename", "change a removable media" },
+      "device filename", "change a removable medium" },
     { "screendump", "F", do_screen_dump, 
       "filename", "save screen into PPM image 'filename'" },
     { "log", "s", do_log,
@@ -1202,7 +1223,7 @@
     { "c|cont", "", do_cont, 
       "", "resume emulation", },
 #ifdef CONFIG_GDBSTUB
-    { "gdbserver", "i?", do_gdbserver, 
+    { "gdbserver", "s?", do_gdbserver, 
       "[port]", "start gdbserver session (default port=1234)", },
 #endif
     { "x", "/l", do_memory_dump, 
@@ -1291,6 +1312,14 @@
       "", "show guest PCMCIA status" },
     { "mice", "", do_info_mice,
       "", "show which guest mouse is receiving events" },
+    { "vnc", "", do_info_vnc,
+      "", "show the vnc server status"},
+    { "name", "", do_info_name,
+      "", "show the current VM name" },
+#if defined(TARGET_PPC)
+    { "cpustats", "", do_info_cpu_stats,
+      "", "show CPU statistics", },
+#endif
     { NULL, NULL, },
 };
 
@@ -2081,9 +2110,9 @@
                 }
                 if (nb_args + 3 > MAX_ARGS)
                     goto error_args;
-                args[nb_args++] = (void*)count;
-                args[nb_args++] = (void*)format;
-                args[nb_args++] = (void*)size;
+                args[nb_args++] = (void*)(long)count;
+                args[nb_args++] = (void*)(long)format;
+                args[nb_args++] = (void*)(long)size;
             }
             break;
         case 'i':
@@ -2111,7 +2140,7 @@
                     typestr++;
                     if (nb_args >= MAX_ARGS)
                         goto error_args;
-                    args[nb_args++] = (void *)has_arg;
+                    args[nb_args++] = (void *)(long)has_arg;
                     if (!has_arg) {
                         if (nb_args >= MAX_ARGS)
                             goto error_args;
@@ -2125,16 +2154,16 @@
                 if (c == 'i') {
                     if (nb_args >= MAX_ARGS)
                         goto error_args;
-                    args[nb_args++] = (void *)(int)val;
+                    args[nb_args++] = (void *)(long)val;
                 } else {
                     if ((nb_args + 1) >= MAX_ARGS)
                         goto error_args;
 #if TARGET_LONG_BITS == 64
-                    args[nb_args++] = (void *)(int)((val >> 32) & 0xffffffff);
+                    args[nb_args++] = (void *)(long)((val >> 32) & 0xffffffff);
 #else
                     args[nb_args++] = (void *)0;
 #endif
-                    args[nb_args++] = (void *)(int)(val & 0xffffffff);
+                    args[nb_args++] = (void *)(long)(val & 0xffffffff);
                 }
             }
             break;
@@ -2161,7 +2190,7 @@
                 }
                 if (nb_args >= MAX_ARGS)
                     goto error_args;
-                args[nb_args++] = (void *)has_option;
+                args[nb_args++] = (void *)(long)has_option;
             }
             break;
         default:
@@ -2444,13 +2473,28 @@
     monitor_start_input();
 }
 
+static int is_first_init = 1;
+
 void monitor_init(CharDriverState *hd, int show_banner)
 {
-    monitor_hd = hd;
+    int i;
+
+    if (is_first_init) {
+        for (i = 0; i < MAX_MON; i++) {
+            monitor_hd[i] = NULL;
+        }
+        is_first_init = 0;
+    }
+    for (i = 0; i < MAX_MON; i++) {
+        if (monitor_hd[i] == NULL) {
+            monitor_hd[i] = hd;
+            break;
+        }
+    }
+
     hide_banner = !show_banner;
 
-    qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
-    qemu_chr_add_event_handler(hd, term_event);
+    qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
 }
 
 /* XXX: use threads ? */
@@ -2468,8 +2512,12 @@
 void monitor_readline(const char *prompt, int is_password,
                       char *buf, int buf_size)
 {
+    int i;
+
     if (is_password) {
-        qemu_chr_send_event(monitor_hd, CHR_EVENT_FOCUS);
+        for (i = 0; i < MAX_MON; i++)
+            if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+                qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
     }
     readline_start(prompt, is_password, monitor_readline_cb, NULL);
     monitor_readline_buf = buf;

Modified: trunk/src/host/qemu-neo1973/openmoko/download.sh
===================================================================
--- trunk/src/host/qemu-neo1973/openmoko/download.sh	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/openmoko/download.sh	2007-05-11 23:44:50 UTC (rev 1948)
@@ -34,7 +34,7 @@
 			${echo} "$name" > .list
 		fi
 	done
-	export $2=`sort .list | tail -n 1`
+	export $2=`sort -n .list | tail -n 1`
 	rm -rf .list
 	[ -z "${!2}" ] && ( ${echo} not found; exit -1 )
 	${echo} ${!2}

Modified: trunk/src/host/qemu-neo1973/openmoko/flash.sh
===================================================================
--- trunk/src/host/qemu-neo1973/openmoko/flash.sh	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/openmoko/flash.sh	2007-05-11 23:44:50 UTC (rev 1948)
@@ -43,7 +43,7 @@
 # We assume they have numeric date or some build number in their names.
 most_recent () {
 	cd $src_dir
-	export $2="`basename \`ls -d -1 $img_dir/$1 | sort | tail -n 1\``"
+	export $2="`basename \`ls -d -1 $img_dir/$1 | sort -n | tail -n 1\``"
 	export $3="`python -c \"import os; print '0x%lx' \
 		%(os.stat('$img_dir/${!2}').st_size)\"`"
 	cd $script_dir

Modified: trunk/src/host/qemu-neo1973/osdep.c
===================================================================
--- trunk/src/host/qemu-neo1973/osdep.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/osdep.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -27,6 +27,11 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <fcntl.h>
+#ifdef HOST_SOLARIS
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#endif
 
 #include "cpu.h"
 #if defined(USE_KQEMU)
@@ -86,13 +91,22 @@
     const char *tmpdir;
     char phys_ram_file[1024];
     void *ptr;
+#ifdef HOST_SOLARIS
+    struct statvfs stfs;
+#else
     struct statfs stfs;
+#endif
 
     if (phys_ram_fd < 0) {
         tmpdir = getenv("QEMU_TMPDIR");
         if (!tmpdir)
+#ifdef HOST_SOLARIS
+            tmpdir = "/tmp";
+        if (statvfs(tmpdir, &stfs) == 0) {
+#else
             tmpdir = "/dev/shm";
         if (statfs(tmpdir, &stfs) == 0) {
+#endif
             int64_t free_space;
             int ram_mb;
 
@@ -203,3 +217,50 @@
     strcpy(ptr, str);
     return ptr;
 }
+
+int qemu_create_pidfile(const char *filename)
+{
+    char buffer[128];
+    int len;
+#ifndef _WIN32
+    int fd;
+
+    fd = open(filename, O_RDWR | O_CREAT, 0600);
+    if (fd == -1)
+        return -1;
+
+    if (lockf(fd, F_TLOCK, 0) == -1)
+        return -1;
+
+    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
+    if (write(fd, buffer, len) != len)
+        return -1;
+#else
+    HANDLE file;
+    DWORD flags;
+    OVERLAPPED overlap;
+    BOOL ret;
+
+    /* Open for writing with no sharing. */
+    file = CreateFile(filename, GENERIC_WRITE, 0, NULL, 
+		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    if (file == INVALID_HANDLE_VALUE)
+      return -1;
+
+    flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
+    overlap.hEvent = 0;
+    /* Lock 1 byte. */
+    ret = LockFileEx(file, flags, 0, 0, 1, &overlap);
+    if (ret == 0)
+      return -1;
+
+    /* Write PID to file. */
+    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
+    ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len, 
+		      &overlap, NULL);
+    if (ret == 0)
+      return -1;
+#endif
+    return 0;
+}

Modified: trunk/src/host/qemu-neo1973/osdep.h
===================================================================
--- trunk/src/host/qemu-neo1973/osdep.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/osdep.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -15,4 +15,6 @@
 
 void *get_mmap_addr(unsigned long size);
 
+int qemu_create_pidfile(const char *filename);
+
 #endif

Modified: trunk/src/host/qemu-neo1973/pc-bios/README
===================================================================
--- trunk/src/host/qemu-neo1973/pc-bios/README	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/pc-bios/README	2007-05-11 23:44:50 UTC (rev 1948)
@@ -14,6 +14,8 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
+  The included Sparc32 image is built from SVN version 144 and Sparc64
+  image from version 125.
 
 - The PXE roms come from Rom-o-Matic etherboot 5.4.2.
   pcnet32:pcnet32 -- [0x1022,0x2000]

Modified: trunk/src/host/qemu-neo1973/pc-bios/bios.bin
===================================================================
(Binary files differ)

Modified: trunk/src/host/qemu-neo1973/pc-bios/bios.diff
===================================================================
--- trunk/src/host/qemu-neo1973/pc-bios/bios.diff	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/pc-bios/bios.diff	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,3 +1,25 @@
+Index: rombios.c
+===================================================================
+RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
+retrieving revision 1.174
+diff -u -w -r1.174 rombios.c
+--- rombios.c	17 Oct 2006 16:48:05 -0000	1.174
++++ rombios.c	8 Feb 2007 21:57:48 -0000
+@@ -9472,6 +9472,14 @@
+   mov eax, #0x00040000
+   call eax
+ 
++  ;; reset the memory (some boot loaders such as syslinux suppose 
++  ;; that the memory is set to zero)
++  mov edi, #0x00040000
++  mov ecx, #0x40000 / 4
++  xor eax, eax
++  rep 
++    stosd
++
+   ;; return to 16 bit protected mode first
+   db 0xea
+   dd rombios32_10
 Index: rombios.h
 ===================================================================
 RCS file: /cvsroot/bochs/bochs/bios/rombios.h,v
@@ -4,7 +26,7 @@
 retrieving revision 1.3
 diff -u -w -r1.3 rombios.h
 --- rombios.h	3 Oct 2006 20:27:30 -0000	1.3
-+++ rombios.h	1 Nov 2006 19:16:34 -0000
++++ rombios.h	8 Feb 2007 21:57:48 -0000
 @@ -19,7 +19,7 @@
  //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  
@@ -20,7 +42,7 @@
 retrieving revision 1.8
 diff -u -w -r1.8 rombios32.c
 --- rombios32.c	3 Oct 2006 20:27:30 -0000	1.8
-+++ rombios32.c	1 Nov 2006 19:16:34 -0000
++++ rombios32.c	8 Feb 2007 21:57:48 -0000
 @@ -852,6 +852,11 @@
      int ioapic_id, i, len;
      int mp_config_table_size;

Modified: trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc32
===================================================================
(Binary files differ)

Added: trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc64
===================================================================
(Binary files differ)


Property changes on: trunk/src/host/qemu-neo1973/pc-bios/openbios-sparc64
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/src/host/qemu-neo1973/ppc.ld
===================================================================
--- trunk/src/host/qemu-neo1973/ppc.ld	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/ppc.ld	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,8 +2,8 @@
  * Written by Martin Mares <mj at atrey.karlin.mff.cuni.cz>;
  */
 OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
-OUTPUT_ARCH(powerpc)
-SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
+OUTPUT_ARCH(powerpc:common)
+SEARCH_DIR(/usr/powerpc-linux-gnu/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib)
 ENTRY(_start)
 SECTIONS
 {
@@ -16,93 +16,179 @@
   .gnu.version   : { *(.gnu.version)	}
   .gnu.version_d   : { *(.gnu.version_d)	}
   .gnu.version_r   : { *(.gnu.version_r)	}
-  .rel.text      :
-    { *(.rel.text) *(.rel.gnu.linkonce.t*) }
-  .rela.text     :
-    { *(.rela.text) *(.rela.gnu.linkonce.t*) }
-  .rel.data      :
-    { *(.rel.data) *(.rel.gnu.linkonce.d*) }
-  .rela.data     :
-    { *(.rela.data) *(.rela.gnu.linkonce.d*) }
-  .rel.rodata    :
-    { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
-  .rela.rodata   :
-    { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
-  .rel.got       : { *(.rel.got)		}
-  .rela.got      : { *(.rela.got)		}
-  .rel.ctors     : { *(.rel.ctors)	}
-  .rela.ctors    : { *(.rela.ctors)	}
-  .rel.dtors     : { *(.rel.dtors)	}
-  .rela.dtors    : { *(.rela.dtors)	}
-  .rel.init      : { *(.rel.init)	}
-  .rela.init     : { *(.rela.init)	}
-  .rel.fini      : { *(.rel.fini)	}
-  .rela.fini     : { *(.rela.fini)	}
-  .rel.bss       : { *(.rel.bss)		}
-  .rela.bss      : { *(.rela.bss)		}
-  .rel.plt       : { *(.rel.plt)		}
-  .rela.plt      : { *(.rela.plt)		}
-  .init          : { *(.init)	} =0x47ff041f
-  .text      :
+  .rel.init       : { *(.rel.init) }
+  .rela.init      : { *(.rela.init) }
+  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+  .rel.fini       : { *(.rel.fini) }
+  .rela.fini      : { *(.rela.fini) }
+  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+  .rel.data.rel.ro   : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+  .rela.data.rel.ro   : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
+  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+  .rel.tdata	  : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+  .rela.tdata	  : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+  .rel.tbss	  : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+  .rela.tbss	  : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+  .rel.ctors      : { *(.rel.ctors) }
+  .rela.ctors     : { *(.rela.ctors) }
+  .rel.dtors      : { *(.rel.dtors) }
+  .rela.dtors     : { *(.rela.dtors) }
+  .rel.got        : { *(.rel.got) }
+  .rela.got       : { *(.rela.got) }
+  .rela.got1           : { *(.rela.got1) }
+  .rela.got2           : { *(.rela.got2) }
+  .rel.sdata      : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+  .rela.sdata     : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+  .rel.sbss       : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+  .rela.sbss      : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
+  .rel.sdata2     : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+  .rela.sdata2    : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+  .rel.sbss2      : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+  .rela.sbss2     : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
   {
-    *(.text)
+    KEEP (*(.init))
+  } =0
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    KEEP (*(.text.*personality*))
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
-    *(.gnu.linkonce.t*)
+    *(.glink)
   } =0x47ff041f
-  _etext = .;
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x47ff041f
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
   PROVIDE (etext = .);
-  .fini      : { *(.fini)    } =0x47ff041f
-  . = ALIGN(32 / 8);
-  PROVIDE (__preinit_array_start = .);
-  .preinit_array     : { *(.preinit_array) }
-  PROVIDE (__preinit_array_end = .);
-  PROVIDE (__init_array_start = .);
-  .init_array     : { *(.init_array) }
-  PROVIDE (__init_array_end = .);
-  PROVIDE (__fini_array_start = .);
-  .fini_array     : { *(.fini_array) }
-  PROVIDE (__fini_array_end = .);
-  .rodata    : { *(.rodata) *(.gnu.linkonce.r*) }
-  .rodata1   : { *(.rodata1) }
-  .reginfo : { *(.reginfo) }
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .sdata2         :
+  {
+    PROVIDE (_SDA2_BASE_ = 32768);
+    *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+  }
+  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
-  . = ALIGN(0x100000) + (. & (0x100000 - 1));
-  .data    :
+  . = ALIGN (0x10000) - ((0x10000 - .) & (0x10000 - 1)); . = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
   {
-    *(.data)
-    *(.gnu.linkonce.d*)
-    CONSTRUCTORS
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
   }
-  .data1   : { *(.data1) }
-  .ctors         :
+  .init_array     :
   {
-    *(.ctors)
+     PROVIDE_HIDDEN (__init_array_start = .);
+     KEEP (*(SORT(.init_array.*)))
+     KEEP (*(.init_array))
+     PROVIDE_HIDDEN (__init_array_end = .);
   }
-  .dtors         :
+  .fini_array     :
   {
-    *(.dtors)
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(.fini_array))
+    KEEP (*(SORT(.fini_array.*)))
+    PROVIDE_HIDDEN (__fini_array_end = .);
   }
-  .plt      : { *(.plt)	}
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin*.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+  .got1           : { *(.got1) }
+  .got2           : { *(.got2) }
+  .dynamic        : { *(.dynamic) }
+  .got            : SPECIAL { *(.got) }
+  . = DATA_SEGMENT_RELRO_END (0, .);
+  .plt            : SPECIAL { *(.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    KEEP (*(.gnu.linkonce.d.*personality*))
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .got            : SPECIAL { *(.got) }
   /* We want the small data sections together, so single-instruction offsets
      can access them all, and initialized data all before uninitialized, so
      we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
+  .sdata          :
+  {
+    PROVIDE (_SDA_BASE_ = 32768);
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+  }
+  _edata = .; PROVIDE (edata = .);
   __bss_start = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
+  .sbss           :
   {
+    PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .);
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+    PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .);
+  }
+  .plt            : SPECIAL { *(.plt) }
+  .bss            :
+  {
    *(.dynbss)
-   *(.bss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
    *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 32 / 8 : 1);
   }
-  _end = . ;
-  PROVIDE (end = .);
+  . = ALIGN(32 / 8);
+  . = ALIGN(32 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
@@ -137,4 +223,6 @@
   .debug_typenames 0 : { *(.debug_typenames) }
   .debug_varnames  0 : { *(.debug_varnames) }
   /* These must appear regardless of  .  */
+  /DISCARD/    : { *(.fixup) }
+  /DISCARD/ : { *(.note.GNU-stack) }
 }

Modified: trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/qemu-binfmt-conf.sh	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,8 +1,13 @@
 #!/bin/sh
-# enable automatic i386/ARM/SPARC/PPC program execution by the kernel
+# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC program execution by the kernel
 
 # load the binfmt_misc module
-/sbin/modprobe binfmt_misc
+if [ ! -d /proc/sys/fs/binfmt_misc ]; then
+  /sbin/modprobe binfmt_misc
+fi
+if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
+  mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
+fi
 
 # probe cpu type
 cpu=`uname -m`
@@ -10,6 +15,12 @@
   i386|i486|i586|i686|i86pc|BePC)
     cpu="i386"
   ;;
+  m68k)
+    cpu="m68k"
+  ;;
+  mips*)
+    cpu="mips"
+  ;;
   "Power Macintosh"|ppc|ppc64)
     cpu="ppc"
   ;;
@@ -33,7 +44,12 @@
 if [ $cpu != "ppc" ] ; then
     echo   ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
 fi
+if [ $cpu != "m68k" ] ; then
+    echo   'Please check cpu value and header information for m68k!'
+    echo   ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
+fi
 if [ $cpu != "mips" ] ; then
+    # FIXME: We could use the other endianness on a MIPS host.
     echo   ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
     echo   ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
 fi

Modified: trunk/src/host/qemu-neo1973/qemu-doc.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-doc.texi	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi	2007-05-11 23:44:50 UTC (rev 1948)
@@ -25,7 +25,7 @@
 * Installation::
 * QEMU PC System emulator::
 * QEMU System emulator for non PC targets::
-* QEMU Linux User space emulator::
+* QEMU User space emulator::
 * compilation:: Compilation from the sources
 * Index::
 @end menu
@@ -57,8 +57,8 @@
 without rebooting the PC or to debug system code.
 
 @item 
-User mode emulation (Linux host only). In this mode, QEMU can launch
-Linux processes compiled for one CPU on another CPU. It can be used to
+User mode emulation. In this mode, QEMU can launch
+processes compiled for one CPU on another CPU. It can be used to
 launch the Wine Windows API emulator (@url{http://www.winehq.org}) or
 to ease cross-compilation and cross-debugging.
 
@@ -77,8 +77,10 @@
 @item Sun4m (32-bit Sparc processor)
 @item Sun4u (64-bit Sparc processor, in progress)
 @item Malta board (32-bit MIPS processor)
- at item ARM Integrator/CP (ARM926E or 1026E processor)
+ at item ARM Integrator/CP (ARM926E, 1026E or 946E processor)
 @item ARM Versatile baseboard (ARM926E)
+ at item ARM RealView Emulation baseboard (ARM926EJ-S)
+ at item Spitz, Akita, Borzoi and Terrier PDAs (PXA270 processor)
 @end itemize
 
 For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
@@ -247,6 +249,12 @@
 the console. Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 
+ at item -no-frame
+
+Do not use decorations for SDL windows and start them using the whole
+available screen space. This makes the using QEMU in a dedicated desktop
+workspace more convenient.
+
 @item -vnc display
 
 Normally, QEMU uses SDL to display the VGA output.  With this option,
@@ -324,6 +332,10 @@
 Load the contents of file as an option ROM.  This option is useful to load
 things like EtherBoot.
 
+ at item -name string
+Sets the name of the guest.  This name will be display in the SDL window
+caption.  The name will also be used for the VNC server.
+
 @end table
 
 USB options:
@@ -345,10 +357,12 @@
 = 0 is the default). The NIC is currently an NE2000 on the PC
 target. Optionally, the MAC address can be changed. If no
 @option{-net} option is specified, a single NIC is created.
-Qemu can emulate several different models of network card.  Valid values for
- at var{type} are @code{ne2k_pci}, @code{ne2k_isa}, @code{rtl8139},
- at code{smc91c111} and @code{lance}.  Not all devices are supported on all
-targets.
+Qemu can emulate several different models of network card.
+Valid values for @var{type} are
+ at code{i82551}, @code{i82557b}, @code{i82559er},
+ at code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139},
+ at code{smc91c111} and @code{lance}.
+Not all devices are supported on all targets.
 
 @item -net user[,vlan=n][,hostname=name]
 Use the user mode network stack which requires no administrator
@@ -358,7 +372,8 @@
 @item -net tap[,vlan=n][,fd=h][,ifname=name][,script=file]
 Connect the host TAP network interface @var{name} to VLAN @var{n} and
 use the network script @var{file} to configure it. The default
-network script is @file{/etc/qemu-ifup}. If @var{name} is not
+network script is @file{/etc/qemu-ifup}. Use @option{script=no} to
+disable script execution. If @var{name} is not
 provided, the OS automatically provides one.  @option{fd=h} can be
 used to specify the handle of an already opened host TAP interface. Example:
 
@@ -437,14 +452,23 @@
 override the default configuration (@option{-net nic -net user}) which
 is activated if no @option{-net} options are provided.
 
- at item -tftp prefix
+ at item -tftp dir
 When using the user mode network stack, activate a built-in TFTP
-server. All filenames beginning with @var{prefix} can be downloaded
-from the host to the guest using a TFTP client. The TFTP client on the
-guest must be configured in binary mode (use the command @code{bin} of
-the Unix TFTP client). The host IP address on the guest is as usual
-10.0.2.2.
+server. The files in @var{dir} will be exposed as the root of a TFTP server.
+The TFTP client on the guest must be configured in binary mode (use the command
+ at code{bin} of the Unix TFTP client). The host IP address on the guest is as
+usual 10.0.2.2.
 
+ at item -bootp file
+When using the user mode network stack, broadcast @var{file} as the BOOTP
+filename.  In conjunction with @option{-tftp}, this can be used to network boot
+a guest from a local directory.
+
+Example (using pxelinux):
+ at example
+qemu -hda linux.img -boot n -tftp /path/to/tftp/files -bootp /pxelinux.0
+ at end example
+
 @item -smb dir
 When using the user mode network stack, activate a built-in SMB
 server so that Windows OSes can access to the host files in @file{dir}
@@ -540,7 +564,7 @@
 parameters are set according to the emulated ones.
 @item /dev/parportN
 [Linux only, parallel port only] Use host parallel port
- at var{N}. Currently only SPP parallel port features can be used.
+ at var{N}. Currently SPP and EPP parallel port features can be used.
 @item file:filename
 Write output to filename. No character can be read.
 @item stdio
@@ -576,13 +600,14 @@
 @end table
 
 
- at item tcp:[host]:port[,server][,nowait]
+ at item tcp:[host]:port[,server][,nowait][,nodelay]
 The TCP Net Console has two modes of operation.  It can send the serial
 I/O to a location or wait for a connection from a location.  By default
 the TCP Net Console is sent to @var{host} at the @var{port}.  If you use
 the @var{server} option QEMU will wait for a client socket application
 to connect to the port before continuing, unless the @code{nowait}
-option was specified. If @var{host} is omitted, 0.0.0.0 is assumed. Only
+option was specified.  The @code{nodelay} option disables the Nagle buffering
+algoritm.  If @var{host} is omitted, 0.0.0.0 is assumed. Only
 one TCP connection at a time is accepted. You can use @code{telnet} to
 connect to the corresponding character device.
 @table @code
@@ -594,7 +619,7 @@
 -serial tcp:192.168.0.100:4444,server,nowait
 @end table
 
- at item telnet:host:port[,server][,nowait]
+ at item telnet:host:port[,server][,nowait][,nodelay]
 The telnet protocol is used instead of raw tcp sockets.  The options
 work the same as if you had specified @code{-serial tcp}.  The
 difference is that the port acts like a telnet server or client using
@@ -608,8 +633,20 @@
 same as if you had specified @code{-serial tcp} except the unix domain socket
 @var{path} is used for connections.
 
+ at item mon:dev_string
+This is a special option to allow the monitor to be multiplexed onto
+another serial port.  The monitor is accessed with key sequence of
+ at key{Control-a} and then pressing @key{c}. See monitor access
+ at ref{pcsys_keys} in the -nographic section for more keys.
+ at var{dev_string} should be any one of the serial devices specified
+above.  An example to multiplex the monitor onto a telnet server
+listening on port 4444 would be:
+ at table @code
+ at item -serial mon:telnet::4444,server,nowait
 @end table
 
+ at end table
+
 @item -parallel dev
 Redirect the virtual parallel port to host device @var{dev} (same
 devices as the serial port). On Linux hosts, @file{/dev/parportN} can
@@ -627,10 +664,24 @@
 The default device is @code{vc} in graphical mode and @code{stdio} in
 non graphical mode.
 
+ at item -echr numeric_ascii_value
+Change the escape character used for switching to the monitor when using
+monitor and serial sharing.  The default is @code{0x01} when using the
+ at code{-nographic} option.  @code{0x01} is equal to pressing
+ at code{Control-a}.  You can select a different character from the ascii
+control keys where 1 through 26 map to Control-a through Control-z.  For
+instance you could use the either of the following to change the escape
+character to Control-t.
+ at table @code
+ at item -echr 0x14
+ at item -echr 20
+ at end table
+
 @item -s
 Wait gdb connection to port 1234 (@pxref{gdb_usage}). 
 @item -p port
-Change gdb connection port.
+Change gdb connection port.  @var{port} can be either a decimal number
+to specify a TCP port, or a host device (same devices as the serial port).
 @item -S
 Do not start CPU at startup (you must type 'c' in the monitor).
 @item -d             
@@ -661,6 +712,11 @@
 
 @item -loadvm file
 Start right away with a saved state (@code{loadvm} in monitor)
+
+ at item -semihosting
+Enable "Angel" semihosting interface (ARM target machines only).
+Note that this allows guest direct access to the host filesystem,
+so should only be used with trusted guest OS.
 @end table
 
 @c man end
@@ -703,6 +759,8 @@
 Exit emulator
 @item Ctrl-a s    
 Save disk data back to file (if -snapshot)
+ at item Ctrl-a t
+toggle console timestamps
 @item Ctrl-a b
 Send break (magic sysrq in Linux)
 @item Ctrl-a c
@@ -734,7 +792,7 @@
 @itemize @minus
 
 @item
-Remove or insert removable medias images
+Remove or insert removable media images
 (such as CD-ROM or floppies)
 
 @item 
@@ -787,10 +845,10 @@
 Quit the emulator.
 
 @item eject [-f] device
-Eject a removable media (use -f to force it).
+Eject a removable medium (use -f to force it).
 
 @item change device filename
-Change a removable media.
+Change a removable medium.
 
 @item screendump filename
 Save screen into PPM image @var{filename}.
@@ -1085,7 +1143,7 @@
 alternate syntax @file{\\.\d:} is supported. @file{/dev/cdrom} is
 supported as an alias to the first CDROM drive.
 
-Currently there is no specific code to handle removable medias, so it
+Currently there is no specific code to handle removable media, so it
 is better to use the @code{change} or @code{eject} monitor commands to
 change or eject media.
 @item Hard disks
@@ -1103,7 +1161,7 @@
 
 @file{/dev/cdrom} is an alias to the first CDROM. 
 
-Currently there is no specific code to handle removable medias, so it
+Currently there is no specific code to handle removable media, so it
 is better to use the @code{change} or @code{eject} monitor commands to
 change or eject media.
 
@@ -1605,6 +1663,15 @@
 
 Set the initial TCX graphic mode. The default is 1024x768.
 
+ at item -prom-env string
+
+Set OpenBIOS variables in NVRAM, for example:
+
+ at example
+qemu-system-sparc -prom-env 'auto-boot?=false' \
+ -prom-env 'boot-device=sd(0,2,0):d' -prom-env 'boot-args=linux single'
+ at end example
+
 @end table
 
 @c man end 
@@ -1655,7 +1722,7 @@
 
 @itemize @minus
 @item
-ARM926E or ARM1026E CPU
+ARM926E, ARM1026E or ARM946E CPU
 @item
 Two PL011 UARTs
 @item 
@@ -1664,6 +1731,8 @@
 PL110 LCD controller
 @item
 PL050 KMI with PS/2 keyboard and mouse.
+ at item
+PL181 MultiMedia Card Interface with SD card.
 @end itemize
 
 The ARM Versatile baseboard is emulated with the following devices:
@@ -1691,15 +1760,93 @@
 PCI OHCI USB controller.
 @item
 LSI53C895A PCI SCSI Host Bus Adapter with hard disk and CD-ROM devices.
+ at item
+PL181 MultiMedia Card Interface with SD card.
 @end itemize
 
+The ARM RealView Emulation baseboard is emulated with the following devices:
+
+ at itemize @minus
+ at item
+ARM926E CPU
+ at item
+ARM AMBA Generic/Distributed Interrupt Controller
+ at item
+Four PL011 UARTs
+ at item 
+SMC 91c111 Ethernet adapter
+ at item
+PL110 LCD controller
+ at item
+PL050 KMI with PS/2 keyboard and mouse
+ at item
+PCI host bridge
+ at item
+PCI OHCI USB controller
+ at item
+LSI53C895A PCI SCSI Host Bus Adapter with hard disk and CD-ROM devices
+ at item
+PL181 MultiMedia Card Interface with SD card.
+ at end itemize
+
+The XScale-based clamshell PDA models ("Spitz", "Akita", "Borzoi"
+and "Terrier") emulation includes the following peripherals:
+
+ at itemize @minus
+ at item
+Intel PXA270 System-on-chip (ARM V5TE core)
+ at item
+NAND Flash memory
+ at item
+IBM/Hitachi DSCM microdrive in a PXA PCMCIA slot - not in "Akita"
+ at item
+On-chip OHCI USB controller
+ at item
+On-chip LCD controller
+ at item
+On-chip Real Time Clock
+ at item
+TI ADS7846 touchscreen controller on SSP bus
+ at item
+Maxim MAX1111 analog-digital converter on I at math{^2}C bus
+ at item
+GPIO-connected keyboard controller and LEDs
+ at item
+Secure Digital card connected to PXA MMC/SD host
+ at item
+Three on-chip UARTs
+ at item
+WM8750 audio CODEC on I at math{^2}C and I at math{^2}S busses
+ at end itemize
+
 A Linux 2.6 test image is available on the QEMU web site. More
 information is available in the QEMU mailing-list archive.
 
- at node QEMU Linux User space emulator 
- at chapter QEMU Linux User space emulator 
+ at node QEMU User space emulator 
+ at chapter QEMU User space emulator 
 
 @menu
+* Supported Operating Systems ::
+* Linux User space emulator::
+* Mac OS X/Darwin User space emulator ::
+ at end menu
+
+ at node Supported Operating Systems
+ at section Supported Operating Systems
+
+The following OS are supported in user space emulation:
+
+ at itemize @minus
+ at item
+Linux (refered as qemu-linux-user)
+ at item
+Mac OS X/Darwin (refered as qemu-darwin-user)
+ at end itemize
+
+ at node Linux User space emulator
+ at section Linux User space emulator
+
+ at menu
 * Quick Start::
 * Wine launch::
 * Command line options::
@@ -1707,7 +1854,7 @@
 @end menu
 
 @node Quick Start
- at section Quick Start
+ at subsection Quick Start
 
 In order to launch a Linux process, QEMU needs the process executable
 itself and all the target (x86) dynamic libraries used by it. 
@@ -1724,7 +1871,8 @@
 @code{-L /} tells that the x86 dynamic linker must be searched with a
 @file{/} prefix.
 
- at item Since QEMU is also a linux process, you can launch qemu with qemu (NOTE: you can only do that if you compiled QEMU from the sources):
+ at item Since QEMU is also a linux process, you can launch qemu with
+qemu (NOTE: you can only do that if you compiled QEMU from the sources):
 
 @example 
 qemu-i386 -L / qemu-i386 -L / /bin/ls
@@ -1757,7 +1905,7 @@
 @end itemize
 
 @node Wine launch
- at section Wine launch
+ at subsection Wine launch
 
 @itemize
 
@@ -1786,7 +1934,7 @@
 @end itemize
 
 @node Command line options
- at section Command line options
+ at subsection Command line options
 
 @example
 usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
@@ -1811,7 +1959,7 @@
 @end table
 
 @node Other binaries
- at section Other binaries
+ at subsection Other binaries
 
 @command{qemu-arm} is also capable of running ARM "Angel" semihosted ELF
 binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
@@ -1823,6 +1971,91 @@
 
 The binary format is detected automatically.
 
+ at node Mac OS X/Darwin User space emulator
+ at section Mac OS X/Darwin User space emulator
+
+ at menu
+* Mac OS X/Darwin Status::
+* Mac OS X/Darwin Quick Start::
+* Mac OS X/Darwin Command line options::
+ at end menu
+
+ at node Mac OS X/Darwin Status
+ at subsection Mac OS X/Darwin Status
+
+ at itemize @minus
+ at item
+target x86 on x86: Most apps (Cocoa and Carbon too) works. [1]
+ at item
+target PowerPC on x86: Not working as the ppc commpage can't be mapped (yet!)
+ at item
+target PowerPC on PowerPC: Most apps (Cocoa and Carbon too) works. [1]
+ at item
+target x86 on PowerPC: most utilities work. Cocoa and Carbon apps are not yet supported.
+ at end itemize
+
+[1] If you're host commpage can be executed by qemu.
+
+ at node Mac OS X/Darwin Quick Start
+ at subsection Quick Start
+
+In order to launch a Mac OS X/Darwin process, QEMU needs the process executable
+itself and all the target dynamic libraries used by it. If you don't have the FAT
+libraries (you're running Mac OS X/ppc) you'll need to obtain it from a Mac OS X
+CD or compile them by hand.
+
+ at itemize
+
+ at item On x86, you can just try to launch any process by using the native
+libraries:
+
+ at example 
+qemu-i386 /bin/ls
+ at end example
+
+or to run the ppc version of the executable:
+
+ at example 
+qemu-ppc /bin/ls
+ at end example
+
+ at item On ppc, you'll have to tell qemu where your x86 libraries (and dynamic linker)
+are installed:
+
+ at example 
+qemu-i386 -L /opt/x86_root/ /bin/ls
+ at end example
+
+ at code{-L /opt/x86_root/} tells that the dynamic linker (dyld) path is in
+ at file{/opt/x86_root/usr/bin/dyld}.
+
+ at end itemize
+
+ at node Mac OS X/Darwin Command line options
+ at subsection Command line options
+
+ at example
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+ at end example
+
+ at table @option
+ at item -h
+Print the help
+ at item -L path   
+Set the library root path (default=/)
+ at item -s size
+Set the stack size in bytes (default=524288)
+ at end table
+
+Debug options:
+
+ at table @option
+ at item -d
+Activate log (logfile=/tmp/qemu.log)
+ at item -p pagesize
+Act as if the host page size was 'pagesize' bytes
+ at end table
+
 @node compilation
 @chapter Compilation from the sources
 
@@ -1857,40 +2090,16 @@
 @end example
 to install QEMU in @file{/usr/local}.
 
- at subsection Tested tool versions
+ at subsection GCC version
 
 In order to compile QEMU successfully, it is very important that you
-have the right tools. The most important one is gcc. I cannot guaranty
-that QEMU works if you do not use a tested gcc version. Look at
-'configure' and 'Makefile' if you want to make a different gcc
-version work.
+have the right tools. The most important one is gcc. On most hosts and
+in particular on x86 ones, @emph{gcc 4.x is not supported}. If your
+Linux distribution includes a gcc 4.x compiler, you can usually
+install an older version (it is invoked by @code{gcc32} or
+ at code{gcc34}). The QEMU configure script automatically probes for
+these older versions so that usally you don't have to do anything.
 
- at example
-host      gcc      binutils      glibc    linux       distribution
-----------------------------------------------------------------------
-x86       3.2      2.13.2        2.1.3    2.4.18
-          2.96     2.11.93.0.2   2.2.5    2.4.18      Red Hat 7.3
-          3.2.2    2.13.90.0.18  2.3.2    2.4.20      Red Hat 9
-
-PowerPC   3.3 [4]  2.13.90.0.18  2.3.1    2.4.20briq
-          3.2
-
-Alpha     3.3 [1]  2.14.90.0.4   2.2.5    2.2.20 [2]  Debian 3.0
-
-Sparc32   2.95.4   2.12.90.0.1   2.2.5    2.4.18      Debian 3.0
-
-ARM       2.95.4   2.12.90.0.1   2.2.5    2.4.9 [3]   Debian 3.0
-
-[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
-    for gcc version >= 3.3.
-[2] Linux >= 2.4.20 is necessary for precise exception support
-    (untested).
-[3] 2.4.9-ac10-rmk2-np1-cerf2
-
-[4] gcc 2.95.x generates invalid code when using too many register
-variables. You must use gcc 3.x on PowerPC.
- at end example
-
 @node Windows
 @section Windows
 

Modified: trunk/src/host/qemu-neo1973/qemu-img.c
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-img.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/qemu-img.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU disk image utility
  * 
- * Copyright (c) 2003-2006 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -93,7 +93,7 @@
 
 void help(void)
 {
-    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2006 Fabrice Bellard\n"
+    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2007 Fabrice Bellard\n"
            "usage: qemu-img command [command options]\n"
            "QEMU disk image utility\n"
            "\n"
@@ -457,7 +457,7 @@
 
     drv = bdrv_find_format(out_fmt);
     if (!drv)
-        error("Unknown file format '%s'", fmt);
+        error("Unknown file format '%s'", out_fmt);
     if (compress && drv != &bdrv_qcow && drv != &bdrv_qcow2)
         error("Compression not supported for this file format");
     if (encrypt && drv != &bdrv_qcow && drv != &bdrv_qcow2)

Modified: trunk/src/host/qemu-neo1973/qemu-tech.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-tech.texi	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/qemu-tech.texi	2007-05-11 23:44:50 UTC (rev 1948)
@@ -169,11 +169,11 @@
 
 @itemize
 
- at item Somewhat complete SPARC V8 emulation, including privileged
+ at item Full SPARC V8 emulation, including privileged
 instructions, FPU and MMU. SPARC V9 emulation includes most privileged
-instructions, FPU and I/D MMU, but misses VIS instructions.
+instructions, FPU and I/D MMU, but misses most VIS instructions.
 
- at item Can run some 32-bit SPARC Linux binaries.
+ at item Can run most 32-bit SPARC Linux binaries and some handcrafted 64-bit SPARC Linux binaries.
 
 @end itemize
 
@@ -181,9 +181,6 @@
 
 @itemize 
 
- at item Tagged add/subtract instructions are not supported, but they are
-probably not used.
-
 @item IPC syscalls are missing.
 
 @item 128-bit floating point operations are not supported, though none of the

Modified: trunk/src/host/qemu-neo1973/sdl.c
===================================================================
--- trunk/src/host/qemu-neo1973/sdl.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/sdl.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -34,6 +34,7 @@
 static int last_vm_running;
 static int gui_saved_grab;
 static int gui_fullscreen;
+static int gui_noframe;
 static int gui_key_modifier_pressed;
 static int gui_keysym;
 static int gui_fullscreen_initial_grab;
@@ -43,6 +44,9 @@
 static SDL_Cursor *sdl_cursor_normal;
 static SDL_Cursor *sdl_cursor_hidden;
 static int absolute_enabled = 0;
+static int guest_cursor = 0;
+static int guest_x, guest_y;
+static SDL_Cursor *guest_sprite = 0;
 
 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 {
@@ -59,6 +63,8 @@
     flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
     if (gui_fullscreen)
         flags |= SDL_FULLSCREEN;
+    if (gui_noframe)
+        flags |= SDL_NOFRAME;
 
     width = w;
     height = h;
@@ -122,88 +128,6 @@
 
 #else
 
-static const uint8_t x_keycode_to_pc_keycode[115] = {
-   0xc7,      /*  97  Home   */
-   0xc8,      /*  98  Up     */
-   0xc9,      /*  99  PgUp   */
-   0xcb,      /* 100  Left   */
-   0x4c,        /* 101  KP-5   */
-   0xcd,      /* 102  Right  */
-   0xcf,      /* 103  End    */
-   0xd0,      /* 104  Down   */
-   0xd1,      /* 105  PgDn   */
-   0xd2,      /* 106  Ins    */
-   0xd3,      /* 107  Del    */
-   0x9c,      /* 108  Enter  */
-   0x9d,      /* 109  Ctrl-R */
-   0x0,       /* 110  Pause  */
-   0xb7,      /* 111  Print  */
-   0xb5,      /* 112  Divide */
-   0xb8,      /* 113  Alt-R  */
-   0xc6,      /* 114  Break  */   
-   0x0,         /* 115 */
-   0x0,         /* 116 */
-   0x0,         /* 117 */
-   0x0,         /* 118 */
-   0x0,         /* 119 */
-   0x0,         /* 120 */
-   0x0,         /* 121 */
-   0x0,         /* 122 */
-   0x0,         /* 123 */
-   0x0,         /* 124 */
-   0x0,         /* 125 */
-   0x0,         /* 126 */
-   0x0,         /* 127 */
-   0x0,         /* 128 */
-   0x79,         /* 129 Henkan */
-   0x0,         /* 130 */
-   0x7b,         /* 131 Muhenkan */
-   0x0,         /* 132 */
-   0x7d,         /* 133 Yen */
-   0x0,         /* 134 */
-   0x0,         /* 135 */
-   0x47,         /* 136 KP_7 */
-   0x48,         /* 137 KP_8 */
-   0x49,         /* 138 KP_9 */
-   0x4b,         /* 139 KP_4 */
-   0x4c,         /* 140 KP_5 */
-   0x4d,         /* 141 KP_6 */
-   0x4f,         /* 142 KP_1 */
-   0x50,         /* 143 KP_2 */
-   0x51,         /* 144 KP_3 */
-   0x52,         /* 145 KP_0 */
-   0x53,         /* 146 KP_. */
-   0x47,         /* 147 KP_HOME */
-   0x48,         /* 148 KP_UP */
-   0x49,         /* 149 KP_PgUp */
-   0x4b,         /* 150 KP_Left */
-   0x4c,         /* 151 KP_ */
-   0x4d,         /* 152 KP_Right */
-   0x4f,         /* 153 KP_End */
-   0x50,         /* 154 KP_Down */
-   0x51,         /* 155 KP_PgDn */
-   0x52,         /* 156 KP_Ins */
-   0x53,         /* 157 KP_Del */
-   0x0,         /* 158 */
-   0x0,         /* 159 */
-   0x0,         /* 160 */
-   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 170 */
-   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 180 */
-   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 190 */
-   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 200 */
-   0x0,         /* 201 */
-   0x0,         /* 202 */
-   0x0,         /* 203 */
-   0x0,         /* 204 */
-   0x0,         /* 205 */
-   0x0,         /* 206 */
-   0x0,         /* 207 */
-   0x70,         /* 208 Hiragana_Katakana */
-   0x0,         /* 209 */
-   0x0,         /* 210 */
-   0x73,         /* 211 backslash */
-};
-
 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
 {
     int keycode;
@@ -216,7 +140,7 @@
         keycode -= 8; /* just an offset */
     } else if (keycode < 212) {
         /* use conversion table */
-        keycode = x_keycode_to_pc_keycode[keycode - 97];
+        keycode = _translate_keycode(keycode - 97);
     } else {
         keycode = 0;
     }
@@ -295,13 +219,18 @@
 static void sdl_update_caption(void)
 {
     char buf[1024];
-    strcpy(buf, "QEMU");
-    if (!vm_running) {
-        strcat(buf, " [Stopped]");
-    }
-    if (gui_grab) {
-        strcat(buf, " - Press Ctrl-Alt to exit grab");
-    }
+    const char *status = "";
+
+    if (!vm_running)
+        status = " [Stopped]";
+    else if (gui_grab)
+        status = " - Press Ctrl-Alt to exit grab";
+
+    if (qemu_name)
+        snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
+    else
+        snprintf(buf, sizeof(buf), "QEMU%s", status);
+
     SDL_WM_SetCaption(buf, "QEMU");
 }
 
@@ -325,13 +254,21 @@
 
     if (!kbd_mouse_is_absolute()) {
         SDL_ShowCursor(1);
-        SDL_SetCursor(sdl_cursor_normal);
+        if (guest_cursor &&
+                (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
+            SDL_SetCursor(guest_sprite);
+        else
+            SDL_SetCursor(sdl_cursor_normal);
     }
 }
 
 static void sdl_grab_start(void)
 {
-    sdl_hide_cursor();
+    if (guest_cursor) {
+        SDL_SetCursor(guest_sprite);
+        SDL_WarpMouse(guest_x, guest_y);
+    } else
+        sdl_hide_cursor();
     SDL_WM_GrabInput(SDL_GRAB_ON);
     /* dummy read to avoid moving the mouse */
     SDL_GetRelativeMouseState(NULL, NULL);
@@ -342,8 +279,8 @@
 static void sdl_grab_end(void)
 {
     SDL_WM_GrabInput(SDL_GRAB_OFF);
+    gui_grab = 0;
     sdl_show_cursor();
-    gui_grab = 0;
     sdl_update_caption();
 }
 
@@ -374,6 +311,12 @@
     } else if (absolute_enabled) {
 	sdl_show_cursor();
 	absolute_enabled = 0;
+    } else if (guest_cursor) {
+        SDL_GetMouseState(&dx, &dy);
+        dx -= guest_x;
+        dy -= guest_y;
+        guest_x += dx;
+        guest_y += dy;
     }
 
     kbd_mouse_event(dx, dy, dz, buttons);
@@ -552,12 +495,81 @@
     }
 }
 
+static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
+{
+    SDL_Rect dst = { x, y, w, h };
+    SDL_FillRect(screen, &dst, c);
+}
+
+static void sdl_mouse_warp(int x, int y, int on)
+{
+    if (on) {
+        if (!guest_cursor)
+            sdl_show_cursor();
+        if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
+            SDL_SetCursor(guest_sprite);
+            SDL_WarpMouse(x, y);
+        }
+    } else if (gui_grab)
+        sdl_hide_cursor();
+    guest_cursor = on;
+    guest_x = x, guest_y = y;
+}
+
+static void sdl_mouse_define(int width, int height, int bpp,
+                             int hot_x, int hot_y,
+                             uint8_t *image, uint8_t *mask)
+{
+    uint8_t sprite[256], *line;
+    int x, y, dst, bypl, src = 0;
+    if (guest_sprite)
+        SDL_FreeCursor(guest_sprite);
+
+    memset(sprite, 0, 256);
+    bypl = ((width * bpp + 31) >> 5) << 2;
+    for (y = 0, dst = 0; y < height; y ++, image += bypl) {
+        line = image;
+        for (x = 0; x < width; x ++, dst ++) {
+            switch (bpp) {
+            case 24:
+                src = *(line ++); src |= *(line ++); src |= *(line ++);
+                break;
+            case 16:
+            case 15:
+                src = *(line ++); src |= *(line ++);
+                break;
+            case 8:
+                src = *(line ++);
+                break;
+            case 4:
+                src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
+                break;
+            case 2:
+                src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
+                break;
+            case 1:
+                src = 1 & (line[x >> 3] >> (x & 7));
+                break;
+            }
+            if (!src)
+                sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
+        }
+    }
+    guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
+
+    if (guest_cursor &&
+            (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
+        SDL_SetCursor(guest_sprite);
+}
+
 static void sdl_cleanup(void) 
 {
+    if (guest_sprite)
+        SDL_FreeCursor(guest_sprite);
     SDL_Quit();
 }
 
-void sdl_display_init(DisplayState *ds, int full_screen)
+void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 {
     int flags;
     uint8_t data = 0;
@@ -573,6 +585,9 @@
             exit(1);
     }
 
+    if (no_frame)
+        gui_noframe = 1;
+
     flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
     if (SDL_Init (flags)) {
         fprintf(stderr, "Could not initialize SDL - exiting\n");
@@ -587,6 +602,9 @@
     ds->dpy_update = sdl_update;
     ds->dpy_resize = sdl_resize;
     ds->dpy_refresh = sdl_refresh;
+    ds->dpy_fill = sdl_fill;
+    ds->mouse_set = sdl_mouse_warp;
+    ds->cursor_define = sdl_mouse_define;
 
     sdl_resize(ds, 640, 400);
     sdl_update_caption();

Modified: trunk/src/host/qemu-neo1973/slirp/bootp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/bootp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/slirp/bootp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -38,6 +38,8 @@
 
 BOOTPClient bootp_clients[NB_ADDR];
 
+const char *bootp_filename;
+
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
 #ifdef DEBUG
@@ -168,6 +170,10 @@
             goto new_addr;
         }
     }
+
+    if (bootp_filename)
+        snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
+
     dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
 
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);

Modified: trunk/src/host/qemu-neo1973/slirp/tftp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tftp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/slirp/tftp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -102,9 +102,16 @@
 {
   int fd;
   int bytes_read = 0;
+  char buffer[1024];
+  int n;
 
-  fd = open(spt->filename, O_RDONLY | O_BINARY);
+  n = snprintf(buffer, sizeof(buffer), "%s/%s",
+	       tftp_prefix, spt->filename);
+  if (n >= sizeof(buffer))
+    return -1;
 
+  fd = open(buffer, O_RDONLY | O_BINARY);
+
   if (fd < 0) {
     return -1;
   }
@@ -120,6 +127,45 @@
   return bytes_read;
 }
 
+static int tftp_send_oack(struct tftp_session *spt, 
+                          const char *key, uint32_t value,
+                          struct tftp_t *recv_tp)
+{
+    struct sockaddr_in saddr, daddr;
+    struct mbuf *m;
+    struct tftp_t *tp;
+    int n = 0;
+
+    m = m_get();
+
+    if (!m)
+	return -1;
+
+    memset(m->m_data, 0, m->m_size);
+
+    m->m_data += if_maxlinkhdr;
+    tp = (void *)m->m_data;
+    m->m_data += sizeof(struct udpiphdr);
+    
+    tp->tp_op = htons(TFTP_OACK);
+    n += sprintf(tp->x.tp_buf + n, "%s", key) + 1;
+    n += sprintf(tp->x.tp_buf + n, "%u", value) + 1;
+
+    saddr.sin_addr = recv_tp->ip.ip_dst;
+    saddr.sin_port = recv_tp->udp.uh_dport;
+    
+    daddr.sin_addr = spt->client_ip;
+    daddr.sin_port = spt->client_port;
+
+    m->m_len = sizeof(struct tftp_t) - 514 + n - 
+        sizeof(struct ip) - sizeof(struct udphdr);
+    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+
+    return 0;
+}
+
+
+
 static int tftp_send_error(struct tftp_session *spt, 
 			   u_int16_t errorcode, const char *msg,
 			   struct tftp_t *recv_tp)
@@ -273,6 +319,8 @@
       return;
   }
 
+  k += 6; /* skipping octet */
+
   /* do sanity checks on the filename */
 
   if ((spt->filename[0] != '/')
@@ -284,8 +332,7 @@
 
   /* only allow exported prefixes */
 
-  if (!tftp_prefix
-      || (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) {
+  if (!tftp_prefix) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
@@ -297,6 +344,48 @@
       return;
   }
 
+  if (src[n - 1] != 0) {
+      tftp_send_error(spt, 2, "Access violation", tp);
+      return;
+  }
+
+  while (k < n) {
+      const char *key, *value;
+
+      key = src + k;
+      k += strlen(key) + 1;
+
+      if (k >= n) {
+	  tftp_send_error(spt, 2, "Access violation", tp);
+	  return;
+      }
+
+      value = src + k;
+      k += strlen(value) + 1;
+
+      if (strcmp(key, "tsize") == 0) {
+	  int tsize = atoi(value);
+	  struct stat stat_p;
+
+	  if (tsize == 0 && tftp_prefix) {
+	      char buffer[1024];
+	      int len;
+
+	      len = snprintf(buffer, sizeof(buffer), "%s/%s",
+			     tftp_prefix, spt->filename);
+
+	      if (stat(buffer, &stat_p) == 0)
+		  tsize = stat_p.st_size;
+	      else {
+		  tftp_send_error(spt, 1, "File not found", tp);
+		  return;
+	      }
+	  }
+
+	  tftp_send_oack(spt, "tsize", tsize, tp);
+      }
+  }
+
   tftp_send_data(spt, 1, tp);
 }
 

Modified: trunk/src/host/qemu-neo1973/slirp/tftp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/tftp.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/slirp/tftp.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -9,6 +9,7 @@
 #define TFTP_DATA   3
 #define TFTP_ACK    4
 #define TFTP_ERROR  5
+#define TFTP_OACK   6
 
 #define TFTP_FILENAME_MAX 512
 

Modified: trunk/src/host/qemu-neo1973/slirp/udp.c
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/udp.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/slirp/udp.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -205,8 +205,6 @@
 	  /* udp_last_so = so; */
 	  so->so_laddr = ip->ip_src;
 	  so->so_lport = uh->uh_sport;
-	  so->so_faddr = ip->ip_dst; /* XXX */
-	  so->so_fport = uh->uh_dport; /* XXX */
 	  
 	  if ((so->so_iptos = udp_tos(so)) == 0)
 	    so->so_iptos = ip->ip_tos;
@@ -217,6 +215,9 @@
 	   */
 	}
 
+        so->so_faddr = ip->ip_dst; /* XXX */
+        so->so_fport = uh->uh_dport; /* XXX */
+
 	iphlen += sizeof(struct udphdr);
 	m->m_len -= iphlen;
 	m->m_data += iphlen;

Modified: trunk/src/host/qemu-neo1973/softmmu_header.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu_header.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/softmmu_header.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -63,6 +63,8 @@
 #define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
 #elif defined (TARGET_SH4)
 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
+#elif defined (TARGET_ALPHA)
+#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
 #else
 #error unsupported CPU
 #endif
@@ -82,6 +84,8 @@
 #define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
 #elif defined (TARGET_SH4)
 #define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
+#elif defined (TARGET_ALPHA)
+#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
 #else
 #error unsupported CPU
 #endif

Modified: trunk/src/host/qemu-neo1973/sparc.ld
===================================================================
--- trunk/src/host/qemu-neo1973/sparc.ld	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/sparc.ld	2007-05-11 23:44:50 UTC (rev 1948)
@@ -64,6 +64,8 @@
     CONSTRUCTORS
   }
   .data1   : { *(.data1) }
+  .tdata    : { *(.tdata) }
+  .tbss    : { *(.tbss) }
   .ctors         :
   {
     *(.ctors)
@@ -125,4 +127,5 @@
   .debug_typenames 0 : { *(.debug_typenames) }
   .debug_varnames  0 : { *(.debug_varnames) }
   /* These must appear regardless of  .  */
+  /DISCARD/ : { *(.note.GNU-stack) *(.note.ABI-tag) }
 }

Added: trunk/src/host/qemu-neo1973/target-alpha/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,398 @@
+/*
+ *  Alpha emulation cpu definitions for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined (__CPU_ALPHA_H__)
+#define __CPU_ALPHA_H__
+
+#include "config.h"
+
+#define TARGET_LONG_BITS 64
+
+#include "cpu-defs.h"
+
+
+#include <setjmp.h>
+
+#include "softfloat.h"
+
+/* XXX: put this in a common place */
+#define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x)   __builtin_expect(!!(x), 0)
+
+#define TARGET_HAS_ICE 1
+
+#define ELF_MACHINE	EM_ALPHA
+
+#define ICACHE_LINE_SIZE 32
+#define DCACHE_LINE_SIZE 32
+
+#define TARGET_PAGE_BITS 12
+
+#define VA_BITS 43
+
+/* Alpha major type */
+enum {
+    ALPHA_EV3  = 1,
+    ALPHA_EV4  = 2,
+    ALPHA_SIM  = 3,
+    ALPHA_LCA  = 4,
+    ALPHA_EV5  = 5, /* 21164 */
+    ALPHA_EV45 = 6, /* 21064A */
+    ALPHA_EV56 = 7, /* 21164A */
+};
+
+/* EV4 minor type */
+enum {
+    ALPHA_EV4_2 = 0,
+    ALPHA_EV4_3 = 1,
+};
+
+/* LCA minor type */
+enum {
+    ALPHA_LCA_1 = 1, /* 21066 */
+    ALPHA_LCA_2 = 2, /* 20166 */
+    ALPHA_LCA_3 = 3, /* 21068 */
+    ALPHA_LCA_4 = 4, /* 21068 */
+    ALPHA_LCA_5 = 5, /* 21066A */
+    ALPHA_LCA_6 = 6, /* 21068A */
+};
+
+/* EV5 minor type */
+enum {
+    ALPHA_EV5_1 = 1, /* Rev BA, CA */
+    ALPHA_EV5_2 = 2, /* Rev DA, EA */
+    ALPHA_EV5_3 = 3, /* Pass 3 */
+    ALPHA_EV5_4 = 4, /* Pass 3.2 */
+    ALPHA_EV5_5 = 5, /* Pass 4 */
+};
+
+/* EV45 minor type */
+enum {
+    ALPHA_EV45_1 = 1, /* Pass 1 */
+    ALPHA_EV45_2 = 2, /* Pass 1.1 */
+    ALPHA_EV45_3 = 3, /* Pass 2 */
+};
+
+/* EV56 minor type */
+enum {
+    ALPHA_EV56_1 = 1, /* Pass 1 */
+    ALPHA_EV56_2 = 2, /* Pass 2 */
+};
+
+enum {
+    IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */
+    IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */
+    IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */
+    IMPLVER_21364 = 3, /* EV7 & EV79 */
+};
+
+enum {
+    AMASK_BWX      = 0x00000001,
+    AMASK_FIX      = 0x00000002,
+    AMASK_CIX      = 0x00000004,
+    AMASK_MVI      = 0x00000100,
+    AMASK_TRAP     = 0x00000200,
+    AMASK_PREFETCH = 0x00001000,
+};
+
+enum {
+    VAX_ROUND_NORMAL = 0,
+    VAX_ROUND_CHOPPED,
+};
+
+enum {
+    IEEE_ROUND_NORMAL = 0,
+    IEEE_ROUND_DYNAMIC,
+    IEEE_ROUND_PLUS,
+    IEEE_ROUND_MINUS,
+    IEEE_ROUND_CHOPPED,
+};
+
+/* IEEE floating-point operations encoding */
+/* Trap mode */
+enum {
+    FP_TRAP_I   = 0x0,
+    FP_TRAP_U   = 0x1,
+    FP_TRAP_S  = 0x4,
+    FP_TRAP_SU  = 0x5,
+    FP_TRAP_SUI = 0x7,
+};
+
+/* Rounding mode */
+enum {
+    FP_ROUND_CHOPPED = 0x0,
+    FP_ROUND_MINUS   = 0x1,
+    FP_ROUND_NORMAL  = 0x2,
+    FP_ROUND_DYNAMIC = 0x3,
+};
+
+/* Internal processor registers */
+/* XXX: TOFIX: most of those registers are implementation dependant */
+enum {
+    /* Ebox IPRs */
+    IPR_CC           = 0xC0,
+    IPR_CC_CTL       = 0xC1,
+    IPR_VA           = 0xC2,
+    IPR_VA_CTL       = 0xC4,
+    IPR_VA_FORM      = 0xC3,
+    /* Ibox IPRs */
+    IPR_ITB_TAG      = 0x00,
+    IPR_ITB_PTE      = 0x01,
+    IPT_ITB_IAP      = 0x02,
+    IPT_ITB_IA       = 0x03,
+    IPT_ITB_IS       = 0x04,
+    IPR_PMPC         = 0x05,
+    IPR_EXC_ADDR     = 0x06,
+    IPR_IVA_FORM     = 0x07,
+    IPR_CM           = 0x09,
+    IPR_IER          = 0x0A,
+    IPR_SIRR         = 0x0C,
+    IPR_ISUM         = 0x0D,
+    IPR_HW_INT_CLR   = 0x0E,
+    IPR_EXC_SUM      = 0x0F,
+    IPR_PAL_BASE     = 0x10,
+    IPR_I_CTL        = 0x11,
+    IPR_I_STAT       = 0x16,
+    IPR_IC_FLUSH     = 0x13,
+    IPR_IC_FLUSH_ASM = 0x12,
+    IPR_CLR_MAP      = 0x15,
+    IPR_SLEEP        = 0x17,
+    IPR_PCTX         = 0x40,
+    IPR_PCTR_CTL     = 0x14,
+    /* Mbox IPRs */
+    IPR_DTB_TAG0     = 0x20,
+    IPR_DTB_TAG1     = 0xA0,
+    IPR_DTB_PTE0     = 0x21,
+    IPR_DTB_PTE1     = 0xA1,
+    IPR_DTB_ALTMODE  = 0xA6,
+    IPR_DTB_IAP      = 0xA2,
+    IPR_DTB_IA       = 0xA3,
+    IPR_DTB_IS0      = 0x24,
+    IPR_DTB_IS1      = 0xA4,
+    IPR_DTB_ASN0     = 0x25,
+    IPR_DTB_ASN1     = 0xA5,
+    IPR_MM_STAT      = 0x27,
+    IPR_M_CTL        = 0x28,
+    IPR_DC_CTL       = 0x29,
+    IPR_DC_STAT      = 0x2A,
+    /* Cbox IPRs */
+    IPR_C_DATA       = 0x2B,
+    IPR_C_SHIFT      = 0x2C,
+
+    IPR_ASN,
+    IPR_ASTEN,
+    IPR_ASTSR,
+    IPR_DATFX,
+    IPR_ESP,
+    IPR_FEN,
+    IPR_IPIR,
+    IPR_IPL,
+    IPR_KSP,
+    IPR_MCES,
+    IPR_PERFMON,
+    IPR_PCBB,
+    IPR_PRBR,
+    IPR_PTBR,
+    IPR_SCBB,
+    IPR_SISR,
+    IPR_SSP,
+    IPR_SYSPTBR,
+    IPR_TBCHK,
+    IPR_TBIA,
+    IPR_TBIAP,
+    IPR_TBIS,
+    IPR_TBISD,
+    IPR_TBISI,
+    IPR_USP,
+    IPR_VIRBND,
+    IPR_VPTB,
+    IPR_WHAMI,
+    IPR_ALT_MODE,
+    IPR_LAST,
+};
+
+typedef struct CPUAlphaState CPUAlphaState;
+
+typedef struct pal_handler_t pal_handler_t;
+struct pal_handler_t {
+    /* Reset */
+    void (*reset)(CPUAlphaState *env);
+    /* Uncorrectable hardware error */
+    void (*machine_check)(CPUAlphaState *env);
+    /* Arithmetic exception */
+    void (*arithmetic)(CPUAlphaState *env);
+    /* Interrupt / correctable hardware error */
+    void (*interrupt)(CPUAlphaState *env);
+    /* Data fault */
+    void (*dfault)(CPUAlphaState *env);
+    /* DTB miss pal */
+    void (*dtb_miss_pal)(CPUAlphaState *env);
+    /* DTB miss native */
+    void (*dtb_miss_native)(CPUAlphaState *env);
+    /* Unaligned access */
+    void (*unalign)(CPUAlphaState *env);
+    /* ITB miss */
+    void (*itb_miss)(CPUAlphaState *env);
+    /* Instruction stream access violation */
+    void (*itb_acv)(CPUAlphaState *env);
+    /* Reserved or privileged opcode */
+    void (*opcdec)(CPUAlphaState *env);
+    /* Floating point exception */
+    void (*fen)(CPUAlphaState *env);
+    /* Call pal instruction */
+    void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
+};
+
+struct CPUAlphaState {
+    uint64_t ir[31];
+    float64  fir[31];
+    float_status fp_status;
+    uint64_t fpcr;
+    uint64_t pc;
+    uint64_t lock;
+    uint32_t pcc[2];
+    uint64_t ipr[IPR_LAST];
+    uint64_t ps;
+    uint64_t unique;
+    int saved_mode; /* Used for HW_LD / HW_ST */
+
+#if TARGET_LONG_BITS > HOST_LONG_BITS
+    /* temporary fixed-point registers
+     * used to emulate 64 bits target on 32 bits hosts
+     */ 
+    target_ulong t0, t1, t2;
+#endif
+    /* */
+    double ft0, ft1, ft2;
+
+    /* Those resources are used only in Qemu core */
+    CPU_COMMON
+
+    jmp_buf jmp_env;
+    int user_mode_only; /* user mode only simulation */
+    uint32_t hflags;
+    int halted;
+
+    int exception_index;
+    int error_code;
+    int interrupt_request;
+
+    uint32_t features;
+    uint32_t amask;
+    int implver;
+    pal_handler_t *pal_handler;
+};
+
+#include "cpu-all.h"
+
+enum {
+    FEATURE_ASN    = 0x00000001,
+    FEATURE_SPS    = 0x00000002,
+    FEATURE_VIRBND = 0x00000004,
+    FEATURE_TBCHK  = 0x00000008,
+};
+
+enum {
+    EXCP_RESET            = 0x0000,
+    EXCP_MCHK             = 0x0020,
+    EXCP_ARITH            = 0x0060,
+    EXCP_HW_INTERRUPT     = 0x00E0,
+    EXCP_DFAULT           = 0x01E0,
+    EXCP_DTB_MISS_PAL     = 0x09E0,
+    EXCP_ITB_MISS         = 0x03E0,
+    EXCP_ITB_ACV          = 0x07E0,
+    EXCP_DTB_MISS_NATIVE  = 0x08E0,
+    EXCP_UNALIGN          = 0x11E0,
+    EXCP_OPCDEC           = 0x13E0,
+    EXCP_FEN              = 0x17E0,
+    EXCP_CALL_PAL         = 0x2000,
+    EXCP_CALL_PALP        = 0x3000,
+    EXCP_CALL_PALE        = 0x4000,
+    /* Pseudo exception for console */
+    EXCP_CONSOLE_DISPATCH = 0x4001,
+    EXCP_CONSOLE_FIXUP    = 0x4002,
+};
+
+/* Arithmetic exception */
+enum {
+    EXCP_ARITH_OVERFLOW,
+};
+
+enum {
+    PALCODE_CALL = 0x00000000,
+    PALCODE_LD   = 0x01000000,
+    PALCODE_ST   = 0x02000000,
+    PALCODE_MFPR = 0x03000000,
+    PALCODE_MTPR = 0x04000000,
+    PALCODE_REI  = 0x05000000,
+    PALCODE_INIT = 0xF0000000,
+};
+
+enum {
+    IR_V0   = 0,
+    IR_T0   = 1,
+    IR_T1   = 2,
+    IR_T2   = 3,
+    IR_T3   = 4,
+    IR_T4   = 5,
+    IR_T5   = 6,
+    IR_T6   = 7,
+    IR_T7   = 8,
+    IR_S0   = 9,
+    IR_S1   = 10,
+    IR_S2   = 11,
+    IR_S3   = 12,
+    IR_S4   = 13,
+    IR_S5   = 14,
+    IR_S6   = 15,
+#define IR_FP IR_S6
+    IR_A0   = 16,
+    IR_A1   = 17,
+    IR_A2   = 18,
+    IR_A3   = 19,
+    IR_A4   = 20,
+    IR_A5   = 21,
+    IR_T8   = 22,
+    IR_T9   = 23,
+    IR_T10  = 24,
+    IR_T11  = 25,
+    IR_RA   = 26,
+    IR_T12  = 27,
+#define IR_PV IR_T12
+    IR_AT   = 28,
+    IR_GP   = 29,
+    IR_SP   = 30,
+    IR_ZERO = 31,
+};
+
+CPUAlphaState * cpu_alpha_init (void);
+int cpu_alpha_exec(CPUAlphaState *s);
+/* you can call this signal handler from your SIGBUS and SIGSEGV
+   signal handlers to inform the virtual CPU of exceptions. non zero
+   is returned if the signal was handled by the virtual CPU.  */
+int cpu_alpha_signal_handler(int host_signum, void *pinfo, 
+                             void *puc);
+int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
+int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
+void cpu_loop_exit (void);
+void pal_init (CPUState *env);
+void call_pal (CPUState *env, int palcode);
+
+#endif /* !defined (__CPU_ALPHA_H__) */

Added: trunk/src/host/qemu-neo1973/target-alpha/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,82 @@
+/*
+ *  Alpha emulation cpu run-time definitions for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined (__ALPHA_EXEC_H__)
+#define __ALPHA_EXEC_H__
+
+#include "config.h"
+
+#include "dyngen-exec.h"
+
+#define TARGET_LONG_BITS 64
+
+register struct CPUAlphaState *env asm(AREG0);
+
+#if TARGET_LONG_BITS > HOST_LONG_BITS
+
+/* no registers can be used */
+#define T0 (env->t0)
+#define T1 (env->t1)
+#define T2 (env->t2)
+
+#else
+
+register uint64_t T0 asm(AREG1);
+register uint64_t T1 asm(AREG2);
+register uint64_t T2 asm(AREG3);
+
+#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
+
+#define PARAM(n) ((uint64_t)PARAM##n)
+#define SPARAM(n) ((int32_t)PARAM##n)
+#define FT0 (env->ft0)
+#define FT1 (env->ft1)
+#define FT2 (env->ft2)
+#define FP_STATUS (env->fp_status)
+
+#if defined (DEBUG_OP)
+#define RETURN() __asm__ __volatile__("nop" : : : "memory");
+#else
+#define RETURN() __asm__ __volatile__("" : : : "memory");
+#endif
+
+#include "cpu.h"
+#include "exec-all.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
+int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
+                                int is_user, int is_softmmu);
+int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
+int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
+
+void do_interrupt (CPUState *env);
+
+#endif /* !defined (__ALPHA_EXEC_H__) */

Added: trunk/src/host/qemu-neo1973/target-alpha/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,454 @@
+/*
+ *  Alpha emulation cpu helpers for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+
+#if defined(CONFIG_USER_ONLY) 
+
+int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+                                int is_user, int is_softmmu)
+{
+    if (rw == 2)
+        env->exception_index = EXCP_ITB_MISS;
+    else
+        env->exception_index = EXCP_DFAULT;
+    env->ipr[IPR_EXC_ADDR] = address;
+    
+    return 1;
+}
+
+target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
+{
+    return addr;
+}
+
+void do_interrupt (CPUState *env)
+{
+    env->exception_index = -1;
+}
+
+#else
+
+target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
+{
+    return -1;
+}
+
+int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+                                int is_user, int is_softmmu)
+{
+    uint32_t opc;
+
+    if (rw == 2) {
+        /* Instruction translation buffer miss */
+        env->exception_index = EXCP_ITB_MISS;
+    } else {
+        if (env->ipr[IPR_EXC_ADDR] & 1)
+            env->exception_index = EXCP_DTB_MISS_PAL;
+        else
+            env->exception_index = EXCP_DTB_MISS_NATIVE;
+        opc = (ldl_code(env->pc) >> 21) << 4;
+        if (rw) {
+            opc |= 0x9;
+        } else {
+            opc |= 0x4;
+        }
+        env->ipr[IPR_MM_STAT] = opc;
+    }
+
+    return 1;
+}
+
+int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
+{
+    uint64_t hwpcb;
+    int ret = 0;
+
+    hwpcb = env->ipr[IPR_PCBB];
+    switch (iprn) {
+    case IPR_ASN:
+        if (env->features & FEATURE_ASN)
+            *valp = env->ipr[IPR_ASN];
+        else
+            *valp = 0;
+        break;
+    case IPR_ASTEN:
+        *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
+        break;
+    case IPR_ASTSR:
+        *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
+        break;
+    case IPR_DATFX:
+        /* Write only */
+        ret = -1;
+        break;
+    case IPR_ESP:
+        if (env->features & FEATURE_SPS)
+            *valp = env->ipr[IPR_ESP];
+        else
+            *valp = ldq_raw(hwpcb + 8);
+        break;
+    case IPR_FEN:
+        *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
+        break;
+    case IPR_IPIR:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_IPL:
+        *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
+        break;
+    case IPR_KSP:
+        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
+            ret = -1;
+        } else {
+            if (env->features & FEATURE_SPS)
+                *valp = env->ipr[IPR_KSP];
+            else
+                *valp = ldq_raw(hwpcb + 0);
+        }
+        break;
+    case IPR_MCES:
+        *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
+        break;
+    case IPR_PERFMON:
+        /* Implementation specific */
+        *valp = 0;
+        break;
+    case IPR_PCBB:
+        *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
+        break;
+    case IPR_PRBR:
+        *valp = env->ipr[IPR_PRBR];
+        break;
+    case IPR_PTBR:
+        *valp = env->ipr[IPR_PTBR];
+        break;
+    case IPR_SCBB:
+        *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
+        break;
+    case IPR_SIRR:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_SISR:
+        *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
+    case IPR_SSP:
+        if (env->features & FEATURE_SPS)
+            *valp = env->ipr[IPR_SSP];
+        else
+            *valp = ldq_raw(hwpcb + 16);
+        break;
+    case IPR_SYSPTBR:
+        if (env->features & FEATURE_VIRBND)
+            *valp = env->ipr[IPR_SYSPTBR];
+        else
+            ret = -1;
+        break;
+    case IPR_TBCHK:
+        if ((env->features & FEATURE_TBCHK)) {
+            /* XXX: TODO */
+            *valp = 0;
+            ret = -1;
+        } else {
+            ret = -1;
+        }
+        break;
+    case IPR_TBIA:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_TBIAP:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_TBIS:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_TBISD:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_TBISI:
+        /* Write-only */
+        ret = -1;
+        break;
+    case IPR_USP:
+        if (env->features & FEATURE_SPS)
+            *valp = env->ipr[IPR_USP];
+        else
+            *valp = ldq_raw(hwpcb + 24);
+        break;
+    case IPR_VIRBND:
+        if (env->features & FEATURE_VIRBND)
+            *valp = env->ipr[IPR_VIRBND];
+        else
+            ret = -1;
+        break;
+    case IPR_VPTB:
+        *valp = env->ipr[IPR_VPTB];
+        break;
+    case IPR_WHAMI:
+        *valp = env->ipr[IPR_WHAMI];
+        break;
+    default:
+        /* Invalid */
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
+{
+    uint64_t hwpcb, tmp64;
+    uint8_t tmp8;
+    int ret = 0;
+
+    hwpcb = env->ipr[IPR_PCBB];
+    switch (iprn) {
+    case IPR_ASN:
+        /* Read-only */
+        ret = -1;
+        break;
+    case IPR_ASTEN:
+        tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
+        *oldvalp = tmp8;
+        tmp8 &= val & 0xF;
+        tmp8 |= (val >> 4) & 0xF;
+        env->ipr[IPR_ASTEN] &= ~0xF;
+        env->ipr[IPR_ASTEN] |= tmp8;
+        ret = 1;
+        break;
+    case IPR_ASTSR:
+        tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
+        *oldvalp = tmp8;
+        tmp8 &= val & 0xF;
+        tmp8 |= (val >> 4) & 0xF;
+        env->ipr[IPR_ASTSR] &= ~0xF;
+        env->ipr[IPR_ASTSR] |= tmp8;
+        ret = 1;
+    case IPR_DATFX:
+        env->ipr[IPR_DATFX] &= ~0x1;
+        env->ipr[IPR_DATFX] |= val & 1;
+        tmp64 = ldq_raw(hwpcb + 56);
+        tmp64 &= ~0x8000000000000000ULL;
+        tmp64 |= (val & 1) << 63;
+        stq_raw(hwpcb + 56, tmp64);
+        break;
+    case IPR_ESP:
+        if (env->features & FEATURE_SPS)
+            env->ipr[IPR_ESP] = val;
+        else
+            stq_raw(hwpcb + 8, val);
+        break;
+    case IPR_FEN:
+        env->ipr[IPR_FEN] = val & 1;
+        tmp64 = ldq_raw(hwpcb + 56);
+        tmp64 &= ~1;
+        tmp64 |= val & 1;
+        stq_raw(hwpcb + 56, tmp64);
+        break;
+    case IPR_IPIR:
+        /* XXX: TODO: Send IRQ to CPU #ir[16] */
+        break;
+    case IPR_IPL:
+        *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
+        env->ipr[IPR_IPL] &= ~0x1F;
+        env->ipr[IPR_IPL] |= val & 0x1F;
+        /* XXX: may issue an interrupt or ASR _now_ */
+        ret = 1;
+        break;
+    case IPR_KSP:
+        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
+            ret = -1;
+        } else {
+            if (env->features & FEATURE_SPS)
+                env->ipr[IPR_KSP] = val;
+            else
+                stq_raw(hwpcb + 0, val);
+        }
+        break;
+    case IPR_MCES:
+        env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
+        env->ipr[IPR_MCES] |= val & 0x18;
+        break;
+    case IPR_PERFMON:
+        /* Implementation specific */
+        *oldvalp = 0;
+        ret = 1;
+        break;
+    case IPR_PCBB:
+        /* Read-only */
+        ret = -1;
+        break;
+    case IPR_PRBR:
+        env->ipr[IPR_PRBR] = val;
+        break;
+    case IPR_PTBR:
+        /* Read-only */
+        ret = -1;
+        break;
+    case IPR_SCBB:
+        env->ipr[IPR_SCBB] = (uint32_t)val;
+        break;
+    case IPR_SIRR:
+        if (val & 0xF) {
+            env->ipr[IPR_SISR] |= 1 << (val & 0xF);
+            /* XXX: request a software interrupt _now_ */
+        }
+        break;
+    case IPR_SISR:
+        /* Read-only */
+        ret = -1;
+        break;
+    case IPR_SSP:
+        if (env->features & FEATURE_SPS)
+            env->ipr[IPR_SSP] = val;
+        else
+            stq_raw(hwpcb + 16, val);
+        break;
+    case IPR_SYSPTBR:
+        if (env->features & FEATURE_VIRBND)
+            env->ipr[IPR_SYSPTBR] = val;
+        else
+            ret = -1;
+    case IPR_TBCHK:
+        /* Read-only */
+        ret = -1;
+        break;
+    case IPR_TBIA:
+        tlb_flush(env, 1);
+        break;
+    case IPR_TBIAP:
+        tlb_flush(env, 1);
+        break;
+    case IPR_TBIS:
+        tlb_flush_page(env, val);
+        break;
+    case IPR_TBISD:
+        tlb_flush_page(env, val);
+        break;
+    case IPR_TBISI:
+        tlb_flush_page(env, val);
+        break;
+    case IPR_USP:
+        if (env->features & FEATURE_SPS)
+            env->ipr[IPR_USP] = val;
+        else
+            stq_raw(hwpcb + 24, val);
+        break;
+    case IPR_VIRBND:
+        if (env->features & FEATURE_VIRBND)
+            env->ipr[IPR_VIRBND] = val;
+        else
+            ret = -1;
+        break;
+    case IPR_VPTB:
+        env->ipr[IPR_VPTB] = val;
+        break;
+    case IPR_WHAMI:
+        /* Read-only */
+        ret = -1;
+        break;
+    default:
+        /* Invalid */
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+void do_interrupt (CPUState *env)
+{
+    int excp;
+
+    env->ipr[IPR_EXC_ADDR] = env->pc | 1;
+    excp = env->exception_index;
+    env->exception_index = 0;
+    env->error_code = 0;
+    /* XXX: disable interrupts and memory mapping */
+    if (env->ipr[IPR_PAL_BASE] != -1ULL) {
+        /* We use native PALcode */
+        env->pc = env->ipr[IPR_PAL_BASE] + excp;
+    } else {
+        /* We use emulated PALcode */
+        call_pal(env);
+        /* Emulate REI */
+        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
+        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+        /* XXX: re-enable interrupts and memory mapping */
+    }
+}
+#endif
+
+void cpu_dump_state (CPUState *env, FILE *f, 
+                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                     int flags)
+{
+    static unsigned char *linux_reg_names[] = {
+        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
+        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
+        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
+        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
+    };
+    int i;
+
+    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
+                env->pc, env->ps);
+    for (i = 0; i < 31; i++) {
+        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
+                    linux_reg_names[i], env->ir[i]);
+        if ((i % 3) == 2)
+            cpu_fprintf(f, "\n");
+    }
+    cpu_fprintf(f, "\n");
+    for (i = 0; i < 31; i++) {
+        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
+                    *((uint64_t *)(&env->fir[i])));
+        if ((i % 3) == 2)
+            cpu_fprintf(f, "\n");
+    }
+    cpu_fprintf(f, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx,
+                *((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)),
+                *((uint64_t *)(&env->ft2)));
+    cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n",
+                ldq_raw(0x000000004007df60ULL),
+                (uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0]));
+}
+
+void cpu_dump_EA (target_ulong EA)
+{
+    FILE *f;
+
+    if (logfile)
+        f = logfile;
+    else
+        f = stdout;
+    fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
+}

Added: trunk/src/host/qemu-neo1973/target-alpha/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1103 @@
+/*
+ *  Alpha emulation cpu micro-operations for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define DEBUG_OP
+
+#include "config.h"
+#include "exec.h"
+
+#include "op_helper.h"
+
+#define REG 0
+#include "op_template.h"
+
+#define REG 1
+#include "op_template.h"
+
+#define REG 2
+#include "op_template.h"
+
+#define REG 3
+#include "op_template.h"
+
+#define REG 4
+#include "op_template.h"
+
+#define REG 5
+#include "op_template.h"
+
+#define REG 6
+#include "op_template.h"
+
+#define REG 7
+#include "op_template.h"
+
+#define REG 8
+#include "op_template.h"
+
+#define REG 9
+#include "op_template.h"
+
+#define REG 10
+#include "op_template.h"
+
+#define REG 11
+#include "op_template.h"
+
+#define REG 12
+#include "op_template.h"
+
+#define REG 13
+#include "op_template.h"
+
+#define REG 14
+#include "op_template.h"
+
+#define REG 15
+#include "op_template.h"
+
+#define REG 16
+#include "op_template.h"
+
+#define REG 17
+#include "op_template.h"
+
+#define REG 18
+#include "op_template.h"
+
+#define REG 19
+#include "op_template.h"
+
+#define REG 20
+#include "op_template.h"
+
+#define REG 21
+#include "op_template.h"
+
+#define REG 22
+#include "op_template.h"
+
+#define REG 23
+#include "op_template.h"
+
+#define REG 24
+#include "op_template.h"
+
+#define REG 25
+#include "op_template.h"
+
+#define REG 26
+#include "op_template.h"
+
+#define REG 27
+#include "op_template.h"
+
+#define REG 28
+#include "op_template.h"
+
+#define REG 29
+#include "op_template.h"
+
+#define REG 30
+#include "op_template.h"
+
+#define REG 31
+#include "op_template.h"
+
+/* Debug stuff */
+void OPPROTO op_no_op (void)
+{
+#if !defined (DEBUG_OP)
+    __asm__ __volatile__("nop" : : : "memory");
+#endif
+    RETURN();
+}
+
+void OPPROTO op_tb_flush (void)
+{
+    helper_tb_flush();
+    RETURN();
+}
+
+/* Load and stores */
+#define MEMSUFFIX _raw
+#include "op_mem.h"
+#if !defined(CONFIG_USER_ONLY)
+#define MEMSUFFIX _user
+#include "op_mem.h"
+#define MEMSUFFIX _kernel
+#include "op_mem.h"
+/* Those are used for supervisor, executive and pal modes */
+#define MEMSUFFIX _data
+#include "op_mem.h"
+#endif
+
+/* Special operation for load and store */
+void OPPROTO op_n7 (void)
+{
+    T0 &= ~(uint64_t)0x7;
+    RETURN();
+}
+
+/* Misc */
+void OPPROTO op_excp (void)
+{
+    helper_excp(PARAM(1), PARAM(2));
+    RETURN();
+}
+
+void OPPROTO op_load_amask (void)
+{
+    helper_amask();
+    RETURN();
+}
+
+void OPPROTO op_load_pcc (void)
+{
+    helper_load_pcc();
+    RETURN();
+}
+
+void OPPROTO op_load_implver (void)
+{
+    helper_load_implver();
+    RETURN();
+}
+
+void OPPROTO op_load_fpcr (void)
+{
+    helper_load_fpcr();
+    RETURN();
+}
+
+void OPPROTO op_store_fpcr (void)
+{
+    helper_store_fpcr();
+    RETURN();
+}
+
+void OPPROTO op_load_irf (void)
+{
+    helper_load_irf();
+    RETURN();
+}
+
+void OPPROTO op_set_irf (void)
+{
+    helper_set_irf();
+    RETURN();
+}
+
+void OPPROTO op_clear_irf (void)
+{
+    helper_clear_irf();
+    RETURN();
+}
+
+void OPPROTO op_exit_tb (void)
+{
+    EXIT_TB();
+}
+
+/* Arithmetic */
+void OPPROTO op_addq (void)
+{
+    T0 += T1;
+    RETURN();
+}
+
+void OPPROTO op_addqv (void)
+{
+    helper_addqv();
+    RETURN();
+}
+
+void OPPROTO op_addl (void)
+{
+    T0 = (int64_t)((int32_t)(T0 + T1));
+    RETURN();
+}
+
+void OPPROTO op_addlv (void)
+{
+    helper_addlv();
+    RETURN();
+}
+
+void OPPROTO op_subq (void)
+{
+    T0 -= T1;
+    RETURN();
+}
+
+void OPPROTO op_subqv (void)
+{
+    helper_subqv();
+    RETURN();
+}
+
+void OPPROTO op_subl (void)
+{
+    T0 = (int64_t)((int32_t)(T0 - T1));
+    RETURN();
+}
+
+void OPPROTO op_sublv (void)
+{
+    helper_sublv();
+    RETURN();
+}
+
+void OPPROTO op_s4 (void)
+{
+    T0 <<= 2;
+    RETURN();
+}
+
+void OPPROTO op_s8 (void)
+{
+    T0 <<= 3;
+    RETURN();
+}
+
+void OPPROTO op_mull (void)
+{
+    T0 = (int64_t)((int32_t)T0 * (int32_t)T1);
+    RETURN();
+}
+
+void OPPROTO op_mullv (void)
+{
+    helper_mullv();
+    RETURN();
+}
+
+void OPPROTO op_mulq (void)
+{
+    T0 *= T1;
+    RETURN();
+}
+
+void OPPROTO op_mulqv (void)
+{
+    helper_mulqv();
+    RETURN();
+}
+
+void OPPROTO op_umulh (void)
+{
+    helper_umulh();
+    RETURN();
+}
+
+/* Logical */
+void OPPROTO op_and (void)
+{
+    T0 &= T1;
+    RETURN();
+}
+
+void OPPROTO op_bic (void)
+{
+    T0 &= ~T1;
+    RETURN();
+}
+
+void OPPROTO op_bis (void)
+{
+    T0 |= T1;
+    RETURN();
+}
+
+void OPPROTO op_eqv (void)
+{
+    T0 ^= ~T1;
+    RETURN();
+}
+
+void OPPROTO op_ornot (void)
+{
+    T0 |= ~T1;
+    RETURN();
+}
+
+void OPPROTO op_xor (void)
+{
+    T0 ^= T1;
+    RETURN();
+}
+
+void OPPROTO op_sll (void)
+{
+    T0 <<= T1;
+    RETURN();
+}
+
+void OPPROTO op_srl (void)
+{
+    T0 >>= T1;
+    RETURN();
+}
+
+void OPPROTO op_sra (void)
+{
+    T0 = (int64_t)T0 >> T1;
+    RETURN();
+}
+
+void OPPROTO op_sextb (void)
+{
+    T0 = (int64_t)((int8_t)T0);
+    RETURN();
+}
+
+void OPPROTO op_sextw (void)
+{
+    T0 = (int64_t)((int16_t)T0);
+    RETURN();
+
+}
+
+void OPPROTO op_ctpop (void)
+{
+    helper_ctpop();
+    RETURN();
+}
+
+void OPPROTO op_ctlz (void)
+{
+    helper_ctlz();
+    RETURN();
+}
+
+void OPPROTO op_cttz (void)
+{
+    helper_cttz();
+    RETURN();
+}
+
+void OPPROTO op_mskbl (void)
+{
+    helper_mskbl();
+    RETURN();
+}
+
+void OPPROTO op_extbl (void)
+{
+    helper_extbl();
+    RETURN();
+}
+
+void OPPROTO op_insbl (void)
+{
+    helper_insbl();
+    RETURN();
+}
+
+void OPPROTO op_mskwl (void)
+{
+    helper_mskwl();
+    RETURN();
+}
+
+void OPPROTO op_extwl (void)
+{
+    helper_extwl();
+    RETURN();
+}
+
+void OPPROTO op_inswl (void)
+{
+    helper_inswl();
+    RETURN();
+}
+
+void OPPROTO op_mskll (void)
+{
+    helper_mskll();
+    RETURN();
+}
+
+void OPPROTO op_extll (void)
+{
+    helper_extll();
+    RETURN();
+}
+
+void OPPROTO op_insll (void)
+{
+    helper_insll();
+    RETURN();
+}
+
+void OPPROTO op_zap (void)
+{
+    helper_zap();
+    RETURN();
+}
+
+void OPPROTO op_zapnot (void)
+{
+    helper_zapnot();
+    RETURN();
+}
+
+void OPPROTO op_mskql (void)
+{
+    helper_mskql();
+    RETURN();
+}
+
+void OPPROTO op_extql (void)
+{
+    helper_extql();
+    RETURN();
+}
+
+void OPPROTO op_insql (void)
+{
+    helper_insql();
+    RETURN();
+}
+
+void OPPROTO op_mskwh (void)
+{
+    helper_mskwh();
+    RETURN();
+}
+
+void OPPROTO op_inswh (void)
+{
+    helper_inswh();
+    RETURN();
+}
+
+void OPPROTO op_extwh (void)
+{
+    helper_extwh();
+    RETURN();
+}
+
+void OPPROTO op_msklh (void)
+{
+    helper_msklh();
+    RETURN();
+}
+
+void OPPROTO op_inslh (void)
+{
+    helper_inslh();
+    RETURN();
+}
+
+void OPPROTO op_extlh (void)
+{
+    helper_extlh();
+    RETURN();
+}
+
+void OPPROTO op_mskqh (void)
+{
+    helper_mskqh();
+    RETURN();
+}
+
+void OPPROTO op_insqh (void)
+{
+    helper_insqh();
+    RETURN();
+}
+
+void OPPROTO op_extqh (void)
+{
+    helper_extqh();
+    RETURN();
+}
+
+/* Tests */
+void OPPROTO op_cmpult (void)
+{
+    if (T0 < T1)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpule (void)
+{
+    if (T0 <= T1)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpeq (void)
+{
+    if (T0 == T1)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmplt (void)
+{
+    if ((int64_t)T0 < (int64_t)T1)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmple (void)
+{
+    if ((int64_t)T0 <= (int64_t)T1)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpbge (void)
+{
+    helper_cmpbge();
+    RETURN();
+}
+
+void OPPROTO op_cmpeqz (void)
+{
+    if (T0 == 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpnez (void)
+{
+    if (T0 != 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpltz (void)
+{
+    if ((int64_t)T0 < 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmplez (void)
+{
+    if ((int64_t)T0 <= 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpgtz (void)
+{
+    if ((int64_t)T0 > 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmpgez (void)
+{
+    if ((int64_t)T0 >= 0)
+        T0 = 1;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_cmplbs (void)
+{
+    T0 &= 1;
+    RETURN();
+}
+
+void OPPROTO op_cmplbc (void)
+{
+    T0 = (~T0) & 1;
+    RETURN();
+}
+
+/* Branches */
+void OPPROTO op_branch (void)
+{
+    env->pc = T0 & ~3;
+    RETURN();
+}
+
+void OPPROTO op_addq1 (void)
+{
+    T1 += T0;
+    RETURN();
+}
+
+#if 0 // Qemu does not know how to do this...
+void OPPROTO op_bcond (void)
+{
+    if (T0)
+        env->pc = T1 & ~3;
+    else
+        env->pc = PARAM(1);
+    RETURN();
+}
+#else
+void OPPROTO op_bcond (void)
+{
+    if (T0)
+        env->pc = T1 & ~3;
+    else
+        env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
+    RETURN();
+}
+#endif
+
+#if 0 // Qemu does not know how to do this...
+void OPPROTO op_update_pc (void)
+{
+    env->pc = PARAM(1);
+    RETURN();
+}
+#else
+void OPPROTO op_update_pc (void)
+{
+    env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
+    RETURN();
+}
+#endif
+
+/* Optimization for 32 bits hosts architectures */
+void OPPROTO op_update_pc32 (void)
+{
+    env->pc = (uint64_t)PARAM(1);
+    RETURN();
+}
+
+/* IEEE floating point arithmetic */
+/* S floating (single) */
+void OPPROTO op_adds (void)
+{
+    FT0 = float32_add(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_subs (void)
+{
+    FT0 = float32_sub(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_muls (void)
+{
+    FT0 = float32_mul(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_divs (void)
+{
+    FT0 = float32_div(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_sqrts (void)
+{
+    helper_sqrts();
+    RETURN();
+}
+
+void OPPROTO op_cpys (void)
+{
+    helper_cpys();
+    RETURN();
+}
+
+void OPPROTO op_cpysn (void)
+{
+    helper_cpysn();
+    RETURN();
+}
+
+void OPPROTO op_cpyse (void)
+{
+    helper_cpyse();
+    RETURN();
+}
+
+void OPPROTO op_itofs (void)
+{
+    helper_itofs();
+    RETURN();
+}
+
+void OPPROTO op_ftois (void)
+{
+    helper_ftois();
+    RETURN();
+}
+
+/* T floating (double) */
+void OPPROTO op_addt (void)
+{
+    FT0 = float64_add(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_subt (void)
+{
+    FT0 = float64_sub(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_mult (void)
+{
+    FT0 = float64_mul(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_divt (void)
+{
+    FT0 = float64_div(FT0, FT1, &FP_STATUS);
+    RETURN();
+}
+
+void OPPROTO op_sqrtt (void)
+{
+    helper_sqrtt();
+    RETURN();
+}
+
+void OPPROTO op_cmptun (void)
+{
+    helper_cmptun();
+    RETURN();
+}
+
+void OPPROTO op_cmpteq (void)
+{
+    helper_cmpteq();
+    RETURN();
+}
+
+void OPPROTO op_cmptle (void)
+{
+    helper_cmptle();
+    RETURN();
+}
+
+void OPPROTO op_cmptlt (void)
+{
+    helper_cmptlt();
+    RETURN();
+}
+
+void OPPROTO op_itoft (void)
+{
+    helper_itoft();
+    RETURN();
+}
+
+void OPPROTO op_ftoit (void)
+{
+    helper_ftoit();
+    RETURN();
+}
+
+/* VAX floating point arithmetic */
+/* F floating */
+void OPPROTO op_addf (void)
+{
+    helper_addf();
+    RETURN();
+}
+
+void OPPROTO op_subf (void)
+{
+    helper_subf();
+    RETURN();
+}
+
+void OPPROTO op_mulf (void)
+{
+    helper_mulf();
+    RETURN();
+}
+
+void OPPROTO op_divf (void)
+{
+    helper_divf();
+    RETURN();
+}
+
+void OPPROTO op_sqrtf (void)
+{
+    helper_sqrtf();
+    RETURN();
+}
+
+void OPPROTO op_cmpfeq (void)
+{
+    helper_cmpfeq();
+    RETURN();
+}
+
+void OPPROTO op_cmpfne (void)
+{
+    helper_cmpfne();
+    RETURN();
+}
+
+void OPPROTO op_cmpflt (void)
+{
+    helper_cmpflt();
+    RETURN();
+}
+
+void OPPROTO op_cmpfle (void)
+{
+    helper_cmpfle();
+    RETURN();
+}
+
+void OPPROTO op_cmpfgt (void)
+{
+    helper_cmpfgt();
+    RETURN();
+}
+
+void OPPROTO op_cmpfge (void)
+{
+    helper_cmpfge();
+    RETURN();
+}
+
+void OPPROTO op_itoff (void)
+{
+    helper_itoff();
+    RETURN();
+}
+
+/* G floating */
+void OPPROTO op_addg (void)
+{
+    helper_addg();
+    RETURN();
+}
+
+void OPPROTO op_subg (void)
+{
+    helper_subg();
+    RETURN();
+}
+
+void OPPROTO op_mulg (void)
+{
+    helper_mulg();
+    RETURN();
+}
+
+void OPPROTO op_divg (void)
+{
+    helper_divg();
+    RETURN();
+}
+
+void OPPROTO op_sqrtg (void)
+{
+    helper_sqrtg();
+    RETURN();
+}
+
+void OPPROTO op_cmpgeq (void)
+{
+    helper_cmpgeq();
+    RETURN();
+}
+
+void OPPROTO op_cmpglt (void)
+{
+    helper_cmpglt();
+    RETURN();
+}
+
+void OPPROTO op_cmpgle (void)
+{
+    helper_cmpgle();
+    RETURN();
+}
+
+/* Floating point format conversion */
+void OPPROTO op_cvtst (void)
+{
+    FT0 = (float)FT0;
+    RETURN();
+}
+
+void OPPROTO op_cvtqs (void)
+{
+    helper_cvtqs();
+    RETURN();
+}
+
+void OPPROTO op_cvtts (void)
+{
+    FT0 = (float)FT0;
+    RETURN();
+}
+
+void OPPROTO op_cvttq (void)
+{
+    helper_cvttq();
+    RETURN();
+}
+
+void OPPROTO op_cvtqt (void)
+{
+    helper_cvtqt();
+    RETURN();
+}
+
+void OPPROTO op_cvtqf (void)
+{
+    helper_cvtqf();
+    RETURN();
+}
+
+void OPPROTO op_cvtgf (void)
+{
+    helper_cvtgf();
+    RETURN();
+}
+
+void OPPROTO op_cvtgd (void)
+{
+    helper_cvtgd();
+    RETURN();
+}
+
+void OPPROTO op_cvtgq (void)
+{
+    helper_cvtgq();
+    RETURN();
+}
+
+void OPPROTO op_cvtqg (void)
+{
+    helper_cvtqg();
+    RETURN();
+}
+
+void OPPROTO op_cvtdg (void)
+{
+    helper_cvtdg();
+    RETURN();
+}
+
+void OPPROTO op_cvtlq (void)
+{
+    helper_cvtlq();
+    RETURN();
+}
+
+void OPPROTO op_cvtql (void)
+{
+    helper_cvtql();
+    RETURN();
+}
+
+void OPPROTO op_cvtqlv (void)
+{
+    helper_cvtqlv();
+    RETURN();
+}
+
+void OPPROTO op_cvtqlsv (void)
+{
+    helper_cvtqlsv();
+    RETURN();
+}
+
+/* PALcode support special instructions */
+#if !defined (CONFIG_USER_ONLY)
+void OPPROTO op_hw_rei (void)
+{
+    env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
+    env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+    /* XXX: re-enable interrupts and memory mapping */
+    RETURN();
+}
+
+void OPPROTO op_hw_ret (void)
+{
+    env->pc = T0 & ~3;
+    env->ipr[IPR_EXC_ADDR] = T0 & 1;
+    /* XXX: re-enable interrupts and memory mapping */
+    RETURN();
+}
+
+void OPPROTO op_mfpr (void)
+{
+    helper_mfpr(PARAM(1));
+    RETURN();
+}
+
+void OPPROTO op_mtpr (void)
+{
+    helper_mtpr(PARAM(1));
+    RETURN();
+}
+
+void OPPROTO op_set_alt_mode (void)
+{
+    env->saved_mode = env->ps & 0xC;
+    env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
+    RETURN();
+}
+
+void OPPROTO op_restore_mode (void)
+{
+    env->ps = (env->ps & ~0xC) | env->saved_mode;
+    RETURN();
+}
+
+void OPPROTO op_ld_phys_to_virt (void)
+{
+    helper_ld_phys_to_virt();
+    RETURN();
+}
+
+void OPPROTO op_st_phys_to_virt (void)
+{
+    helper_st_phys_to_virt();
+    RETURN();
+}
+#endif /* !defined (CONFIG_USER_ONLY) */

Added: trunk/src/host/qemu-neo1973/target-alpha/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,1255 @@
+/*
+ *  Alpha emulation cpu micro-operations helpers for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "exec.h"
+#include "softfloat.h"
+
+#include "op_helper.h"
+
+#define MEMSUFFIX _raw
+#include "op_helper_mem.h"
+
+#if !defined(CONFIG_USER_ONLY)
+#define MEMSUFFIX _user
+#include "op_helper_mem.h"
+
+#define MEMSUFFIX _kernel
+#include "op_helper_mem.h"
+
+/* Those are used for supervisor and executive modes */
+#define MEMSUFFIX _data
+#include "op_helper_mem.h"
+#endif
+
+void helper_tb_flush (void)
+{
+    tlb_flush(env, 1);
+}
+
+void cpu_dump_EA (target_ulong EA);
+void helper_print_mem_EA (target_ulong EA)
+{
+    cpu_dump_EA(EA);
+}
+
+/*****************************************************************************/
+/* Exceptions processing helpers */
+void helper_excp (uint32_t excp, uint32_t error)
+{
+    env->exception_index = excp;
+    env->error_code = error;
+    cpu_loop_exit();
+}
+
+void helper_amask (void)
+{
+    switch (env->implver) {
+    case IMPLVER_2106x:
+        /* EV4, EV45, LCA, LCA45 & EV5 */
+        break;
+    case IMPLVER_21164:
+    case IMPLVER_21264:
+    case IMPLVER_21364:
+        T0 &= ~env->amask;
+        break;
+    }
+}
+
+void helper_load_pcc (void)
+{
+    /* XXX: TODO */
+    T0 = 0;
+}
+
+void helper_load_implver (void)
+{
+    T0 = env->implver;
+}
+
+void helper_load_fpcr (void)
+{
+    T0 = 0;
+#ifdef CONFIG_SOFTFLOAT
+    T0 |= env->fp_status.float_exception_flags << 52;
+    if (env->fp_status.float_exception_flags)
+        T0 |= 1ULL << 63;
+    env->ipr[IPR_EXC_SUM] &= ~0x3E:
+    env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
+#endif
+    switch (env->fp_status.float_rounding_mode) {
+    case float_round_nearest_even:
+        T0 |= 2ULL << 58;
+        break;
+    case float_round_down:
+        T0 |= 1ULL << 58;
+        break;
+    case float_round_up:
+        T0 |= 3ULL << 58;
+        break;
+    case float_round_to_zero:
+        break;
+    }
+}
+
+void helper_store_fpcr (void)
+{
+#ifdef CONFIG_SOFTFLOAT
+    set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
+#endif
+    switch ((T0 >> 58) & 3) {
+    case 0:
+        set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
+        break;
+    case 1:
+        set_float_rounding_mode(float_round_down, &FP_STATUS);
+        break;
+    case 2:
+        set_float_rounding_mode(float_round_nearest_even, &FP_STATUS);
+        break;
+    case 3:
+        set_float_rounding_mode(float_round_up, &FP_STATUS);
+        break;
+    }
+}
+
+void helper_load_irf (void)
+{
+    /* XXX: TODO */
+    T0 = 0;
+}
+
+void helper_set_irf (void)
+{
+    /* XXX: TODO */
+}
+
+void helper_clear_irf (void)
+{
+    /* XXX: TODO */
+}
+
+void helper_addqv (void)
+{
+    T2 = T0;
+    T0 += T1;
+    if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+}
+
+void helper_addlv (void)
+{
+    T2 = T0;
+    T0 = (uint32_t)(T0 + T1);
+    if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+}
+
+void helper_subqv (void)
+{
+    T2 = T0;
+    T0 -= T1;
+    if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+}
+
+void helper_sublv (void)
+{
+    T2 = T0;
+    T0 = (uint32_t)(T0 - T1);
+    if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+}
+
+void helper_mullv (void)
+{
+    int64_t res = (int64_t)T0 * (int64_t)T1;
+
+    if (unlikely((int32_t)res != res)) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+    T0 = (int64_t)((int32_t)res);
+}
+
+void helper_mulqv ()
+{
+    uint64_t res, tmp0, tmp1;
+
+    res = (T0 >> 32) * (T1 >> 32);
+    tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
+        ((T0 >> 32) * (T1 & 0xFFFFFFFF));
+    tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
+    tmp0 += tmp1 >> 32;
+    res += tmp0 >> 32;
+    T0 *= T1;
+    if (unlikely(res != 0)) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+}
+
+void helper_umulh (void)
+{
+    uint64_t tmp0, tmp1;
+
+    tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
+        ((T0 >> 32) * (T1 & 0xFFFFFFFF));
+    tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
+    tmp0 += tmp1 >> 32;
+    T0 = (T0 >> 32) * (T0 >> 32);
+    T0 += tmp0 >> 32;
+}
+
+void helper_ctpop (void)
+{
+    int n;
+
+    for (n = 0; T0 != 0; n++)
+        T0 = T0 ^ (T0 - 1);
+    T0 = n;
+}
+
+void helper_ctlz (void)
+{
+    uint32_t op32;
+    int n;
+
+    n = 0;
+    if (!(T0 & 0xFFFFFFFF00000000ULL)) {
+        n += 32;
+        T0 <<= 32;
+    }
+    /* Make it easier for 32 bits hosts */
+    op32 = T0 >> 32;
+    if (!(op32 & 0xFFFF0000UL)) {
+        n += 16;
+        op32 <<= 16;
+    }
+    if (!(op32 & 0xFF000000UL)) {
+        n += 8;
+        op32 <<= 8;
+    }
+    if (!(op32 & 0xF0000000UL)) {
+        n += 4;
+        op32 <<= 4;
+    }
+    if (!(op32 & 0xC0000000UL)) {
+        n += 2;
+        op32 <<= 2;
+    }
+    if (!(op32 & 0x80000000UL)) {
+        n++;
+        op32 <<= 1;
+    }
+    if (!(op32 & 0x80000000UL)) {
+        n++;
+    }
+    T0 = n;
+}
+
+void helper_cttz (void)
+{
+    uint32_t op32;
+    int n;
+
+    n = 0;
+    if (!(T0 & 0x00000000FFFFFFFFULL)) {
+        n += 32;
+        T0 >>= 32;
+    }
+    /* Make it easier for 32 bits hosts */
+    op32 = T0;
+    if (!(op32 & 0x0000FFFFUL)) {
+        n += 16;
+        op32 >>= 16;
+    }
+    if (!(op32 & 0x000000FFUL)) {
+        n += 8;
+        op32 >>= 8;
+    }
+    if (!(op32 & 0x0000000FUL)) {
+        n += 4;
+        op32 >>= 4;
+    }
+    if (!(op32 & 0x00000003UL)) {
+        n += 2;
+        op32 >>= 2;
+    }
+    if (!(op32 & 0x00000001UL)) {
+        n++;
+        op32 >>= 1;
+    }
+    if (!(op32 & 0x00000001UL)) {
+        n++;
+    }
+    T0 = n;
+}
+
+static inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
+{
+    uint64_t mask;
+
+    mask = 0;
+    mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
+    mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
+    mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
+    mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
+    mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
+    mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
+    mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
+    mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
+
+    return op & ~mask;
+}
+
+void helper_mskbl (void)
+{
+    T0 = byte_zap(T0, 0x01 << (T1 & 7));
+}
+
+void helper_extbl (void)
+{
+    T0 >>= (T1 & 7) * 8;
+    T0 = byte_zap(T0, 0xFE);
+}
+
+void helper_insbl (void)
+{
+    T0 <<= (T1 & 7) * 8;
+    T0 = byte_zap(T0, ~(0x01 << (T1 & 7)));
+}
+
+void helper_mskwl (void)
+{
+    T0 = byte_zap(T0, 0x03 << (T1 & 7));
+}
+
+void helper_extwl (void)
+{
+    T0 >>= (T1 & 7) * 8;
+    T0 = byte_zap(T0, 0xFC);
+}
+
+void helper_inswl (void)
+{
+    T0 <<= (T1 & 7) * 8;
+    T0 = byte_zap(T0, ~(0x03 << (T1 & 7)));
+}
+
+void helper_mskll (void)
+{
+    T0 = byte_zap(T0, 0x0F << (T1 & 7));
+}
+
+void helper_extll (void)
+{
+    T0 >>= (T1 & 7) * 8;
+    T0 = byte_zap(T0, 0xF0);
+}
+
+void helper_insll (void)
+{
+    T0 <<= (T1 & 7) * 8;
+    T0 = byte_zap(T0, ~(0x0F << (T1 & 7)));
+}
+
+void helper_zap (void)
+{
+    T0 = byte_zap(T0, T1);
+}
+
+void helper_zapnot (void)
+{
+    T0 = byte_zap(T0, ~T1);
+}
+
+void helper_mskql (void)
+{
+    T0 = byte_zap(T0, 0xFF << (T1 & 7));
+}
+
+void helper_extql (void)
+{
+    T0 >>= (T1 & 7) * 8;
+    T0 = byte_zap(T0, 0x00);
+}
+
+void helper_insql (void)
+{
+    T0 <<= (T1 & 7) * 8;
+    T0 = byte_zap(T0, ~(0xFF << (T1 & 7)));
+}
+
+void helper_mskwh (void)
+{
+    T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8);
+}
+
+void helper_inswh (void)
+{
+    T0 >>= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8));
+}
+
+void helper_extwh (void)
+{
+    T0 <<= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, ~0x07);
+}
+
+void helper_msklh (void)
+{
+    T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8);
+}
+
+void helper_inslh (void)
+{
+    T0 >>= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8));
+}
+
+void helper_extlh (void)
+{
+    T0 <<= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, ~0x0F);
+}
+
+void helper_mskqh (void)
+{
+    T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8);
+}
+
+void helper_insqh (void)
+{
+    T0 >>= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8));
+}
+
+void helper_extqh (void)
+{
+    T0 <<= 64 - ((T1 & 7) * 8);
+    T0 = byte_zap(T0, 0x00);
+}
+
+void helper_cmpbge (void)
+{
+    uint8_t opa, opb, res;
+    int i;
+
+    res = 0;
+    for (i = 0; i < 7; i++) {
+        opa = T0 >> (i * 8);
+        opb = T1 >> (i * 8);
+        if (opa >= opb)
+            res |= 1 << i;
+    }
+    T0 = res;
+}
+
+void helper_cmov_fir (int freg)
+{
+    if (FT0 != 0)
+        env->fir[freg] = FT1;
+}
+
+void helper_sqrts (void)
+{
+    FT0 = float32_sqrt(FT0, &FP_STATUS);
+}
+
+void helper_cpys (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p, q, r;
+
+    p.d = FT0;
+    q.d = FT1;
+    r.i = p.i & 0x8000000000000000ULL;
+    r.i |= q.i & ~0x8000000000000000ULL;
+    FT0 = r.d;
+}
+
+void helper_cpysn (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p, q, r;
+
+    p.d = FT0;
+    q.d = FT1;
+    r.i = (~p.i) & 0x8000000000000000ULL;
+    r.i |= q.i & ~0x8000000000000000ULL;
+    FT0 = r.d;
+}
+
+void helper_cpyse (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p, q, r;
+
+    p.d = FT0;
+    q.d = FT1;
+    r.i = p.i & 0xFFF0000000000000ULL;
+    r.i |= q.i & ~0xFFF0000000000000ULL;
+    FT0 = r.d;
+}
+
+void helper_itofs (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.d = FT0;
+    FT0 = int64_to_float32(p.i, &FP_STATUS);
+}
+
+void helper_ftois (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = float32_to_int64(FT0, &FP_STATUS);
+    FT0 = p.d;
+}
+
+void helper_sqrtt (void)
+{
+    FT0 = float64_sqrt(FT0, &FP_STATUS);
+}
+
+void helper_cmptun (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = 0;
+    if (float64_is_nan(FT0) || float64_is_nan(FT1))
+        p.i = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cmpteq (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = 0;
+    if (float64_eq(FT0, FT1, &FP_STATUS))
+        p.i = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cmptle (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = 0;
+    if (float64_le(FT0, FT1, &FP_STATUS))
+        p.i = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cmptlt (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = 0;
+    if (float64_lt(FT0, FT1, &FP_STATUS))
+        p.i = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_itoft (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.d = FT0;
+    FT0 = int64_to_float64(p.i, &FP_STATUS);
+}
+
+void helper_ftoit (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = float64_to_int64(FT0, &FP_STATUS);
+    FT0 = p.d;
+}
+
+static int vaxf_is_valid (float ff)
+{
+    union {
+        float f;
+        uint32_t i;
+    } p;
+    uint32_t exp, mant;
+
+    p.f = ff;
+    exp = (p.i >> 23) & 0xFF;
+    mant = p.i & 0x007FFFFF;
+    if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
+        /* Reserved operands / Dirty zero */
+        return 0;
+    }
+
+    return 1;
+}
+
+static float vaxf_to_ieee32 (float ff)
+{
+    union {
+        float f;
+        uint32_t i;
+    } p;
+    uint32_t exp;
+
+    p.f = ff;
+    exp = (p.i >> 23) & 0xFF;
+    if (exp < 3) {
+        /* Underflow */
+        p.f = 0.0;
+    } else {
+        p.f *= 0.25;
+    }
+
+    return p.f;
+}
+
+static float ieee32_to_vaxf (float fi)
+{
+    union {
+        float f;
+        uint32_t i;
+    } p;
+    uint32_t exp, mant;
+
+    p.f = fi;
+    exp = (p.i >> 23) & 0xFF;
+    mant = p.i & 0x007FFFFF;
+    if (exp == 255) {
+        /* NaN or infinity */
+        p.i = 1;
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            p.i = 0;
+        } else {
+            /* Denormalized */
+            p.f *= 2.0;
+        }
+    } else {
+        if (exp >= 253) {
+            /* Overflow */
+            p.i = 1;
+        } else {
+            p.f *= 4.0;
+        }
+    }
+
+    return p.f;
+}
+
+void helper_addf (void)
+{
+    float ft0, ft1, ft2;
+
+    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxf_to_ieee32(FT0);
+    ft1 = vaxf_to_ieee32(FT1);
+    ft2 = float32_add(ft0, ft1, &FP_STATUS);
+    FT0 = ieee32_to_vaxf(ft2);
+}
+
+void helper_subf (void)
+{
+    float ft0, ft1, ft2;
+
+    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxf_to_ieee32(FT0);
+    ft1 = vaxf_to_ieee32(FT1);
+    ft2 = float32_sub(ft0, ft1, &FP_STATUS);
+    FT0 = ieee32_to_vaxf(ft2);
+}
+
+void helper_mulf (void)
+{
+    float ft0, ft1, ft2;
+
+    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxf_to_ieee32(FT0);
+    ft1 = vaxf_to_ieee32(FT1);
+    ft2 = float32_mul(ft0, ft1, &FP_STATUS);
+    FT0 = ieee32_to_vaxf(ft2);
+}
+
+void helper_divf (void)
+{
+    float ft0, ft1, ft2;
+
+    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxf_to_ieee32(FT0);
+    ft1 = vaxf_to_ieee32(FT1);
+    ft2 = float32_div(ft0, ft1, &FP_STATUS);
+    FT0 = ieee32_to_vaxf(ft2);
+}
+
+void helper_sqrtf (void)
+{
+    float ft0, ft1;
+
+    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxf_to_ieee32(FT0);
+    ft1 = float32_sqrt(ft0, &FP_STATUS);
+    FT0 = ieee32_to_vaxf(ft1);
+}
+
+void helper_itoff (void)
+{
+    /* XXX: TODO */
+}
+
+static int vaxg_is_valid (double ff)
+{
+    union {
+        double f;
+        uint64_t i;
+    } p;
+    uint64_t exp, mant;
+
+    p.f = ff;
+    exp = (p.i >> 52) & 0x7FF;
+    mant = p.i & 0x000FFFFFFFFFFFFFULL;
+    if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
+        /* Reserved operands / Dirty zero */
+        return 0;
+    }
+
+    return 1;
+}
+
+static double vaxg_to_ieee64 (double fg)
+{
+    union {
+        double f;
+        uint64_t i;
+    } p;
+    uint32_t exp;
+
+    p.f = fg;
+    exp = (p.i >> 52) & 0x7FF;
+    if (exp < 3) {
+        /* Underflow */
+        p.f = 0.0;
+    } else {
+        p.f *= 0.25;
+    }
+
+    return p.f;
+}
+
+static double ieee64_to_vaxg (double fi)
+{
+    union {
+        double f;
+        uint64_t i;
+    } p;
+    uint64_t mant;
+    uint32_t exp;
+
+    p.f = fi;
+    exp = (p.i >> 52) & 0x7FF;
+    mant = p.i & 0x000FFFFFFFFFFFFFULL;
+    if (exp == 255) {
+        /* NaN or infinity */
+        p.i = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            p.i = 0;
+        } else {
+            /* Denormalized */
+            p.f *= 2.0;
+        }
+    } else {
+        if (exp >= 2045) {
+            /* Overflow */
+            p.i = 1; /* VAX dirty zero */
+        } else {
+            p.f *= 4.0;
+        }
+    }
+
+    return p.f;
+}
+
+void helper_addg (void)
+{
+    double ft0, ft1, ft2;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    ft2 = float64_add(ft0, ft1, &FP_STATUS);
+    FT0 = ieee64_to_vaxg(ft2);
+}
+
+void helper_subg (void)
+{
+    double ft0, ft1, ft2;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    ft2 = float64_sub(ft0, ft1, &FP_STATUS);
+    FT0 = ieee64_to_vaxg(ft2);
+}
+
+void helper_mulg (void)
+{
+    double ft0, ft1, ft2;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    ft2 = float64_mul(ft0, ft1, &FP_STATUS);
+    FT0 = ieee64_to_vaxg(ft2);
+}
+
+void helper_divg (void)
+{
+    double ft0, ft1, ft2;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    ft2 = float64_div(ft0, ft1, &FP_STATUS);
+    FT0 = ieee64_to_vaxg(ft2);
+}
+
+void helper_sqrtg (void)
+{
+    double ft0, ft1;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = float64_sqrt(ft0, &FP_STATUS);
+    FT0 = ieee64_to_vaxg(ft1);
+}
+
+void helper_cmpgeq (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+    double ft0, ft1;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    p.u = 0;
+    if (float64_eq(ft0, ft1, &FP_STATUS))
+        p.u = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cmpglt (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+    double ft0, ft1;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    p.u = 0;
+    if (float64_lt(ft0, ft1, &FP_STATUS))
+        p.u = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cmpgle (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+    double ft0, ft1;
+
+    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
+        /* XXX: TODO */
+    }
+    ft0 = vaxg_to_ieee64(FT0);
+    ft1 = vaxg_to_ieee64(FT1);
+    p.u = 0;
+    if (float64_le(ft0, ft1, &FP_STATUS))
+        p.u = 0x4000000000000000ULL;
+    FT0 = p.d;
+}
+
+void helper_cvtqs (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.d = FT0;
+    FT0 = (float)p.u;
+}
+
+void helper_cvttq (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.u = FT0;
+    FT0 = p.d;
+}
+
+void helper_cvtqt (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.d = FT0;
+    FT0 = p.u;
+}
+
+void helper_cvtqf (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.d = FT0;
+    FT0 = ieee32_to_vaxf(p.u);
+}
+
+void helper_cvtgf (void)
+{
+    double ft0;
+
+    ft0 = vaxg_to_ieee64(FT0);
+    FT0 = ieee32_to_vaxf(ft0);
+}
+
+void helper_cvtgd (void)
+{
+    /* XXX: TODO */
+}
+
+void helper_cvtgq (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.u = vaxg_to_ieee64(FT0);
+    FT0 = p.d;
+}
+
+void helper_cvtqg (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p;
+
+    p.d = FT0;
+    FT0 = ieee64_to_vaxg(p.u);
+}
+
+void helper_cvtdg (void)
+{
+    /* XXX: TODO */
+}
+
+void helper_cvtlq (void)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p, q;
+
+    p.d = FT0;
+    q.u = (p.u >> 29) & 0x3FFFFFFF;
+    q.u |= (p.u >> 32);
+    q.u = (int64_t)((int32_t)q.u);
+    FT0 = q.d;
+}
+
+static inline void __helper_cvtql (int s, int v)
+{
+    union {
+        double d;
+        uint64_t u;
+    } p, q;
+
+    p.d = FT0;
+    q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
+    q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
+    FT0 = q.d;
+    if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+    if (s) {
+        /* TODO */
+    }
+}
+
+void helper_cvtql (void)
+{
+    __helper_cvtql(0, 0);
+}
+
+void helper_cvtqlv (void)
+{
+    __helper_cvtql(0, 1);
+}
+
+void helper_cvtqlsv (void)
+{
+    __helper_cvtql(1, 1);
+}
+
+void helper_cmpfeq (void)
+{
+    if (float64_eq(FT0, FT1, &FP_STATUS))
+        T0 = 1;
+    else
+        T0 = 0;
+}
+
+void helper_cmpfne (void)
+{
+    if (float64_eq(FT0, FT1, &FP_STATUS))
+        T0 = 0;
+    else
+        T0 = 1;
+}
+
+void helper_cmpflt (void)
+{
+    if (float64_lt(FT0, FT1, &FP_STATUS))
+        T0 = 1;
+    else
+        T0 = 0;
+}
+
+void helper_cmpfle (void)
+{
+    if (float64_lt(FT0, FT1, &FP_STATUS))
+        T0 = 1;
+    else
+        T0 = 0;
+}
+
+void helper_cmpfgt (void)
+{
+    if (float64_le(FT0, FT1, &FP_STATUS))
+        T0 = 0;
+    else
+        T0 = 1;
+}
+
+void helper_cmpfge (void)
+{
+    if (float64_lt(FT0, FT1, &FP_STATUS))
+        T0 = 0;
+    else
+        T0 = 1;
+}
+
+#if !defined (CONFIG_USER_ONLY)
+void helper_mfpr (int iprn)
+{
+    uint64_t val;
+
+    if (cpu_alpha_mfpr(env, iprn, &val) == 0)
+        T0 = val;
+}
+
+void helper_mtpr (int iprn)
+{
+    cpu_alpha_mtpr(env, iprn, T0, NULL);
+}
+#endif
+
+/*****************************************************************************/
+/* Softmmu support */
+#if !defined (CONFIG_USER_ONLY)
+
+#define GETPC() (__builtin_return_address(0))
+
+/* XXX: the two following helpers are pure hacks.
+ *      Hopefully, we emulate the PALcode, then we should never see
+ *      HW_LD / HW_ST instructions.
+ */
+void helper_ld_phys_to_virt (void)
+{
+    uint64_t tlb_addr, physaddr;
+    int index, is_user;
+    void *retaddr;
+
+    is_user = (env->ps >> 3) & 3;
+    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ redo:
+    tlb_addr = env->tlb_table[is_user][index].addr_read;
+    if ((T0 & TARGET_PAGE_MASK) ==
+        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+        physaddr = T0 + env->tlb_table[is_user][index].addend;
+    } else {
+        /* the page is not in the TLB : fill it */
+        retaddr = GETPC();
+        tlb_fill(T0, 0, is_user, retaddr);
+        goto redo;
+    }
+    T0 = physaddr;
+}
+
+void helper_st_phys_to_virt (void)
+{
+    uint64_t tlb_addr, physaddr;
+    int index, is_user;
+    void *retaddr;
+
+    is_user = (env->ps >> 3) & 3;
+    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ redo:
+    tlb_addr = env->tlb_table[is_user][index].addr_write;
+    if ((T0 & TARGET_PAGE_MASK) ==
+        (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
+        physaddr = T0 + env->tlb_table[is_user][index].addend;
+    } else {
+        /* the page is not in the TLB : fill it */
+        retaddr = GETPC();
+        tlb_fill(T0, 1, is_user, retaddr);
+        goto redo;
+    }
+    T0 = physaddr;
+}
+
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+   NULL, it means that the function was called in C code (i.e. not
+   from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
+{
+    TranslationBlock *tb;
+    CPUState *saved_env;
+    target_phys_addr_t pc;
+    int ret;
+
+    /* XXX: hack to restore env in all cases, even if not called from
+       generated code */
+    saved_env = env;
+    env = cpu_single_env;
+    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, is_user, 1);
+    if (!likely(ret == 0)) {
+        if (likely(retaddr)) {
+            /* now we have a real cpu fault */
+            pc = (target_phys_addr_t)retaddr;
+            tb = tb_find_pc(pc);
+            if (likely(tb)) {
+                /* the PC is inside the translated code. It means that we have
+                   a virtual CPU fault */
+                cpu_restore_state(tb, env, pc, NULL);
+            }
+        }
+        /* Exception index and error code are already set */
+        cpu_loop_exit();
+    }
+    env = saved_env;
+}
+
+#endif

Added: trunk/src/host/qemu-neo1973/target-alpha/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_helper.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_helper.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,141 @@
+/*
+ *  Alpha emulation cpu micro-operations helpers definitions for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void helper_call_pal (uint32_t palcode);
+void helper_excp (uint32_t excp, uint32_t error);
+void helper_amask (void);
+void helper_load_pcc (void);
+void helper_load_implver (void);
+void helper_load_fpcr (void);
+void helper_store_fpcr (void);
+void helper_load_irf (void);
+void helper_set_irf (void);
+void helper_clear_irf (void);
+void helper_addqv (void);
+void helper_addlv (void);
+void helper_subqv (void);
+void helper_sublv (void);
+void helper_mullv (void);
+void helper_mulqv (void);
+void helper_umulh (void);
+void helper_ctpop (void);
+void helper_ctlz (void);
+void helper_cttz (void);
+void helper_mskbl (void);
+void helper_extbl (void);
+void helper_insbl (void);
+void helper_mskwl (void);
+void helper_extwl (void);
+void helper_inswl (void);
+void helper_mskll (void);
+void helper_extll (void);
+void helper_insll (void);
+void helper_zap (void);
+void helper_zapnot (void);
+void helper_mskql (void);
+void helper_extql (void);
+void helper_insql (void);
+void helper_mskwh (void);
+void helper_inswh (void);
+void helper_extwh (void);
+void helper_msklh (void);
+void helper_inslh (void);
+void helper_extlh (void);
+void helper_mskqh (void);
+void helper_insqh (void);
+void helper_extqh (void);
+void helper_cmpbge (void);
+void helper_cmov_fir (int freg);
+
+double helper_ldff_raw (target_ulong ea);
+void helper_stff_raw (target_ulong ea, double op);
+double helper_ldfg_raw (target_ulong ea);
+void helper_stfg_raw (target_ulong ea, double op);
+#if !defined(CONFIG_USER_ONLY)
+double helper_ldff_user (target_ulong ea);
+void helper_stff_user (target_ulong ea, double op);
+double helper_ldff_kernel (target_ulong ea);
+void helper_stff_kernel (target_ulong ea, double op);
+double helper_ldff_data (target_ulong ea);
+void helper_stff_data (target_ulong ea, double op);
+double helper_ldfg_user (target_ulong ea);
+void helper_stfg_user (target_ulong ea, double op);
+double helper_ldfg_kernel (target_ulong ea);
+void helper_stfg_kernel (target_ulong ea, double op);
+double helper_ldfg_data (target_ulong ea);
+void helper_stfg_data (target_ulong ea, double op);
+#endif
+
+void helper_sqrts (void);
+void helper_cpys (void);
+void helper_cpysn (void);
+void helper_cpyse (void);
+void helper_itofs (void);
+void helper_ftois (void);
+
+void helper_sqrtt (void);
+void helper_cmptun (void);
+void helper_cmpteq (void);
+void helper_cmptle (void);
+void helper_cmptlt (void);
+void helper_itoft (void);
+void helper_ftoit (void);
+
+void helper_addf (void);
+void helper_subf (void);
+void helper_mulf (void);
+void helper_divf (void);
+void helper_sqrtf (void);
+void helper_cmpfeq (void);
+void helper_cmpfne (void);
+void helper_cmpflt (void);
+void helper_cmpfle (void);
+void helper_cmpfgt (void);
+void helper_cmpfge (void);
+void helper_itoff (void);
+
+void helper_addg (void);
+void helper_subg (void);
+void helper_mulg (void);
+void helper_divg (void);
+void helper_sqrtg (void);
+void helper_cmpgeq (void);
+void helper_cmpglt (void);
+void helper_cmpgle (void);
+
+void helper_cvtqs (void);
+void helper_cvttq (void);
+void helper_cvtqt (void);
+void helper_cvtqf (void);
+void helper_cvtgf (void);
+void helper_cvtgd (void);
+void helper_cvtgq (void);
+void helper_cvtqg (void);
+void helper_cvtdg (void);
+void helper_cvtlq (void);
+void helper_cvtql (void);
+void helper_cvtqlv (void);
+void helper_cvtqlsv (void);
+
+void helper_mfpr (int iprn);
+void helper_mtpr (int iprn);
+void helper_ld_phys_to_virt (void);
+void helper_st_phys_to_virt (void);
+void helper_tb_flush (void);

Added: trunk/src/host/qemu-neo1973/target-alpha/op_helper_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_helper_mem.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_helper_mem.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,40 @@
+/*
+ *  Alpha emulation cpu micro-operations helpers for memory accesses for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* XXX: TODO */
+double glue(helper_ldff, MEMSUFFIX) (target_ulong ea)
+{
+    return 0;
+}
+
+void glue(helper_stff, MEMSUFFIX) (target_ulong ea, double op)
+{
+}
+
+double glue(helper_ldfg, MEMSUFFIX) (target_ulong ea)
+{
+    return 0;
+}
+
+void glue(helper_stfg, MEMSUFFIX) (target_ulong ea, double op)
+{
+}
+
+#undef MEMSUFFIX

Added: trunk/src/host/qemu-neo1973/target-alpha/op_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_mem.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_mem.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,125 @@
+/*
+ *  Alpha emulation cpu micro-operations for memory accesses for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define DEBUG_MEM_ACCESSES
+#if defined (DEBUG_MEM_ACCESSES)
+void helper_print_mem_EA (target_ulong EA);
+#define print_mem_EA(EA) do { helper_print_mem_EA(EA); } while (0)
+#else
+#define print_mem_EA(EA) do { } while (0)
+#endif
+
+static inline uint32_t glue(ldl_l, MEMSUFFIX) (target_ulong EA)
+{
+    env->lock = EA;
+
+    return glue(ldl, MEMSUFFIX)(EA);
+}
+
+static inline uint32_t glue(ldq_l, MEMSUFFIX) (target_ulong EA)
+{
+    env->lock = EA;
+
+    return glue(ldq, MEMSUFFIX)(EA);
+}
+
+static inline void glue(stl_c, MEMSUFFIX) (target_ulong EA, uint32_t data)
+{
+    if (EA == env->lock) {
+        glue(stl, MEMSUFFIX)(EA, data);
+        T0 = 0;
+    } else {
+        T0 = 1;
+    }
+    env->lock = -1;
+}
+
+static inline void glue(stq_c, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    if (EA == env->lock) {
+        glue(stq, MEMSUFFIX)(EA, data);
+        T0 = 0;
+    } else {
+        T0 = 1;
+    }
+    env->lock = -1;
+}
+
+#define ALPHA_LD_OP(name, op)                                                 \
+void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void)                        \
+{                                                                             \
+    print_mem_EA(T0);                                                         \
+    T1 = glue(op, MEMSUFFIX)(T0);                                             \
+    RETURN();                                                                 \
+}
+
+#define ALPHA_ST_OP(name, op)                                                 \
+void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void)                        \
+{                                                                             \
+    print_mem_EA(T0);                                                         \
+    glue(op, MEMSUFFIX)(T0, T1);                                              \
+    RETURN();                                                                 \
+}
+
+ALPHA_LD_OP(bu, ldub);
+ALPHA_ST_OP(b, stb);
+ALPHA_LD_OP(wu, lduw);
+ALPHA_ST_OP(w, stw);
+ALPHA_LD_OP(l, ldl);
+ALPHA_ST_OP(l, stl);
+ALPHA_LD_OP(q, ldq);
+ALPHA_ST_OP(q, stq);
+
+ALPHA_LD_OP(q_u, ldq);
+ALPHA_ST_OP(q_u, stq);
+
+ALPHA_LD_OP(l_l, ldl_l);
+ALPHA_LD_OP(q_l, ldq_l);
+ALPHA_ST_OP(l_c, stl_c);
+ALPHA_ST_OP(q_c, stq_c);
+
+#define ALPHA_LDF_OP(name, op)                                                \
+void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void)                        \
+{                                                                             \
+    print_mem_EA(T0);                                                         \
+    FT1 = glue(op, MEMSUFFIX)(T0);                                            \
+    RETURN();                                                                 \
+}
+
+#define ALPHA_STF_OP(name, op)                                                \
+void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void)                        \
+{                                                                             \
+    print_mem_EA(T0);                                                         \
+    glue(op, MEMSUFFIX)(T0, FT1);                                             \
+    RETURN();                                                                 \
+}
+
+ALPHA_LDF_OP(t, ldfq);
+ALPHA_STF_OP(t, stfq);
+ALPHA_LDF_OP(s, ldfl);
+ALPHA_STF_OP(s, stfl);
+
+/* VAX floating point */
+ALPHA_LDF_OP(f, helper_ldff);
+ALPHA_STF_OP(f, helper_stff);
+ALPHA_LDF_OP(g, helper_ldfg);
+ALPHA_STF_OP(g, helper_stfg);
+
+#undef MEMSUFFIX

Added: trunk/src/host/qemu-neo1973/target-alpha/op_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/op_template.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/op_template.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,167 @@
+/*
+ *  Alpha emulation cpu micro-operations templates for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Optimized constant loads */
+#if REG < 3
+void OPPROTO glue(op_reset_T, REG) (void)
+{
+    glue(T, REG) = 0;
+    RETURN();
+}
+
+void OPPROTO glue(op_reset_FT, REG) (void)
+{
+    glue(FT, REG) = 0;
+    RETURN();
+}
+
+/* XXX: This can be great on most RISC machines */
+#if !defined(__i386__) && !defined(__x86_64__)
+void OPPROTO glue(op_set_s16_T, REG) (void)
+{
+    glue(T, REG) = (int16_t)PARAM(1);
+    RETURN();
+}
+
+void OPPROTO glue(op_set_u16_T, REG) (void)
+{
+    glue(T, REG) = (uint16_t)PARAM(1);
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_set_s32_T, REG) (void)
+{
+    glue(T, REG) = (int32_t)PARAM(1);
+    RETURN();
+}
+
+void OPPROTO glue(op_set_u32_T, REG) (void)
+{
+    glue(T, REG) = (uint32_t)PARAM(1);
+    RETURN();
+}
+
+#if 0 // Qemu does not know how to do this...
+void OPPROTO glue(op_set_64_T, REG) (void)
+{
+    glue(T, REG) = (int64_t)PARAM(1);
+    RETURN();
+}
+#else
+void OPPROTO glue(op_set_64_T, REG) (void)
+{
+    glue(T, REG) = ((int64_t)PARAM(1) << 32) | (int64_t)PARAM(2);
+    RETURN();
+}
+#endif
+
+#endif /* REG < 3 */
+
+/* Fixed-point register moves */
+#if REG < 31
+void OPPROTO glue(op_load_T0_ir, REG) (void)
+{
+    T0 = env->ir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_load_T1_ir, REG) (void)
+{
+    T1 = env->ir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_load_T2_ir, REG) (void)
+{
+    T2 = env->ir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_store_T0_ir, REG) (void)
+{
+    env->ir[REG] = T0;
+    RETURN();
+}
+
+void OPPROTO glue(op_store_T1_ir, REG) (void)
+{
+    env->ir[REG] = T1;
+    RETURN();
+}
+
+void OPPROTO glue(op_store_T2_ir, REG) (void)
+{
+    env->ir[REG] = T2;
+    RETURN();
+}
+
+void OPPROTO glue(op_cmov_ir, REG) (void)
+{
+    if (T0)
+        env->ir[REG] = T1;
+    RETURN();
+}
+
+/* floating point registers moves */
+void OPPROTO glue(op_load_FT0_fir, REG) (void)
+{
+    FT0 = env->fir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_load_FT1_fir, REG) (void)
+{
+    FT1 = env->fir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_load_FT2_fir, REG) (void)
+{
+    FT2 = env->fir[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_store_FT0_fir, REG) (void)
+{
+    env->fir[REG] = FT0;
+    RETURN();
+}
+
+void OPPROTO glue(op_store_FT1_fir, REG) (void)
+{
+    env->fir[REG] = FT1;
+    RETURN();
+}
+
+void OPPROTO glue(op_store_FT2_fir, REG) (void)
+{
+    env->fir[REG] = FT2;
+    RETURN();
+}
+
+void OPPROTO glue(op_cmov_fir, REG) (void)
+{
+    helper_cmov_fir(REG);
+    RETURN();
+}
+#endif /* REG < 31 */
+
+#undef REG

Added: trunk/src/host/qemu-neo1973/target-alpha/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-alpha/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-alpha/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,2118 @@
+/*
+ *  Alpha emulation cpu translation for qemu.
+ * 
+ *  Copyright (c) 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+
+#define DO_SINGLE_STEP
+#define GENERATE_NOP
+#define ALPHA_DEBUG_DISAS
+#define DO_TB_FLUSH
+
+typedef struct DisasContext DisasContext;
+struct DisasContext {
+    uint64_t pc;
+    int mem_idx;
+#if !defined (CONFIG_USER_ONLY)
+    int pal_mode;
+#endif
+    uint32_t amask;
+};
+
+#ifdef USE_DIRECT_JUMP
+#define TBPARAM(x)
+#else
+#define TBPARAM(x) (long)(x)
+#endif
+
+enum {
+#define DEF(s, n, copy_size) INDEX_op_ ## s,
+#include "opc.h"
+#undef DEF
+    NB_OPS,
+};
+
+static uint16_t *gen_opc_ptr;
+static uint32_t *gen_opparam_ptr;
+
+#include "gen-op.h"
+
+static inline void gen_op_nop (void)
+{
+#if defined(GENERATE_NOP)
+    gen_op_no_op();
+#endif
+}
+
+#define GEN32(func, NAME) \
+static GenOpFunc *NAME ## _table [32] = {                                     \
+NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
+NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
+NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
+NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
+NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
+NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
+NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
+NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
+};                                                                            \
+static inline void func(int n)                                                \
+{                                                                             \
+    NAME ## _table[n]();                                                      \
+}
+
+/* IR moves */
+/* Special hacks for ir31 */
+#define gen_op_load_T0_ir31 gen_op_reset_T0
+#define gen_op_load_T1_ir31 gen_op_reset_T1
+#define gen_op_load_T2_ir31 gen_op_reset_T2
+#define gen_op_store_T0_ir31 gen_op_nop
+#define gen_op_store_T1_ir31 gen_op_nop
+#define gen_op_store_T2_ir31 gen_op_nop
+#define gen_op_cmov_ir31 gen_op_nop
+GEN32(gen_op_load_T0_ir, gen_op_load_T0_ir);
+GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir);
+GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir);
+GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir);
+GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir);
+GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir);
+GEN32(gen_op_cmov_ir, gen_op_cmov_ir);
+
+static inline void gen_load_ir (DisasContext *ctx, int irn, int Tn)
+{
+    switch (Tn) {
+    case 0:
+        gen_op_load_T0_ir(irn);
+        break;
+    case 1:
+        gen_op_load_T1_ir(irn);
+        break;
+    case 2:
+        gen_op_load_T2_ir(irn);
+        break;
+    }
+}
+
+static inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
+{
+    switch (Tn) {
+    case 0:
+        gen_op_store_T0_ir(irn);
+        break;
+    case 1:
+        gen_op_store_T1_ir(irn);
+        break;
+    case 2:
+        gen_op_store_T2_ir(irn);
+        break;
+    }
+}
+
+/* FIR moves */
+/* Special hacks for fir31 */
+#define gen_op_load_FT0_fir31 gen_op_reset_FT0
+#define gen_op_load_FT1_fir31 gen_op_reset_FT1
+#define gen_op_load_FT2_fir31 gen_op_reset_FT2
+#define gen_op_store_FT0_fir31 gen_op_nop
+#define gen_op_store_FT1_fir31 gen_op_nop
+#define gen_op_store_FT2_fir31 gen_op_nop
+#define gen_op_cmov_fir31 gen_op_nop
+GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);
+GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);
+GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);
+GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);
+GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);
+GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);
+GEN32(gen_op_cmov_fir, gen_op_cmov_fir);
+
+static inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
+{
+    switch (Tn) {
+    case 0:
+        gen_op_load_FT0_fir(firn);
+        break;
+    case 1:
+        gen_op_load_FT1_fir(firn);
+        break;
+    case 2:
+        gen_op_load_FT2_fir(firn);
+        break;
+    }
+}
+
+static inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
+{
+    switch (Tn) {
+    case 0:
+        gen_op_store_FT0_fir(firn);
+        break;
+    case 1:
+        gen_op_store_FT1_fir(firn);
+        break;
+    case 2:
+        gen_op_store_FT2_fir(firn);
+        break;
+    }
+}
+
+/* Memory moves */
+#if defined(CONFIG_USER_ONLY)
+#define OP_LD_TABLE(width)                                                    \
+static GenOpFunc *gen_op_ld##width[] = {                                      \
+    &gen_op_ld##width##_raw,                                                  \
+}
+#define OP_ST_TABLE(width)                                                    \
+static GenOpFunc *gen_op_st##width[] = {                                      \
+    &gen_op_st##width##_raw,                                                  \
+}
+#else
+#define OP_LD_TABLE(width)                                                    \
+static GenOpFunc *gen_op_ld##width[] = {                                      \
+    &gen_op_ld##width##_kernel,                                               \
+    &gen_op_ld##width##_user, /* executive */                                 \
+    &gen_op_ld##width##_data, /* supervisor */                                \
+    &gen_op_ld##width##_data, /* user */                                      \
+}
+#define OP_ST_TABLE(width)                                                    \
+static GenOpFunc *gen_op_st##width[] = {                                      \
+    &gen_op_st##width##_kernel,                                               \
+    &gen_op_st##width##_user, /* executive */                                 \
+    &gen_op_st##width##_data, /* supervisor */                                \
+    &gen_op_st##width##_data, /* user */                                      \
+}
+#endif
+
+#define GEN_LD(width)                                                         \
+OP_LD_TABLE(width);                                                           \
+static void gen_ld##width (DisasContext *ctx)                                 \
+{                                                                             \
+    (*gen_op_ld##width[ctx->mem_idx])();                                      \
+}
+
+#define GEN_ST(width)                                                         \
+OP_ST_TABLE(width);                                                           \
+static void gen_st##width (DisasContext *ctx)                                 \
+{                                                                             \
+    (*gen_op_st##width[ctx->mem_idx])();                                      \
+}
+
+GEN_LD(bu);
+GEN_ST(b);
+GEN_LD(wu);
+GEN_ST(w);
+GEN_LD(l);
+GEN_ST(l);
+GEN_LD(q);
+GEN_ST(q);
+GEN_LD(q_u);
+GEN_ST(q_u);
+GEN_LD(l_l);
+GEN_ST(l_c);
+GEN_LD(q_l);
+GEN_ST(q_c);
+
+GEN_LD(f);
+GEN_ST(f);
+GEN_LD(g);
+GEN_ST(g);
+GEN_LD(s);
+GEN_ST(s);
+GEN_LD(t);
+GEN_ST(t);
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline void gen_op_set_s16_T0 (int16_t imm)
+{
+    gen_op_set_s32_T0((int32_t)imm);
+}
+
+static inline void gen_op_set_s16_T1 (int16_t imm)
+{
+    gen_op_set_s32_T1((int32_t)imm);
+}
+
+static inline void gen_op_set_u16_T0 (uint16_t imm)
+{
+    gen_op_set_s32_T0((uint32_t)imm);
+}
+
+static inline void gen_op_set_u16_T1 (uint16_t imm)
+{
+    gen_op_set_s32_T1((uint32_t)imm);
+}
+#endif
+
+static inline void gen_set_sT0 (DisasContext *ctx, int64_t imm)
+{
+    int32_t imm32;
+    int16_t imm16;
+
+    imm32 = imm;
+    if (imm32 == imm) {
+        imm16 = imm;
+        if (imm16 == imm) {
+            if (imm == 0) {
+                gen_op_reset_T0();
+            } else {
+                gen_op_set_s16_T0(imm16);
+            }
+        } else {
+            gen_op_set_s32_T0(imm32);
+        }
+    } else {
+#if 0 // Qemu does not know how to do this...
+        gen_op_set_64_T0(imm);
+#else
+        gen_op_set_64_T0(imm >> 32, imm);
+#endif
+    }
+}
+
+static inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
+{
+    int32_t imm32;
+    int16_t imm16;
+
+    imm32 = imm;
+    if (imm32 == imm) {
+        imm16 = imm;
+        if (imm16 == imm) {
+            if (imm == 0) {
+                gen_op_reset_T1();
+            } else {
+                gen_op_set_s16_T1(imm16);
+            }
+        } else {
+            gen_op_set_s32_T1(imm32);
+        }
+    } else {
+#if 0 // Qemu does not know how to do this...
+        gen_op_set_64_T1(imm);
+#else
+        gen_op_set_64_T1(imm >> 32, imm);
+#endif
+    }
+}
+
+static inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
+{
+    if (!(imm >> 32)) {
+        if ((!imm >> 16)) {
+            if (imm == 0)
+                gen_op_reset_T0();
+            else
+                gen_op_set_u16_T0(imm);
+        } else {
+            gen_op_set_u32_T0(imm);
+        }
+    } else {
+#if 0 // Qemu does not know how to do this...
+        gen_op_set_64_T0(imm);
+#else
+        gen_op_set_64_T0(imm >> 32, imm);
+#endif
+    }
+}
+
+static inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
+{
+    if (!(imm >> 32)) {
+        if ((!imm >> 16)) {
+            if (imm == 0)
+                gen_op_reset_T1();
+            else
+                gen_op_set_u16_T1(imm);
+        } else {
+            gen_op_set_u32_T1(imm);
+        }
+    } else {
+#if 0 // Qemu does not know how to do this...
+        gen_op_set_64_T1(imm);
+#else
+        gen_op_set_64_T1(imm >> 32, imm);
+#endif
+    }
+}
+
+static inline void gen_update_pc (DisasContext *ctx)
+{
+    if (!(ctx->pc >> 32)) {
+        gen_op_update_pc32(ctx->pc);
+    } else {
+#if 0 // Qemu does not know how to do this...
+        gen_op_update_pc(ctx->pc);
+#else
+        gen_op_update_pc(ctx->pc >> 32, ctx->pc);
+#endif
+    }
+}
+
+static inline void _gen_op_bcond (DisasContext *ctx)
+{
+#if 0 // Qemu does not know how to do this...
+    gen_op_bcond(ctx->pc);
+#else
+    gen_op_bcond(ctx->pc >> 32, ctx->pc);
+#endif
+}
+
+static inline void gen_excp (DisasContext *ctx, int exception, int error_code)
+{
+    gen_update_pc(ctx);
+    gen_op_excp(exception, error_code);
+}
+
+static inline void gen_invalid (DisasContext *ctx)
+{
+    gen_excp(ctx, EXCP_OPCDEC, 0);
+}
+
+static void gen_load_mem (DisasContext *ctx,
+                          void (*gen_load_op)(DisasContext *ctx),
+                          int ra, int rb, int32_t disp16, int clear)
+{
+    if (ra == 31 && disp16 == 0) {
+        /* UNOP */
+        gen_op_nop();
+    } else {
+        gen_load_ir(ctx, rb, 0);
+        if (disp16 != 0) {
+            gen_set_sT1(ctx, disp16);
+            gen_op_addq();
+        }
+        if (clear)
+            gen_op_n7();
+        (*gen_load_op)(ctx);
+        gen_store_ir(ctx, ra, 1);
+    }
+}
+
+static void gen_store_mem (DisasContext *ctx,
+                           void (*gen_store_op)(DisasContext *ctx),
+                           int ra, int rb, int32_t disp16, int clear)
+{
+    gen_load_ir(ctx, rb, 0);
+    if (disp16 != 0) {
+        gen_set_sT1(ctx, disp16);
+        gen_op_addq();
+    }
+    if (clear)
+        gen_op_n7();
+    gen_load_ir(ctx, ra, 1);
+    (*gen_store_op)(ctx);
+}
+
+static void gen_load_fmem (DisasContext *ctx,
+                           void (*gen_load_fop)(DisasContext *ctx),
+                          int ra, int rb, int32_t disp16)
+{
+    gen_load_ir(ctx, rb, 0);
+    if (disp16 != 0) {
+        gen_set_sT1(ctx, disp16);
+        gen_op_addq();
+    }
+    (*gen_load_fop)(ctx);
+    gen_store_fir(ctx, ra, 1);
+}
+
+static void gen_store_fmem (DisasContext *ctx,
+                            void (*gen_store_fop)(DisasContext *ctx),
+                            int ra, int rb, int32_t disp16)
+{
+    gen_load_ir(ctx, rb, 0);
+    if (disp16 != 0) {
+        gen_set_sT1(ctx, disp16);
+        gen_op_addq();
+    }
+    gen_load_fir(ctx, ra, 1);
+    (*gen_store_fop)(ctx);
+}
+
+static void gen_bcond (DisasContext *ctx, void (*gen_test_op)(void),
+                       int ra, int32_t disp16)
+{
+    if (disp16 != 0) {
+        gen_set_uT0(ctx, ctx->pc);
+        gen_set_sT1(ctx, disp16 << 2);
+        gen_op_addq1();
+    } else {
+        gen_set_uT1(ctx, ctx->pc);
+    }
+    gen_load_ir(ctx, ra, 0);
+    (*gen_test_op)();
+    _gen_op_bcond(ctx);
+}
+
+static void gen_fbcond (DisasContext *ctx, void (*gen_test_op)(void),
+                        int ra, int32_t disp16)
+{
+    if (disp16 != 0) {
+        gen_set_uT0(ctx, ctx->pc);
+        gen_set_sT1(ctx, disp16 << 2);
+        gen_op_addq1();
+    } else {
+        gen_set_uT1(ctx, ctx->pc);
+    }
+    gen_load_fir(ctx, ra, 0);
+    (*gen_test_op)();
+    _gen_op_bcond(ctx);
+}
+
+static void gen_arith2 (DisasContext *ctx, void (*gen_arith_op)(void),
+                        int rb, int rc, int islit, int8_t lit)
+{
+    if (islit)
+        gen_set_sT0(ctx, lit);
+    else
+        gen_load_ir(ctx, rb, 0);
+    (*gen_arith_op)();
+    gen_store_ir(ctx, rc, 0);
+}
+
+static void gen_arith3 (DisasContext *ctx, void (*gen_arith_op)(void),
+                        int ra, int rb, int rc, int islit, int8_t lit)
+{
+    gen_load_ir(ctx, ra, 0);
+    if (islit)
+        gen_set_sT1(ctx, lit);
+    else
+        gen_load_ir(ctx, rb, 1);
+    (*gen_arith_op)();
+    gen_store_ir(ctx, rc, 0);
+}
+
+static void gen_cmov (DisasContext *ctx, void (*gen_test_op)(void),
+                      int ra, int rb, int rc, int islit, int8_t lit)
+{
+    gen_load_ir(ctx, ra, 1);
+    if (islit)
+        gen_set_sT0(ctx, lit);
+    else
+        gen_load_ir(ctx, rb, 0);
+    (*gen_test_op)();
+    gen_op_cmov_ir(rc);
+}
+
+static void gen_farith2 (DisasContext *ctx, void (*gen_arith_fop)(void),
+                         int rb, int rc)
+{
+    gen_load_fir(ctx, rb, 0);
+    (*gen_arith_fop)();
+    gen_store_fir(ctx, rc, 0);
+}
+
+static void gen_farith3 (DisasContext *ctx, void (*gen_arith_fop)(void),
+                         int ra, int rb, int rc)
+{
+    gen_load_fir(ctx, ra, 0);
+    gen_load_fir(ctx, rb, 1);
+    (*gen_arith_fop)();
+    gen_store_fir(ctx, rc, 0);
+}
+
+static void gen_fcmov (DisasContext *ctx, void (*gen_test_fop)(void),
+                       int ra, int rb, int rc)
+{
+    gen_load_fir(ctx, ra, 0);
+    gen_load_fir(ctx, rb, 1);
+    (*gen_test_fop)();
+    gen_op_cmov_fir(rc);
+}
+
+static void gen_fti (DisasContext *ctx, void (*gen_move_fop)(void),
+                     int ra, int rc)
+{
+    gen_load_fir(ctx, rc, 0);
+    (*gen_move_fop)();
+    gen_store_ir(ctx, ra, 0);
+}
+
+static void gen_itf (DisasContext *ctx, void (*gen_move_fop)(void),
+                     int ra, int rc)
+{
+    gen_load_ir(ctx, ra, 0);
+    (*gen_move_fop)();
+    gen_store_fir(ctx, rc, 0);
+}
+
+static void gen_s4addl (void)
+{
+    gen_op_s4();
+    gen_op_addl();
+} 
+
+static void gen_s4subl (void)
+{
+    gen_op_s4();
+    gen_op_subl();
+} 
+
+static void gen_s8addl (void)
+{
+    gen_op_s8();
+    gen_op_addl();
+} 
+
+static void gen_s8subl (void)
+{
+    gen_op_s8();
+    gen_op_subl();
+} 
+
+static void gen_s4addq (void)
+{
+    gen_op_s4();
+    gen_op_addq();
+} 
+
+static void gen_s4subq (void)
+{
+    gen_op_s4();
+    gen_op_subq();
+} 
+
+static void gen_s8addq (void)
+{
+    gen_op_s8();
+    gen_op_addq();
+} 
+
+static void gen_s8subq (void)
+{
+    gen_op_s8();
+    gen_op_subq();
+} 
+
+static void gen_amask (void)
+{
+    gen_op_load_amask();
+    gen_op_bic();
+}
+
+static int translate_one (DisasContext *ctx, uint32_t insn)
+{
+    uint32_t palcode;
+    int32_t disp21, disp16, disp12;
+    uint16_t fn11, fn16;
+    uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
+    int8_t lit;
+    int ret;
+
+    /* Decode all instruction fields */
+    opc = insn >> 26;
+    ra = (insn >> 21) & 0x1F;
+    rb = (insn >> 16) & 0x1F;
+    rc = insn & 0x1F;
+    sbz = (insn >> 13) & 0x07;
+    islit = (insn >> 12) & 1;
+    lit = (insn >> 13) & 0xFF;
+    palcode = insn & 0x03FFFFFF;
+    disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
+    disp16 = (int16_t)(insn & 0x0000FFFF);
+    disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
+    fn16 = insn & 0x0000FFFF;
+    fn11 = (insn >> 5) & 0x000007FF;
+    fpfn = fn11 & 0x3F;
+    fn7 = (insn >> 5) & 0x0000007F;
+    fn2 = (insn >> 5) & 0x00000003;
+    ret = 0;
+#if defined ALPHA_DEBUG_DISAS
+    if (logfile != NULL) {
+        fprintf(logfile, "opc %02x ra %d rb %d rc %d disp16 %04x\n",
+                opc, ra, rb, rc, disp16);
+    }
+#endif
+    switch (opc) {
+    case 0x00:
+        /* CALL_PAL */
+        if (palcode >= 0x80 && palcode < 0xC0) {
+            /* Unprivileged PAL call */
+            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
+#if !defined (CONFIG_USER_ONLY)
+        } else if (palcode < 0x40) {
+            /* Privileged PAL code */
+            if (ctx->mem_idx & 1)
+                goto invalid_opc;
+            else
+                gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0);
+#endif
+        } else {
+            /* Invalid PAL call */
+            goto invalid_opc;
+        }
+        ret = 3;
+        break;
+    case 0x01:
+        /* OPC01 */
+        goto invalid_opc;
+    case 0x02:
+        /* OPC02 */
+        goto invalid_opc;
+    case 0x03:
+        /* OPC03 */
+        goto invalid_opc;
+    case 0x04:
+        /* OPC04 */
+        goto invalid_opc;
+    case 0x05:
+        /* OPC05 */
+        goto invalid_opc;
+    case 0x06:
+        /* OPC06 */
+        goto invalid_opc;
+    case 0x07:
+        /* OPC07 */
+        goto invalid_opc;
+    case 0x08:
+        /* LDA */
+        gen_load_ir(ctx, rb, 0);
+        gen_set_sT1(ctx, disp16);
+        gen_op_addq();
+        gen_store_ir(ctx, ra, 0);
+        break;
+    case 0x09:
+        /* LDAH */
+        gen_load_ir(ctx, rb, 0);
+        gen_set_sT1(ctx, disp16 << 16);
+        gen_op_addq();
+        gen_store_ir(ctx, ra, 0);
+        break;
+    case 0x0A:
+        /* LDBU */
+        if (!(ctx->amask & AMASK_BWX))
+            goto invalid_opc;
+        gen_load_mem(ctx, &gen_ldbu, ra, rb, disp16, 0);
+        break;
+    case 0x0B:
+        /* LDQ_U */
+        gen_load_mem(ctx, &gen_ldq_u, ra, rb, disp16, 1);
+        break;
+    case 0x0C:
+        /* LDWU */
+        if (!(ctx->amask & AMASK_BWX))
+            goto invalid_opc;
+        gen_load_mem(ctx, &gen_ldwu, ra, rb, disp16, 0);
+        break;
+    case 0x0D:
+        /* STW */
+        if (!(ctx->amask & AMASK_BWX))
+            goto invalid_opc;
+        gen_store_mem(ctx, &gen_stw, ra, rb, disp16, 0);
+        break;
+    case 0x0E:
+        /* STB */
+        if (!(ctx->amask & AMASK_BWX))
+            goto invalid_opc;
+        gen_store_mem(ctx, &gen_stb, ra, rb, disp16, 0);
+        break;
+    case 0x0F:
+        /* STQ_U */
+        gen_store_mem(ctx, &gen_stq_u, ra, rb, disp16, 1);
+        break;
+    case 0x10:
+        switch (fn7) {
+        case 0x00:
+            /* ADDL */
+            gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit);
+            break;
+        case 0x02:
+            /* S4ADDL */
+            gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit);
+            break;
+        case 0x09:
+            /* SUBL */
+            gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit);
+            break;
+        case 0x0B:
+            /* S4SUBL */
+            gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit);
+            break;
+        case 0x0F:
+            /* CMPBGE */
+            gen_arith3(ctx, &gen_op_cmpbge, ra, rb, rc, islit, lit);
+            break;
+        case 0x12:
+            /* S8ADDL */
+            gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit);
+            break;
+        case 0x1B:
+            /* S8SUBL */
+            gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit);
+            break;
+        case 0x1D:
+            /* CMPULT */
+            gen_arith3(ctx, &gen_op_cmpult, ra, rb, rc, islit, lit);
+            break;
+        case 0x20:
+            /* ADDQ */
+            gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit);
+            break;
+        case 0x22:
+            /* S4ADDQ */
+            gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit);
+            break;
+        case 0x29:
+            /* SUBQ */
+            gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit);
+            break;
+        case 0x2B:
+            /* S4SUBQ */
+            gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit);
+            break;
+        case 0x2D:
+            /* CMPEQ */
+            gen_arith3(ctx, &gen_op_cmpeq, ra, rb, rc, islit, lit);
+            break;
+        case 0x32:
+            /* S8ADDQ */
+            gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit);
+            break;
+        case 0x3B:
+            /* S8SUBQ */
+            gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit);
+            break;
+        case 0x3D:
+            /* CMPULE */
+            gen_arith3(ctx, &gen_op_cmpule, ra, rb, rc, islit, lit);
+            break;
+        case 0x40:
+            /* ADDL/V */
+            gen_arith3(ctx, &gen_op_addlv, ra, rb, rc, islit, lit);
+            break;
+        case 0x49:
+            /* SUBL/V */
+            gen_arith3(ctx, &gen_op_sublv, ra, rb, rc, islit, lit);
+            break;
+        case 0x4D:
+            /* CMPLT */
+            gen_arith3(ctx, &gen_op_cmplt, ra, rb, rc, islit, lit);
+            break;
+        case 0x60:
+            /* ADDQ/V */
+            gen_arith3(ctx, &gen_op_addqv, ra, rb, rc, islit, lit);
+            break;
+        case 0x69:
+            /* SUBQ/V */
+            gen_arith3(ctx, &gen_op_subqv, ra, rb, rc, islit, lit);
+            break;
+        case 0x6D:
+            /* CMPLE */
+            gen_arith3(ctx, &gen_op_cmple, ra, rb, rc, islit, lit);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x11:
+        switch (fn7) {
+        case 0x00:
+            /* AND */
+            gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit);
+            break;
+        case 0x08:
+            /* BIC */
+            gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit);
+            break;
+        case 0x14:
+            /* CMOVLBS */
+            gen_cmov(ctx, &gen_op_cmplbs, ra, rb, rc, islit, lit);
+            break;
+        case 0x16:
+            /* CMOVLBC */
+            gen_cmov(ctx, &gen_op_cmplbc, ra, rb, rc, islit, lit);
+            break;
+        case 0x20:
+            /* BIS */
+            if (ra == rb || ra == 31 || rb == 31) {
+                if (ra == 31 && rc == 31) {
+                    /* NOP */
+                    gen_op_nop();
+                } else {
+                    /* MOV */
+                    gen_load_ir(ctx, rb, 0);
+                    gen_store_ir(ctx, rc, 0);
+                }
+            } else {
+                gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit);
+            }
+            break;
+        case 0x24:
+            /* CMOVEQ */
+            gen_cmov(ctx, &gen_op_cmpeqz, ra, rb, rc, islit, lit);
+            break;
+        case 0x26:
+            /* CMOVNE */
+            gen_cmov(ctx, &gen_op_cmpnez, ra, rb, rc, islit, lit);
+            break;
+        case 0x28:
+            /* ORNOT */
+            gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit);
+            break;
+        case 0x40:
+            /* XOR */
+            gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit);
+            break;
+        case 0x44:
+            /* CMOVLT */
+            gen_cmov(ctx, &gen_op_cmpltz, ra, rb, rc, islit, lit);
+            break;
+        case 0x46:
+            /* CMOVGE */
+            gen_cmov(ctx, &gen_op_cmpgez, ra, rb, rc, islit, lit);
+            break;
+        case 0x48:
+            /* EQV */
+            gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit);
+            break;
+        case 0x61:
+            /* AMASK */
+            gen_arith2(ctx, &gen_amask, rb, rc, islit, lit);
+            break;
+        case 0x64:
+            /* CMOVLE */
+            gen_cmov(ctx, &gen_op_cmplez, ra, rb, rc, islit, lit);
+            break;
+        case 0x66:
+            /* CMOVGT */
+            gen_cmov(ctx, &gen_op_cmpgtz, ra, rb, rc, islit, lit);
+            break;
+        case 0x6C:
+            /* IMPLVER */
+            gen_op_load_implver();
+            gen_store_ir(ctx, rc, 0);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x12:
+        switch (fn7) {
+        case 0x02:
+            /* MSKBL */
+            gen_arith3(ctx, &gen_op_mskbl, ra, rb, rc, islit, lit);
+            break;
+        case 0x06:
+            /* EXTBL */
+            gen_arith3(ctx, &gen_op_extbl, ra, rb, rc, islit, lit);
+            break;
+        case 0x0B:
+            /* INSBL */
+            gen_arith3(ctx, &gen_op_insbl, ra, rb, rc, islit, lit);
+            break;
+        case 0x12:
+            /* MSKWL */
+            gen_arith3(ctx, &gen_op_mskwl, ra, rb, rc, islit, lit);
+            break;
+        case 0x16:
+            /* EXTWL */
+            gen_arith3(ctx, &gen_op_extwl, ra, rb, rc, islit, lit);
+            break;
+        case 0x1B:
+            /* INSWL */
+            gen_arith3(ctx, &gen_op_inswl, ra, rb, rc, islit, lit);
+            break;
+        case 0x22:
+            /* MSKLL */
+            gen_arith3(ctx, &gen_op_mskll, ra, rb, rc, islit, lit);
+            break;
+        case 0x26:
+            /* EXTLL */
+            gen_arith3(ctx, &gen_op_extll, ra, rb, rc, islit, lit);
+            break;
+        case 0x2B:
+            /* INSLL */
+            gen_arith3(ctx, &gen_op_insll, ra, rb, rc, islit, lit);
+            break;
+        case 0x30:
+            /* ZAP */
+            gen_arith3(ctx, &gen_op_zap, ra, rb, rc, islit, lit);
+            break;
+        case 0x31:
+            /* ZAPNOT */
+            gen_arith3(ctx, &gen_op_zapnot, ra, rb, rc, islit, lit);
+            break;
+        case 0x32:
+            /* MSKQL */
+            gen_arith3(ctx, &gen_op_mskql, ra, rb, rc, islit, lit);
+            break;
+        case 0x34:
+            /* SRL */
+            gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit);
+            break;
+        case 0x36:
+            /* EXTQL */
+            gen_arith3(ctx, &gen_op_extql, ra, rb, rc, islit, lit);
+            break;
+        case 0x39:
+            /* SLL */
+            gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit);
+            break;
+        case 0x3B:
+            /* INSQL */
+            gen_arith3(ctx, &gen_op_insql, ra, rb, rc, islit, lit);
+            break;
+        case 0x3C:
+            /* SRA */
+            gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit);
+            break;
+        case 0x52:
+            /* MSKWH */
+            gen_arith3(ctx, &gen_op_mskwh, ra, rb, rc, islit, lit);
+            break;
+        case 0x57:
+            /* INSWH */
+            gen_arith3(ctx, &gen_op_inswh, ra, rb, rc, islit, lit);
+            break;
+        case 0x5A:
+            /* EXTWH */
+            gen_arith3(ctx, &gen_op_extwh, ra, rb, rc, islit, lit);
+            break;
+        case 0x62:
+            /* MSKLH */
+            gen_arith3(ctx, &gen_op_msklh, ra, rb, rc, islit, lit);
+            break;
+        case 0x67:
+            /* INSLH */
+            gen_arith3(ctx, &gen_op_inslh, ra, rb, rc, islit, lit);
+            break;
+        case 0x6A:
+            /* EXTLH */
+            gen_arith3(ctx, &gen_op_extlh, ra, rb, rc, islit, lit);
+            break;
+        case 0x72:
+            /* MSKQH */
+            gen_arith3(ctx, &gen_op_mskqh, ra, rb, rc, islit, lit);
+            break;
+        case 0x77:
+            /* INSQH */
+            gen_arith3(ctx, &gen_op_insqh, ra, rb, rc, islit, lit);
+            break;
+        case 0x7A:
+            /* EXTQH */
+            gen_arith3(ctx, &gen_op_extqh, ra, rb, rc, islit, lit);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x13:
+        switch (fn7) {
+        case 0x00:
+            /* MULL */
+            gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit);
+            break;
+        case 0x20:
+            /* MULQ */
+            gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit);
+            break;
+        case 0x30:
+            /* UMULH */
+            gen_arith3(ctx, &gen_op_umulh, ra, rb, rc, islit, lit);
+            break;
+        case 0x40:
+            /* MULL/V */
+            gen_arith3(ctx, &gen_op_mullv, ra, rb, rc, islit, lit);
+            break;
+        case 0x60:
+            /* MULQ/V */
+            gen_arith3(ctx, &gen_op_mulqv, ra, rb, rc, islit, lit);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x14:
+        switch (fpfn) { /* f11 & 0x3F */
+        case 0x04:
+            /* ITOFS */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_itf(ctx, &gen_op_itofs, ra, rc);
+            break;
+        case 0x0A:
+            /* SQRTF */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_farith2(ctx, &gen_op_sqrtf, rb, rc);
+            break;
+        case 0x0B:
+            /* SQRTS */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_farith2(ctx, &gen_op_sqrts, rb, rc);
+            break;
+        case 0x14:
+            /* ITOFF */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+#if 0 // TODO
+            gen_itf(ctx, &gen_op_itoff, ra, rc);
+#else
+            goto invalid_opc;
+#endif
+            break;
+        case 0x24:
+            /* ITOFT */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_itf(ctx, &gen_op_itoft, ra, rc);
+            break;
+        case 0x2A:
+            /* SQRTG */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_farith2(ctx, &gen_op_sqrtg, rb, rc);
+            break;
+        case 0x02B:
+            /* SQRTT */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_farith2(ctx, &gen_op_sqrtt, rb, rc);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x15:
+        /* VAX floating point */
+        /* XXX: rounding mode and trap are ignored (!) */
+        switch (fpfn) { /* f11 & 0x3F */
+        case 0x00:
+            /* ADDF */
+            gen_farith3(ctx, &gen_op_addf, ra, rb, rc);
+            break;
+        case 0x01:
+            /* SUBF */
+            gen_farith3(ctx, &gen_op_subf, ra, rb, rc);
+            break;
+        case 0x02:
+            /* MULF */
+            gen_farith3(ctx, &gen_op_mulf, ra, rb, rc);
+            break;
+        case 0x03:
+            /* DIVF */
+            gen_farith3(ctx, &gen_op_divf, ra, rb, rc);
+            break;
+        case 0x1E:
+            /* CVTDG */
+#if 0 // TODO
+            gen_farith2(ctx, &gen_op_cvtdg, rb, rc);
+#else
+            goto invalid_opc;
+#endif
+            break;
+        case 0x20:
+            /* ADDG */
+            gen_farith3(ctx, &gen_op_addg, ra, rb, rc);
+            break;
+        case 0x21:
+            /* SUBG */
+            gen_farith3(ctx, &gen_op_subg, ra, rb, rc);
+            break;
+        case 0x22:
+            /* MULG */
+            gen_farith3(ctx, &gen_op_mulg, ra, rb, rc);
+            break;
+        case 0x23:
+            /* DIVG */
+            gen_farith3(ctx, &gen_op_divg, ra, rb, rc);
+            break;
+        case 0x25:
+            /* CMPGEQ */
+            gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc);
+            break;
+        case 0x26:
+            /* CMPGLT */
+            gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc);
+            break;
+        case 0x27:
+            /* CMPGLE */
+            gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc);
+            break;
+        case 0x2C:
+            /* CVTGF */
+            gen_farith2(ctx, &gen_op_cvtgf, rb, rc);
+            break;
+        case 0x2D:
+            /* CVTGD */
+#if 0 // TODO
+            gen_farith2(ctx, &gen_op_cvtgd, rb, rc);
+#else
+            goto invalid_opc;
+#endif
+            break;
+        case 0x2F:
+            /* CVTGQ */
+            gen_farith2(ctx, &gen_op_cvtgq, rb, rc);
+            break;
+        case 0x3C:
+            /* CVTQF */
+            gen_farith2(ctx, &gen_op_cvtqf, rb, rc);
+            break;
+        case 0x3E:
+            /* CVTQG */
+            gen_farith2(ctx, &gen_op_cvtqg, rb, rc);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x16:
+        /* IEEE floating-point */
+        /* XXX: rounding mode and traps are ignored (!) */
+        switch (fpfn) { /* f11 & 0x3F */
+        case 0x00:
+            /* ADDS */
+            gen_farith3(ctx, &gen_op_adds, ra, rb, rc);
+            break;
+        case 0x01:
+            /* SUBS */
+            gen_farith3(ctx, &gen_op_subs, ra, rb, rc);
+            break;
+        case 0x02:
+            /* MULS */
+            gen_farith3(ctx, &gen_op_muls, ra, rb, rc);
+            break;
+        case 0x03:
+            /* DIVS */
+            gen_farith3(ctx, &gen_op_divs, ra, rb, rc);
+            break;
+        case 0x20:
+            /* ADDT */
+            gen_farith3(ctx, &gen_op_addt, ra, rb, rc);
+            break;
+        case 0x21:
+            /* SUBT */
+            gen_farith3(ctx, &gen_op_subt, ra, rb, rc);
+            break;
+        case 0x22:
+            /* MULT */
+            gen_farith3(ctx, &gen_op_mult, ra, rb, rc);
+            break;
+        case 0x23:
+            /* DIVT */
+            gen_farith3(ctx, &gen_op_divt, ra, rb, rc);
+            break;
+        case 0x24:
+            /* CMPTUN */
+            gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc);
+            break;
+        case 0x25:
+            /* CMPTEQ */
+            gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc);
+            break;
+        case 0x26:
+            /* CMPTLT */
+            gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc);
+            break;
+        case 0x27:
+            /* CMPTLE */
+            gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc);
+            break;
+        case 0x2C:
+            /* XXX: incorrect */
+            if (fn11 == 0x2AC) {
+                /* CVTST */
+                gen_farith2(ctx, &gen_op_cvtst, rb, rc);
+            } else {
+                /* CVTTS */
+                gen_farith2(ctx, &gen_op_cvtts, rb, rc);
+            }
+            break;
+        case 0x2F:
+            /* CVTTQ */
+            gen_farith2(ctx, &gen_op_cvttq, rb, rc);
+            break;
+        case 0x3C:
+            /* CVTQS */
+            gen_farith2(ctx, &gen_op_cvtqs, rb, rc);
+            break;
+        case 0x3E:
+            /* CVTQT */
+            gen_farith2(ctx, &gen_op_cvtqt, rb, rc);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x17:
+        switch (fn11) {
+        case 0x010:
+            /* CVTLQ */
+            gen_farith2(ctx, &gen_op_cvtlq, rb, rc);
+            break;
+        case 0x020:
+            /* CPYS */
+            if (ra == rb) {
+                if (ra == 31 && rc == 31) {
+                    /* FNOP */
+                    gen_op_nop();
+                } else {
+                    /* FMOV */
+                    gen_load_fir(ctx, rb, 0);
+                    gen_store_fir(ctx, rc, 0);
+                }
+            } else {
+                gen_farith3(ctx, &gen_op_cpys, ra, rb, rc);
+            }
+            break;
+        case 0x021:
+            /* CPYSN */
+            gen_farith2(ctx, &gen_op_cpysn, rb, rc);
+            break;
+        case 0x022:
+            /* CPYSE */
+            gen_farith2(ctx, &gen_op_cpyse, rb, rc);
+            break;
+        case 0x024:
+            /* MT_FPCR */
+            gen_load_fir(ctx, ra, 0);
+            gen_op_store_fpcr();
+            break;
+        case 0x025:
+            /* MF_FPCR */
+            gen_op_load_fpcr();
+            gen_store_fir(ctx, ra, 0);
+            break;
+        case 0x02A:
+            /* FCMOVEQ */
+            gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc);
+            break;
+        case 0x02B:
+            /* FCMOVNE */
+            gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc);
+            break;
+        case 0x02C:
+            /* FCMOVLT */
+            gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc);
+            break;
+        case 0x02D:
+            /* FCMOVGE */
+            gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc);
+            break;
+        case 0x02E:
+            /* FCMOVLE */
+            gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc);
+            break;
+        case 0x02F:
+            /* FCMOVGT */
+            gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc);
+            break;
+        case 0x030:
+            /* CVTQL */
+            gen_farith2(ctx, &gen_op_cvtql, rb, rc);
+            break;
+        case 0x130:
+            /* CVTQL/V */
+            gen_farith2(ctx, &gen_op_cvtqlv, rb, rc);
+            break;
+        case 0x530:
+            /* CVTQL/SV */
+            gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x18:
+        switch ((uint16_t)disp16) {
+        case 0x0000:
+            /* TRAPB */
+            /* No-op. Just exit from the current tb */
+            ret = 2;
+            break;
+        case 0x0400:
+            /* EXCB */
+            /* No-op. Just exit from the current tb */
+            ret = 2;
+            break;
+        case 0x4000:
+            /* MB */
+            /* No-op */
+            break;
+        case 0x4400:
+            /* WMB */
+            /* No-op */
+            break;
+        case 0x8000:
+            /* FETCH */
+            /* No-op */
+            break;
+        case 0xA000:
+            /* FETCH_M */
+            /* No-op */
+            break;
+        case 0xC000:
+            /* RPCC */
+            gen_op_load_pcc();
+            gen_store_ir(ctx, ra, 0);
+            break;
+        case 0xE000:
+            /* RC */
+            gen_op_load_irf();
+            gen_store_ir(ctx, ra, 0);
+            gen_op_clear_irf();
+            break;
+        case 0xE800:
+            /* ECB */
+            /* XXX: TODO: evict tb cache at address rb */
+#if 0
+            ret = 2;
+#else
+            goto invalid_opc;
+#endif
+            break;
+        case 0xF000:
+            /* RS */
+            gen_op_load_irf();
+            gen_store_ir(ctx, ra, 0);
+            gen_op_set_irf();
+            break;
+        case 0xF800:
+            /* WH64 */
+            /* No-op */
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x19:
+        /* HW_MFPR (PALcode) */
+#if defined (CONFIG_USER_ONLY)
+        goto invalid_opc;
+#else
+        if (!ctx->pal_mode)
+            goto invalid_opc;
+        gen_op_mfpr(insn & 0xFF);
+        gen_store_ir(ctx, ra, 0);
+        break;
+#endif
+    case 0x1A:
+        gen_load_ir(ctx, rb, 0);
+        if (ra != 31) {
+            gen_set_uT1(ctx, ctx->pc);
+            gen_store_ir(ctx, ra, 1);
+        }
+        gen_op_branch();
+        /* Those four jumps only differ by the branch prediction hint */
+        switch (fn2) {
+        case 0x0:
+            /* JMP */
+            break;
+        case 0x1:
+            /* JSR */
+            break;
+        case 0x2:
+            /* RET */
+            break;
+        case 0x3:
+            /* JSR_COROUTINE */
+            break;
+        }
+        ret = 1;
+        break;
+    case 0x1B:
+        /* HW_LD (PALcode) */
+#if defined (CONFIG_USER_ONLY)
+        goto invalid_opc;
+#else
+        if (!ctx->pal_mode)
+            goto invalid_opc;
+        gen_load_ir(ctx, rb, 0);
+        gen_set_sT1(ctx, disp12);
+        gen_op_addq();
+        switch ((insn >> 12) & 0xF) {
+        case 0x0:
+            /* Longword physical access */
+            gen_op_ldl_raw();
+            break;
+        case 0x1:
+            /* Quadword physical access */
+            gen_op_ldq_raw();
+            break;
+        case 0x2:
+            /* Longword physical access with lock */
+            gen_op_ldl_l_raw();
+            break;
+        case 0x3:
+            /* Quadword physical access with lock */
+            gen_op_ldq_l_raw();
+            break;
+        case 0x4:
+            /* Longword virtual PTE fetch */
+            gen_op_ldl_kernel();
+            break;
+        case 0x5:
+            /* Quadword virtual PTE fetch */
+            gen_op_ldq_kernel();
+            break;
+        case 0x6:
+            /* Invalid */
+            goto invalid_opc;
+        case 0x7:
+            /* Invalid */
+            goto invalid_opc;
+        case 0x8:
+            /* Longword virtual access */
+            gen_op_ld_phys_to_virt();
+            gen_op_ldl_raw();
+            break;
+        case 0x9:
+            /* Quadword virtual access */
+            gen_op_ld_phys_to_virt();
+            gen_op_ldq_raw();
+            break;
+        case 0xA:
+            /* Longword virtual access with protection check */
+            gen_ldl(ctx);
+            break;
+        case 0xB:
+            /* Quadword virtual access with protection check */
+            gen_ldq(ctx);
+            break;
+        case 0xC:
+            /* Longword virtual access with altenate access mode */
+            gen_op_set_alt_mode();
+            gen_op_ld_phys_to_virt();
+            gen_op_ldl_raw();
+            gen_op_restore_mode();
+            break;
+        case 0xD:
+            /* Quadword virtual access with altenate access mode */
+            gen_op_set_alt_mode();
+            gen_op_ld_phys_to_virt();
+            gen_op_ldq_raw();
+            gen_op_restore_mode();
+            break;
+        case 0xE:
+            /* Longword virtual access with alternate access mode and
+             * protection checks
+             */
+            gen_op_set_alt_mode();
+            gen_op_ldl_data();
+            gen_op_restore_mode();
+            break;
+        case 0xF:
+            /* Quadword virtual access with alternate access mode and
+             * protection checks
+             */
+            gen_op_set_alt_mode();
+            gen_op_ldq_data();
+            gen_op_restore_mode();
+            break;
+        }
+        gen_store_ir(ctx, ra, 1);
+        break;
+#endif
+    case 0x1C:
+        switch (fn7) {
+        case 0x00:
+            /* SEXTB */
+            if (!(ctx->amask & AMASK_BWX))
+                goto invalid_opc;
+            gen_arith2(ctx, &gen_op_sextb, rb, rc, islit, lit);
+            break;
+        case 0x01:
+            /* SEXTW */
+            if (!(ctx->amask & AMASK_BWX))
+                goto invalid_opc;
+            gen_arith2(ctx, &gen_op_sextw, rb, rc, islit, lit);
+            break;
+        case 0x30:
+            /* CTPOP */
+            if (!(ctx->amask & AMASK_CIX))
+                goto invalid_opc;
+            gen_arith2(ctx, &gen_op_ctpop, rb, rc, 0, 0);
+            break;
+        case 0x31:
+            /* PERR */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x32:
+            /* CTLZ */
+            if (!(ctx->amask & AMASK_CIX))
+                goto invalid_opc;
+            gen_arith2(ctx, &gen_op_ctlz, rb, rc, 0, 0);
+            break;
+        case 0x33:
+            /* CTTZ */
+            if (!(ctx->amask & AMASK_CIX))
+                goto invalid_opc;
+            gen_arith2(ctx, &gen_op_cttz, rb, rc, 0, 0);
+            break;
+        case 0x34:
+            /* UNPKBW */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x35:
+            /* UNPKWL */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x36:
+            /* PKWB */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x37:
+            /* PKLB */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x38:
+            /* MINSB8 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x39:
+            /* MINSW4 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3A:
+            /* MINUB8 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3B:
+            /* MINUW4 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3C:
+            /* MAXUB8 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3D:
+            /* MAXUW4 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3E:
+            /* MAXSB8 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x3F:
+            /* MAXSW4 */
+            if (!(ctx->amask & AMASK_MVI))
+                goto invalid_opc;
+            /* XXX: TODO */
+            goto invalid_opc;
+            break;
+        case 0x70:
+            /* FTOIT */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_fti(ctx, &gen_op_ftoit, ra, rb);
+            break;
+        case 0x78:
+            /* FTOIS */
+            if (!(ctx->amask & AMASK_FIX))
+                goto invalid_opc;
+            gen_fti(ctx, &gen_op_ftois, ra, rb);
+            break;
+        default:
+            goto invalid_opc;
+        }
+        break;
+    case 0x1D:
+        /* HW_MTPR (PALcode) */
+#if defined (CONFIG_USER_ONLY)
+        goto invalid_opc;
+#else
+        if (!ctx->pal_mode)
+            goto invalid_opc;
+        gen_load_ir(ctx, ra, 0);
+        gen_op_mtpr(insn & 0xFF);
+        ret = 2;
+        break;
+#endif
+    case 0x1E:
+        /* HW_REI (PALcode) */
+#if defined (CONFIG_USER_ONLY)
+        goto invalid_opc;
+#else
+        if (!ctx->pal_mode)
+            goto invalid_opc;
+        if (rb == 31) {
+            /* "Old" alpha */
+            gen_op_hw_rei();
+        } else {
+            gen_load_ir(ctx, rb, 0);
+            gen_set_uT1(ctx, (((int64_t)insn << 51) >> 51));
+            gen_op_addq();
+            gen_op_hw_ret();
+        }
+        ret = 2;
+        break;
+#endif
+    case 0x1F:
+        /* HW_ST (PALcode) */
+#if defined (CONFIG_USER_ONLY)
+        goto invalid_opc;
+#else
+        if (!ctx->pal_mode)
+            goto invalid_opc;
+        gen_load_ir(ctx, rb, 0);
+        gen_set_sT1(ctx, disp12);
+        gen_op_addq();
+        gen_load_ir(ctx, ra, 1);
+        switch ((insn >> 12) & 0xF) {
+        case 0x0:
+            /* Longword physical access */
+            gen_op_stl_raw();
+            break;
+        case 0x1:
+            /* Quadword physical access */
+            gen_op_stq_raw();
+            break;
+        case 0x2:
+            /* Longword physical access with lock */
+            gen_op_stl_c_raw();
+            break;
+        case 0x3:
+            /* Quadword physical access with lock */
+            gen_op_stq_c_raw();
+            break;
+        case 0x4:
+            /* Longword virtual access */
+            gen_op_st_phys_to_virt();
+            gen_op_stl_raw();
+            break;
+        case 0x5:
+            /* Quadword virtual access */
+            gen_op_st_phys_to_virt();
+            gen_op_stq_raw();
+            break;
+        case 0x6:
+            /* Invalid */
+            goto invalid_opc;
+        case 0x7:
+            /* Invalid */
+            goto invalid_opc;
+        case 0x8:
+            /* Invalid */
+            goto invalid_opc;
+        case 0x9:
+            /* Invalid */
+            goto invalid_opc;
+        case 0xA:
+            /* Invalid */
+            goto invalid_opc;
+        case 0xB:
+            /* Invalid */
+            goto invalid_opc;
+        case 0xC:
+            /* Longword virtual access with alternate access mode */
+            gen_op_set_alt_mode();
+            gen_op_st_phys_to_virt();
+            gen_op_ldl_raw();
+            gen_op_restore_mode();
+            break;
+        case 0xD:
+            /* Quadword virtual access with alternate access mode */
+            gen_op_set_alt_mode();
+            gen_op_st_phys_to_virt();
+            gen_op_ldq_raw();
+            gen_op_restore_mode();
+            break;
+        case 0xE:
+            /* Invalid */
+            goto invalid_opc;
+        case 0xF:
+            /* Invalid */
+            goto invalid_opc;
+        }
+        ret = 2;
+        break;
+#endif
+    case 0x20:
+        /* LDF */
+#if 0 // TODO
+        gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16);
+#else
+        goto invalid_opc;
+#endif
+        break;
+    case 0x21:
+        /* LDG */
+#if 0 // TODO
+        gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16);
+#else
+        goto invalid_opc;
+#endif
+        break;
+    case 0x22:
+        /* LDS */
+        gen_load_fmem(ctx, &gen_lds, ra, rb, disp16);
+        break;
+    case 0x23:
+        /* LDT */
+        gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16);
+        break;
+    case 0x24:
+        /* STF */
+#if 0 // TODO
+        gen_store_fmem(ctx, &gen_stf, ra, rb, disp16);
+#else
+        goto invalid_opc;
+#endif
+        break;
+    case 0x25:
+        /* STG */
+#if 0 // TODO
+        gen_store_fmem(ctx, &gen_stg, ra, rb, disp16);
+#else
+        goto invalid_opc;
+#endif
+        break;
+    case 0x26:
+        /* STS */
+        gen_store_fmem(ctx, &gen_sts, ra, rb, disp16);
+        break;
+    case 0x27:
+        /* STT */
+        gen_store_fmem(ctx, &gen_stt, ra, rb, disp16);
+        break;
+    case 0x28:
+        /* LDL */
+        gen_load_mem(ctx, &gen_ldl, ra, rb, disp16, 0);
+        break;
+    case 0x29:
+        /* LDQ */
+        gen_load_mem(ctx, &gen_ldq, ra, rb, disp16, 0);
+        break;
+    case 0x2A:
+        /* LDL_L */
+        gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0);
+        break;
+    case 0x2B:
+        /* LDQ_L */
+        gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0);
+        break;
+    case 0x2C:
+        /* STL */
+        gen_store_mem(ctx, &gen_stl, ra, rb, disp16, 0);
+        break;
+    case 0x2D:
+        /* STQ */
+        gen_store_mem(ctx, &gen_stq, ra, rb, disp16, 0);
+        break;
+    case 0x2E:
+        /* STL_C */
+        gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0);
+        break;
+    case 0x2F:
+        /* STQ_C */
+        gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0);
+        break;
+    case 0x30:
+        /* BR */
+        gen_set_uT0(ctx, ctx->pc);
+        gen_store_ir(ctx, ra, 0);
+        if (disp21 != 0) {
+            gen_set_sT1(ctx, disp21 << 2);
+            gen_op_addq();
+        }
+        gen_op_branch();
+        ret = 1;
+        break;
+    case 0x31:
+        /* FBEQ */
+        gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16);
+        ret = 1;
+        break;
+    case 0x32:
+        /* FBLT */
+        gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16);
+        ret = 1;
+        break;
+    case 0x33:
+        /* FBLE */
+        gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16);
+        ret = 1;
+        break;
+    case 0x34:
+        /* BSR */
+        gen_set_uT0(ctx, ctx->pc);
+        gen_store_ir(ctx, ra, 0);
+        if (disp21 != 0) {
+            gen_set_sT1(ctx, disp21 << 2);
+            gen_op_addq();
+        }
+        gen_op_branch();
+        ret = 1;
+        break;
+    case 0x35:
+        /* FBNE */
+        gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16);
+        ret = 1;
+        break;
+    case 0x36:
+        /* FBGE */
+        gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16);
+        ret = 1;
+        break;
+    case 0x37:
+        /* FBGT */
+        gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16);
+        ret = 1;
+        break;
+    case 0x38:
+        /* BLBC */
+        gen_bcond(ctx, &gen_op_cmplbc, ra, disp16);
+        ret = 1;
+        break;
+    case 0x39:
+        /* BEQ */
+        gen_bcond(ctx, &gen_op_cmpeqz, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3A:
+        /* BLT */
+        gen_bcond(ctx, &gen_op_cmpltz, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3B:
+        /* BLE */
+        gen_bcond(ctx, &gen_op_cmplez, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3C:
+        /* BLBS */
+        gen_bcond(ctx, &gen_op_cmplbs, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3D:
+        /* BNE */
+        gen_bcond(ctx, &gen_op_cmpnez, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3E:
+        /* BGE */
+        gen_bcond(ctx, &gen_op_cmpgez, ra, disp16);
+        ret = 1;
+        break;
+    case 0x3F:
+        /* BGT */
+        gen_bcond(ctx, &gen_op_cmpgtz, ra, disp16);
+        ret = 1;
+        break;
+    invalid_opc:
+        gen_invalid(ctx);
+        ret = 3;
+        break;
+    }
+
+    return ret;
+}
+
+int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
+                                    int search_pc)
+{
+#if defined ALPHA_DEBUG_DISAS
+    static int insn_count;
+#endif
+    DisasContext ctx, *ctxp = &ctx;
+    target_ulong pc_start;
+    uint32_t insn;
+    uint16_t *gen_opc_end;
+    int j, lj = -1;
+    int ret;
+
+    pc_start = tb->pc;
+    gen_opc_ptr = gen_opc_buf;
+    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+    gen_opparam_ptr = gen_opparam_buf;
+    nb_gen_labels = 0;
+    ctx.pc = pc_start;
+    ctx.amask = env->amask;
+#if defined (CONFIG_USER_ONLY)
+    ctx.mem_idx = 0;
+#else
+    ctx.mem_idx = ((env->ps >> 3) & 3);
+    ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
+#endif
+    for (ret = 0; ret == 0;) {
+        if (env->nb_breakpoints > 0) {
+            for(j = 0; j < env->nb_breakpoints; j++) {
+                if (env->breakpoints[j] == ctx.pc) {
+                    gen_excp(&ctx, EXCP_DEBUG, 0);
+                    break;
+                }
+            }
+        }
+        if (search_pc) {
+            j = gen_opc_ptr - gen_opc_buf;
+            if (lj < j) {
+                lj++;
+                while (lj < j)
+                    gen_opc_instr_start[lj++] = 0;
+                gen_opc_pc[lj] = ctx.pc;
+                gen_opc_instr_start[lj] = 1;
+            }
+        }
+#if defined ALPHA_DEBUG_DISAS
+        insn_count++;
+        if (logfile != NULL) {
+            fprintf(logfile, "pc " TARGET_FMT_lx " mem_idx %d\n",
+                    ctx.pc, ctx.mem_idx);
+        }
+#endif
+        insn = ldl_code(ctx.pc);
+#if defined ALPHA_DEBUG_DISAS
+        insn_count++;
+        if (logfile != NULL) {
+            fprintf(logfile, "opcode %08x %d\n", insn, insn_count);
+        }
+#endif
+        ctx.pc += 4;
+        ret = translate_one(ctxp, insn);
+        if (ret != 0)
+            break;
+        /* if we reach a page boundary or are single stepping, stop
+         * generation
+         */
+        if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
+            (env->singlestep_enabled)) {
+            break;
+        }
+#if defined (DO_SINGLE_STEP)
+        break;
+#endif
+    }
+    if (ret != 1 && ret != 3) {
+        gen_update_pc(&ctx);
+    }
+    gen_op_reset_T0();
+#if defined (DO_TB_FLUSH)
+    gen_op_tb_flush();
+#endif
+    /* Generate the return instruction */
+    gen_op_exit_tb();
+    *gen_opc_ptr = INDEX_op_end;
+    if (search_pc) {
+        j = gen_opc_ptr - gen_opc_buf;
+        lj++;
+        while (lj <= j)
+            gen_opc_instr_start[lj++] = 0;
+        tb->size = 0;
+    } else {
+        tb->size = ctx.pc - pc_start;
+    }
+#if defined ALPHA_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_CPU) {
+        cpu_dump_state(env, logfile, fprintf, 0);
+    }
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
+	target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
+        fprintf(logfile, "\n");
+    }
+    if (loglevel & CPU_LOG_TB_OP) {
+        fprintf(logfile, "OP:\n");
+        dump_ops(gen_opc_buf, gen_opparam_buf);
+        fprintf(logfile, "\n");
+    }
+#endif
+
+    return 0;
+}
+
+int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+{
+    return gen_intermediate_code_internal(env, tb, 0);
+}
+
+int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+{
+    return gen_intermediate_code_internal(env, tb, 1);
+}
+
+CPUAlphaState * cpu_alpha_init (void)
+{
+    CPUAlphaState *env;
+    uint64_t hwpcb;
+
+    env = qemu_mallocz(sizeof(CPUAlphaState));
+    if (!env)
+        return NULL;
+    cpu_exec_init(env);
+    tlb_flush(env, 1);
+    /* XXX: should not be hardcoded */
+    env->implver = IMPLVER_2106x;
+    env->ps = 0x1F00;
+#if defined (CONFIG_USER_ONLY)
+    env->ps |= 1 << 3;
+#endif
+    pal_init(env);
+    /* Initialize IPR */
+    hwpcb = env->ipr[IPR_PCBB];
+    env->ipr[IPR_ASN] = 0;
+    env->ipr[IPR_ASTEN] = 0;
+    env->ipr[IPR_ASTSR] = 0;
+    env->ipr[IPR_DATFX] = 0;
+    /* XXX: fix this */
+    //    env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
+    //    env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
+    //    env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
+    //    env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
+    env->ipr[IPR_FEN] = 0;
+    env->ipr[IPR_IPL] = 31;
+    env->ipr[IPR_MCES] = 0;
+    env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
+    //    env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
+    env->ipr[IPR_SISR] = 0;
+    env->ipr[IPR_VIRBND] = -1ULL;
+
+    return env;
+}

Modified: trunk/src/host/qemu-neo1973/target-arm/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -38,9 +38,10 @@
 #define EXCP_FIQ             6
 #define EXCP_BKPT            7
 
-typedef void ARMWriteCPFunc(void *opaque,
-                int op2, int reg, int crm, uint32_t value);
-typedef uint32_t ARMReadCPFunc(void *opaque, int op2, int reg, int crm);
+typedef void ARMWriteCPFunc(void *opaque, int cp_info,
+                            int srcreg, int operand, uint32_t value);
+typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info,
+                               int dstreg, int operand);
 
 /* We currently assume float and double are IEEE single and double
    precision respectively.
@@ -82,10 +83,14 @@
         uint32_t c0_cachetype;
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
-        uint32_t c2; /* MMU translation table base.  */
-        uint32_t c3; /* MMU domain access control register.  */
+        uint32_t c2_base; /* MMU translation table base.  */
+        uint32_t c2_data; /* MPU data cachable bits.  */
+        uint32_t c2_insn; /* MPU instruction cachable bits.  */
+        uint32_t c3; /* MMU domain access control register
+                        MPU write buffer control.  */
         uint32_t c5_insn; /* Fault status registers.  */
         uint32_t c5_data;
+        uint32_t c6_region[8]; /* MPU base/size registers.  */
         uint32_t c6_insn; /* Fault address registers.  */
         uint32_t c6_data;
         uint32_t c9_insn; /* Cache lockdown registers.  */
@@ -143,6 +148,13 @@
 
     CPU_COMMON
 
+    /* These fields after the common ones so they are preserved on reset.  */
+    int ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+    int board_id;
+    target_phys_addr_t loader_start;
 } CPUARMState;
 
 CPUARMState *cpu_arm_init(void);
@@ -154,8 +166,7 @@
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
-struct siginfo;
-int cpu_arm_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_arm_signal_handler(int host_signum, void *pinfo, 
                            void *puc);
 
 #define CPSR_M (0x1f)
@@ -236,6 +247,7 @@
     ARM_FEATURE_XSCALE, /* Intel XScale extensions.  */
     ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension.  */
     ARM_FEATURE_S3C,    /* S3C specific bits.  */
+    ARM_FEATURE_MPU     /* Only has Memory Protection Unit, not full MMU.  */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
@@ -243,14 +255,16 @@
     return (env->features & (1u << feature)) != 0;
 }
 
-void cpu_arm_set_model(CPUARMState *env, uint32_t id);
+void arm_cpu_list(void);
+void cpu_arm_set_model(CPUARMState *env, const char *name);
 
 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
-                ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
-                void *opaque);
+                       ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
+                       void *opaque);
 
 #define ARM_CPUID_ARM1026   0x4106a262
 #define ARM_CPUID_ARM926    0x41069265
+#define ARM_CPUID_ARM946    0x41059461
 #define ARM_CPUID_ARM920T   0x41129200
 #define ARM_CPUID_PXA250    0x69052100
 #define ARM_CPUID_PXA255    0x69052d00

Modified: trunk/src/host/qemu-neo1973/target-arm/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -17,6 +17,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include "config.h"
 #include "dyngen-exec.h"
 
 register struct CPUARMState *env asm(AREG0);

Modified: trunk/src/host/qemu-neo1973/target-arm/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -5,56 +5,34 @@
 #include "cpu.h"
 #include "exec-all.h"
 
-void cpu_reset(CPUARMState *env)
-{
-#if defined (CONFIG_USER_ONLY)
-    env->uncached_cpsr = ARM_CPU_MODE_USR;
-    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
-#else
-    /* SVC mode with interrupts disabled.  */
-    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
-    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
-#endif
-    env->regs[15] = 0;
-}
-
-CPUARMState *cpu_arm_init(void)
-{
-    CPUARMState *env;
-
-    env = qemu_mallocz(sizeof(CPUARMState));
-    if (!env)
-        return NULL;
-    cpu_exec_init(env);
-    cpu_reset(env);
-    tlb_flush(env, 1);
-    return env;
-}
-
 static inline void set_feature(CPUARMState *env, int feature)
 {
     env->features |= 1u << feature;
 }
 
-void cpu_arm_set_model(CPUARMState *env, uint32_t id)
+static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 {
     env->cp15.c0_cpuid = id;
     switch (id) {
+    case ARM_CPUID_ARM920T:
+        set_feature(env, ARM_FEATURE_S3C);
+        env->cp15.c0_cachetype = 0xd172172;
+        break;
     case ARM_CPUID_ARM926:
         set_feature(env, ARM_FEATURE_VFP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
+    case ARM_CPUID_ARM946:
+        set_feature(env, ARM_FEATURE_MPU);
+        env->cp15.c0_cachetype = 0x0f004006;
+        break;
     case ARM_CPUID_ARM1026:
         set_feature(env, ARM_FEATURE_VFP);
         set_feature(env, ARM_FEATURE_AUXCR);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
-    case ARM_CPUID_ARM920T:
-        set_feature(env, ARM_FEATURE_S3C);
-        env->cp15.c0_cachetype = 0xd172172;
-        break;
     case ARM_CPUID_PXA250:
     case ARM_CPUID_PXA255:
     case ARM_CPUID_PXA260:
@@ -82,6 +60,92 @@
     }
 }
 
+void cpu_reset(CPUARMState *env)
+{
+    uint32_t id;
+    id = env->cp15.c0_cpuid;
+    memset(env, 0, offsetof(CPUARMState, breakpoints));
+    if (id)
+        cpu_reset_model_id(env, id);
+#if defined (CONFIG_USER_ONLY)
+    env->uncached_cpsr = ARM_CPU_MODE_USR;
+    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
+#else
+    /* SVC mode with interrupts disabled.  */
+    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
+#endif
+    env->regs[15] = 0;
+    tlb_flush(env, 1);
+}
+
+CPUARMState *cpu_arm_init(void)
+{
+    CPUARMState *env;
+
+    env = qemu_mallocz(sizeof(CPUARMState));
+    if (!env)
+        return NULL;
+    cpu_exec_init(env);
+    cpu_reset(env);
+    return env;
+}
+
+struct arm_cpu_t {
+    uint32_t id;
+    const char *name;
+};
+
+static const struct arm_cpu_t arm_cpu_names[] = {
+    { ARM_CPUID_ARM920T, "arm920t"},
+    { ARM_CPUID_ARM926, "arm926"},
+    { ARM_CPUID_ARM946, "arm946"},
+    { ARM_CPUID_ARM1026, "arm1026"},
+    { ARM_CPUID_PXA250, "pxa250" },
+    { ARM_CPUID_PXA255, "pxa255" },
+    { ARM_CPUID_PXA260, "pxa260" },
+    { ARM_CPUID_PXA261, "pxa261" },
+    { ARM_CPUID_PXA262, "pxa262" },
+    { ARM_CPUID_PXA270, "pxa270" },
+    { ARM_CPUID_PXA270_A0, "pxa270-a0" },
+    { ARM_CPUID_PXA270_A1, "pxa270-a1" },
+    { ARM_CPUID_PXA270_B0, "pxa270-b0" },
+    { ARM_CPUID_PXA270_B1, "pxa270-b1" },
+    { ARM_CPUID_PXA270_C0, "pxa270-c0" },
+    { ARM_CPUID_PXA270_C5, "pxa270-c5" },
+    { 0, NULL}
+};
+
+void arm_cpu_list(void)
+{
+    int i;
+
+    printf ("Available CPUs:\n");
+    for (i = 0; arm_cpu_names[i].name; i++) {
+        printf("  %s\n", arm_cpu_names[i].name);
+    }
+}
+
+void cpu_arm_set_model(CPUARMState *env, const char *name)
+{
+    int i;
+    uint32_t id;
+
+    id = 0;
+    i = 0;
+    for (i = 0; arm_cpu_names[i].name; i++) {
+        if (strcmp(name, arm_cpu_names[i].name) == 0) {
+            id = arm_cpu_names[i].id;
+            break;
+        }
+    }
+    if (!id) {
+        cpu_abort(env, "Unknown CPU '%s'", name);
+        return;
+    }
+    cpu_reset_model_id(env, id);
+}
+
 void cpu_arm_close(CPUARMState *env)
 {
     free(env);
@@ -107,12 +171,26 @@
     return 1;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
 
 /* These should probably raise undefined insn exceptions.  */
+void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
+{
+    int op1 = (insn >> 8) & 0xf;
+    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
+    return;
+}
+
+uint32_t helper_get_cp(CPUState *env, uint32_t insn)
+{
+    int op1 = (insn >> 8) & 0xf;
+    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
+    return 0;
+}
+
 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 {
     cpu_abort(env, "cp15 insn %08x\n", insn);
@@ -132,6 +210,8 @@
 
 #else
 
+extern int semihosting_enabled;
+
 /* Map CPU modes onto saved register banks.  */
 static inline int bank_number (int mode)
 {
@@ -202,6 +282,22 @@
             offset = 4;
         break;
     case EXCP_SWI:
+        if (semihosting_enabled) {
+            /* Check for semihosting interrupt.  */
+            if (env->thumb) {
+                mask = lduw_code(env->regs[15] - 2) & 0xff;
+            } else {
+                mask = ldl_code(env->regs[15] - 4) & 0xffffff;
+            }
+            /* Only intercept calls from privileged modes, to provide some
+               semblance of security.  */
+            if (((mask == 0x123456 && !env->thumb)
+                    || (mask == 0xab && env->thumb))
+                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
+                env->regs[0] = do_arm_semihosting(env);
+                return;
+            }
+        }
         new_mode = ARM_CPU_MODE_SVC;
         addr = 0x08;
         mask = CPSR_I;
@@ -306,13 +402,67 @@
         address += env->cp15.c13_fcse;
 
     if ((env->cp15.c1_sys & 1) == 0) {
-        /* MMU diusabled.  */
+        /* MMU/MPU disabled.  */
         *phys_ptr = address;
         *prot = PAGE_READ | PAGE_WRITE;
+    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
+        int n;
+        uint32_t mask;
+        uint32_t base;
+
+        *phys_ptr = address;
+        for (n = 7; n >= 0; n--) {
+            base = env->cp15.c6_region[n];
+            if ((base & 1) == 0)
+                continue;
+            mask = 1 << ((base >> 1) & 0x1f);
+            /* Keep this shift separate from the above to avoid an
+               (undefined) << 32.  */
+            mask = (mask << 1) - 1;
+            if (((base ^ address) & ~mask) == 0)
+                break;
+        }
+        if (n < 0)
+            return 2;
+
+        if (access_type == 2) {
+            mask = env->cp15.c5_insn;
+        } else {
+            mask = env->cp15.c5_data;
+        }
+        mask = (mask >> (n * 4)) & 0xf;
+        switch (mask) {
+        case 0:
+            return 1;
+        case 1:
+            if (is_user)
+              return 1;
+            *prot = PAGE_READ | PAGE_WRITE;
+            break;
+        case 2:
+            *prot = PAGE_READ;
+            if (!is_user)
+                *prot |= PAGE_WRITE;
+            break;
+        case 3:
+            *prot = PAGE_READ | PAGE_WRITE;
+            break;
+        case 5:
+            if (is_user)
+                return 1;
+            *prot = PAGE_READ;
+            break;
+        case 6:
+            *prot = PAGE_READ;
+            break;
+        default:
+            /* Bad permission.  */
+            return 1;
+        }
     } else {
         /* Pagetable walk.  */
         /* Lookup l1 descriptor.  */
-        table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
+        table = (env->cp15.c2_base & 0xffffc000) | ((address >> 18) & 0x3ffc);
         desc = ldl_phys(table);
         type = (desc & 3);
         domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
@@ -333,9 +483,15 @@
             phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
             ap = (desc >> 10) & 3;
             code = 13;
-        } else if (type == 1) {
+        } else {
             /* Lookup l2 entry.  */
-            table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
+            if (type == 1) {
+                /* Coarse pagetable.  */
+                table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
+            } else {
+                /* Fine pagetable.  */
+                table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
+            }
             desc = ldl_phys(table);
             switch (desc & 3) {
             case 0: /* Page translation fault.  */
@@ -367,11 +523,7 @@
                 abort();
             }
             code = 15;
-        } else {
-            code = 15;
-            goto do_fault;
         }
-
         *prot = check_ap(env, ap, domain, access_type, is_user);
         if (!*prot) {
             /* Access permission fault.  */
@@ -412,7 +564,7 @@
     return 1;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     uint32_t phys_addr;
     int prot;
@@ -428,51 +580,73 @@
 
 void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
 {
-    int op1 = (insn >> 8) & 0xf;
-    int op2 = (insn >> 5) & 7;
-    int reg = (insn >> 16) & 0xf;
-    int crm = insn & 0xf;
+    int cp_num = (insn >> 8) & 0xf;
+    int cp_info = (insn >> 5) & 7;
+    int src = (insn >> 16) & 0xf;
+    int operand = insn & 0xf;
 
-    /* On XScale coprocessors [0, 13] have to be enabled in CPAR.  */
-    if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-        if (op1 <= 13 && (env->cp15.c15_cpar & (1 << op1)) == 0)
-            return;	/* Permission Denied */
-    }
-
-    if (env->cp[op1].cp_write)
-        env->cp[op1].cp_write(env->cp[op1].opaque, op2, reg, crm, val);
+    if (env->cp[cp_num].cp_write)
+        env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
+                                 cp_info, src, operand, val);
 }
 
 uint32_t helper_get_cp(CPUState *env, uint32_t insn)
 {
-    int op1 = (insn >> 8) & 0xf;
-    int op2 = (insn >> 5) & 7;
-    int reg = (insn >> 16) & 0xf;
-    int crm = insn & 0xf;
+    int cp_num = (insn >> 8) & 0xf;
+    int cp_info = (insn >> 5) & 7;
+    int dest = (insn >> 16) & 0xf;
+    int operand = insn & 0xf;
 
-    /* On XScale coprocessors [0, 13] have to be enabled in CPAR.  */
-    if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-        if (op1 <= 13 && (env->cp15.c15_cpar & (1 << op1)) == 0)
-            return 0;	/* Permission Denied */
+    if (env->cp[cp_num].cp_read)
+        return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
+                                       cp_info, dest, operand);
+    return 0;
+}
+
+/* Return basic MPU access permission bits.  */
+static uint32_t simple_mpu_ap_bits(uint32_t val)
+{
+    uint32_t ret;
+    uint32_t mask;
+    int i;
+    ret = 0;
+    mask = 3;
+    for (i = 0; i < 16; i += 2) {
+        ret |= (val >> i) & mask;
+        mask <<= 2;
     }
+    return ret;
+}
 
-    if (env->cp[op1].cp_read)
-        return env->cp[op1].cp_read(env->cp[op1].opaque, op2, reg, crm);
-    return 0;
+/* Pad basic MPU access permission bits to extended format.  */
+static uint32_t extended_mpu_ap_bits(uint32_t val)
+{
+    uint32_t ret;
+    uint32_t mask;
+    int i;
+    ret = 0;
+    mask = 3;
+    for (i = 0; i < 16; i += 2) {
+        ret |= (val & mask) << i;
+        mask <<= 2;
+    }
+    return ret;
 }
 
 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
 {
     uint32_t op2;
+    uint32_t crm;
 
     op2 = (insn >> 5) & 7;
+    crm = insn & 0xf;
     switch ((insn >> 16) & 0xf) {
     case 0: /* ID codes.  */
         goto bad_reg;
     case 1: /* System configuration.  */
         switch (op2) {
         case 0:
-            if (!arm_feature(env, ARM_FEATURE_XSCALE) || (insn & 0xf) == 0)
+            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
                 env->cp15.c1_sys = val;
             /* ??? Lots of these bits are not implemented.  */
             /* This may enable/disable the MMU, so do a TLB flush.  */
@@ -493,38 +667,71 @@
             goto bad_reg;
         }
         break;
-    case 2: /* MMU Page table control.  */
-        env->cp15.c2 = val;
+    case 2: /* MMU Page table control / MPU cache control.  */
+        if (arm_feature(env, ARM_FEATURE_MPU)) {
+            switch (op2) {
+            case 0:
+                env->cp15.c2_data = val;
+                break;
+            case 1:
+                env->cp15.c2_insn = val;
+                break;
+            default:
+                goto bad_reg;
+            }
+        } else {
+            env->cp15.c2_base = val;
+        }
         break;
-    case 3: /* MMU Domain access control.  */
+    case 3: /* MMU Domain access control / MPU write buffer control.  */
         env->cp15.c3 = val;
         break;
     case 4: /* Reserved.  */
         goto bad_reg;
-    case 5: /* MMU Fault status.  */
+    case 5: /* MMU Fault status / MPU access permission.  */
         switch (op2) {
         case 0:
+            if (arm_feature(env, ARM_FEATURE_MPU))
+                val = extended_mpu_ap_bits(val);
             env->cp15.c5_data = val;
             break;
         case 1:
+            if (arm_feature(env, ARM_FEATURE_MPU))
+                val = extended_mpu_ap_bits(val);
             env->cp15.c5_insn = val;
             break;
-        default:
-            goto bad_reg;
-        }
-        break;
-    case 6: /* MMU Fault address.  */
-        switch (op2) {
-        case 0:
-            env->cp15.c6_data = val;
+        case 2:
+            if (!arm_feature(env, ARM_FEATURE_MPU))
+                goto bad_reg;
+            env->cp15.c5_data = val;
             break;
-        case 1:
-            env->cp15.c6_insn = val;
+        case 3:
+            if (!arm_feature(env, ARM_FEATURE_MPU))
+                goto bad_reg;
+            env->cp15.c5_insn = val;
             break;
         default:
             goto bad_reg;
         }
         break;
+    case 6: /* MMU Fault address / MPU base/size.  */
+        if (arm_feature(env, ARM_FEATURE_MPU)) {
+            if (crm >= 8)
+                goto bad_reg;
+            env->cp15.c6_region[crm] = val;
+        } else {
+            switch (op2) {
+            case 0:
+                env->cp15.c6_data = val;
+                break;
+            case 1:
+                env->cp15.c6_insn = val;
+                break;
+            default:
+                goto bad_reg;
+            }
+        }
+        break;
     case 7: /* Cache control.  */
         /* No cache, so nothing to do.  */
         break;
@@ -551,14 +758,23 @@
             goto bad_reg;
         }
         break;
-    case 9: /* Cache lockdown.  */
-        switch (op2) {
-        case 0:
-            env->cp15.c9_data = val;
+    case 9:
+        switch (crm) {
+        case 0: /* Cache lockdown.  */
+            switch (op2) {
+            case 0:
+                env->cp15.c9_data = val;
+                break;
+            case 1:
+                env->cp15.c9_insn = val;
+                break;
+            default:
+                goto bad_reg;
+            }
             break;
-        case 1:
-            env->cp15.c9_insn = val;
-            break;
+        case 1: /* TCM memory region registers.  */
+            /* Not implemented.  */
+            goto bad_reg;
         default:
             goto bad_reg;
         }
@@ -566,7 +782,6 @@
     case 10: /* MMU TLB lockdown.  */
         /* ??? TLB lockdown not implemented.  */
         break;
-    case 11: /* TCM DMA control.  */
     case 12: /* Reserved.  */
         goto bad_reg;
     case 13: /* Process ID.  */
@@ -574,6 +789,8 @@
             op2 = 0;
         switch (op2) {
         case 0:
+            if (!arm_feature(env, ARM_FEATURE_MPU))
+                goto bad_reg;
             /* Unlike real hardware the qemu TLB uses virtual addresses,
                not modified virtual addresses, so this causes a TLB flush.
              */
@@ -583,7 +800,8 @@
             break;
         case 1:
             /* This changes the ASID, so do a TLB flush.  */
-            if (env->cp15.c13_context != val)
+            if (env->cp15.c13_context != val
+                && !arm_feature(env, ARM_FEATURE_MPU))
               tlb_flush(env, 0);
             env->cp15.c13_context = val;
             break;
@@ -595,8 +813,10 @@
         goto bad_reg;
     case 15: /* Implementation specific.  */
         if (arm_feature(env, ARM_FEATURE_XSCALE)) {
-            if (op2 == 0 && (insn & 0xf) == 1) {
-                env->cp15.c15_cpar = val & 0x3fff;
+            if (op2 == 0 && crm == 1) {
+                /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
+                tb_flush(env);
+                env->cp15.c15_cpar = (val & 0x3fff) | 2;
                 break;
             }
             goto bad_reg;
@@ -624,7 +844,6 @@
         case 2: /* TCM status.  */
             if (arm_feature(env, ARM_FEATURE_S3C))
                 return env->cp15.c0_cpuid;
-            return 0;
         }
     case 1: /* System configuration.  */
         switch (op2) {
@@ -641,34 +860,67 @@
         default:
             goto bad_reg;
         }
-    case 2: /* MMU Page table control.  */
-        return env->cp15.c2;
-    case 3: /* MMU Domain access control.  */
+    case 2: /* MMU Page table control / MPU cache control.  */
+        if (arm_feature(env, ARM_FEATURE_MPU)) {
+            switch (op2) {
+            case 0:
+                return env->cp15.c2_data;
+                break;
+            case 1:
+                return env->cp15.c2_insn;
+                break;
+            default:
+                goto bad_reg;
+            }
+        } else {
+            return env->cp15.c2_base;
+        }
+    case 3: /* MMU Domain access control / MPU write buffer control.  */
         return env->cp15.c3;
     case 4: /* Reserved.  */
         goto bad_reg;
-    case 5: /* MMU Fault status.  */
+    case 5: /* MMU Fault status / MPU access permission.  */
         switch (op2) {
         case 0:
+            if (arm_feature(env, ARM_FEATURE_MPU))
+                return simple_mpu_ap_bits(env->cp15.c5_data);
             return env->cp15.c5_data;
         case 1:
+            if (arm_feature(env, ARM_FEATURE_MPU))
+                return simple_mpu_ap_bits(env->cp15.c5_data);
             return env->cp15.c5_insn;
+        case 2:
+            if (!arm_feature(env, ARM_FEATURE_MPU))
+                goto bad_reg;
+            return env->cp15.c5_data;
+        case 3:
+            if (!arm_feature(env, ARM_FEATURE_MPU))
+                goto bad_reg;
+            return env->cp15.c5_insn;
         default:
             goto bad_reg;
         }
-    case 6: /* MMU Fault address.  */
-        switch (op2) {
-        case 0:
-            return env->cp15.c6_data;
-        case 1:
-            /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
-               do any harm.  */
-            return env->cp15.c6_insn;
-        default:
-            goto bad_reg;
+    case 6: /* MMU Fault address / MPU base/size.  */
+        if (arm_feature(env, ARM_FEATURE_MPU)) {
+            int n;
+            n = (insn & 0xf);
+            if (n >= 8)
+                goto bad_reg;
+            return env->cp15.c6_region[n];
+        } else {
+            switch (op2) {
+            case 0:
+                return env->cp15.c6_data;
+            case 1:
+                /* Arm9 doesn't have an IFAR, but implementing it anyway
+                   shouldn't do any harm.  */
+                return env->cp15.c6_insn;
+            default:
+                goto bad_reg;
+            }
         }
     case 7: /* Cache control.  */
-        /* ??? This is for test, clean and invaidate operations that set the
+        /* ??? This is for test, clean and invalidate operations that set the
            Z flag.  We can't represent N = Z = 1, so it also clears
            the N flag.  Oh well.  */
         env->NZF = 0;

Modified: trunk/src/host/qemu-neo1973/target-arm/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1214,691 +1214,5 @@
     T0 = T2;
 }
 
-/* iwMMXt support.  */
-
-#define M1	env->iwmmxt.regs[PARAM1]
-
-/* iwMMXt macros extracted from GNU gdb.  */
-
-/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations.  */
-#define SIMD8_SET( v, n, b)	((v != 0) << ((((b) + 1) * 4) + (n)))
-#define SIMD16_SET(v, n, h)	((v != 0) << ((((h) + 1) * 8) + (n)))
-#define SIMD32_SET(v, n, w)	((v != 0) << ((((w) + 1) * 16) + (n)))
-#define SIMD64_SET(v, n)	((v != 0) << (32 + (n)))
-/* Flags to pass as "n" above.  */
-#define SIMD_NBIT	-1
-#define SIMD_ZBIT	-2
-#define SIMD_CBIT	-3
-#define SIMD_VBIT	-4
-/* Various status bit macros.  */
-#define NBIT8(x)	((x) & 0x80)
-#define NBIT16(x)	((x) & 0x8000)
-#define NBIT32(x)	((x) & 0x80000000)
-#define NBIT64(x)	((x) & 0x8000000000000000ULL)
-#define ZBIT8(x)	(((x) & 0xff) == 0)
-#define ZBIT16(x)	(((x) & 0xffff) == 0)
-#define ZBIT32(x)	(((x) & 0xffffffff) == 0)
-#define ZBIT64(x)	(x == 0)
-/* Sign extension macros.  */
-#define EXTEND8H(a)	((a) & 0x80 ? ((a) | 0xff00) : (a))
-#define EXTEND8(a)	((a) & 0x80 ? ((a) | 0xffffff00) : (a))
-#define EXTEND16(a)	((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
-#define EXTEND32(a)	((a) & 0x80000000ULL ? \
-    ((a) | 0xffffffff00000000ULL) : (a))
-
-void OPPROTO op_iwmmxt_movl_T0_T1_wRn(void)
-{
-    T0 = M1 & ~(uint32_t) 0;
-    T1 = M1 >> 32;
-}
-
-void OPPROTO op_iwmmxt_movl_wRn_T0_T1(void)
-{
-    M1 = ((uint64_t) T1 << 32) | T0;
-}
-
-void OPPROTO op_iwmmxt_movq_M0_wRn(void)
-{
-    M0 = M1;
-}
-
-void OPPROTO op_iwmmxt_orq_M0_wRn(void)
-{
-    M0 |= M1;
-}
-
-void OPPROTO op_iwmmxt_andq_M0_wRn(void)
-{
-    M0 &= M1;
-}
-
-void OPPROTO op_iwmmxt_xorq_M0_wRn(void)
-{
-    M0 ^= M1;
-}
-
-void OPPROTO op_iwmmxt_maddsq_M0_wRn(void)
-{
-    M0 = ((
-            EXTEND16((M0 >> 0) & 0xffff) * EXTEND16((M1 >> 0) & 0xffff) +
-            EXTEND16((M0 >> 16) & 0xffff) * EXTEND16((M1 >> 16) & 0xffff)
-        ) & 0xffffffff) | ((
-            EXTEND16((M0 >> 32) & 0xffff) * EXTEND16((M1 >> 32) & 0xffff) +
-            EXTEND16((M0 >> 48) & 0xffff) * EXTEND16((M1 >> 48) & 0xffff)
-        ) << 32);
-}
-
-void OPPROTO op_iwmmxt_madduq_M0_wRn(void)
-{
-    M0 = ((
-            ((M0 >> 0) & 0xffff) * ((M1 >> 0) & 0xffff) +
-            ((M0 >> 16) & 0xffff) * ((M1 >> 16) & 0xffff)
-        ) & 0xffffffff) | ((
-            ((M0 >> 32) & 0xffff) * ((M1 >> 32) & 0xffff) +
-            ((M0 >> 48) & 0xffff) * ((M1 >> 48) & 0xffff)
-        ) << 32);
-}
-
-void OPPROTO op_iwmmxt_sadb_M0_wRn(void)
-{
-#define abs(x) (((x) >= 0) ? x : -x)
-#define SADB(SHR) abs((int) ((M0 >> SHR) & 0xff) - (int) ((M1 >> SHR) & 0xff))
-    M0 =
-        SADB(0) + SADB(8) + SADB(16) + SADB(24) +
-        SADB(32) + SADB(40) + SADB(48) + SADB(56);
-#undef SADB
-}
-
-void OPPROTO op_iwmmxt_sadw_M0_wRn(void)
-{
-#define SADW(SHR) \
-    abs((int) ((M0 >> SHR) & 0xffff) - (int) ((M1 >> SHR) & 0xffff))
-    M0 = SADW(0) + SADW(16) + SADW(32) + SADW(48);
-#undef SADW
-}
-
-void OPPROTO op_iwmmxt_addl_M0_wRn(void)
-{
-    M0 += env->iwmmxt.regs[PARAM1] & 0xffffffff;
-}
-
-void OPPROTO op_iwmmxt_mulsw_M0_wRn(void)
-{
-#define MULS(SHR) (((( \
-        EXTEND16((M0 >> SHR) & 0xffff) * EXTEND16((M1 >> SHR) & 0xffff) \
-    ) >> PARAM2) & 0xffff) << SHR)
-    M0 = MULS(0) | MULS(16) | MULS(32) | MULS(48);
-#undef MULS
-}
-
-void OPPROTO op_iwmmxt_muluw_M0_wRn(void)
-{
-#define MULU(SHR) (((( \
-        ((M0 >> SHR) & 0xffff) * ((M1 >> SHR) & 0xffff) \
-    ) >> PARAM2) & 0xffff) << SHR)
-    M0 = MULU(0) | MULU(16) | MULU(32) | MULU(48);
-#undef MULU
-}
-
-void OPPROTO op_iwmmxt_macsw_M0_wRn(void)
-{
-#define MACS(SHR) ( \
-        (int32_t) EXTEND16((M0 >> SHR) & 0xffff) * \
-        (int32_t) EXTEND16((M1 >> SHR) & 0xffff)) 
-    M0 = (int64_t) (MACS(0) + MACS(16) + MACS(32) + MACS(48));
-#undef MACS
-}
-
-void OPPROTO op_iwmmxt_macuw_M0_wRn(void)
-{
-#define MACU(SHR) ( \
-        (uint32_t) ((M0 >> SHR) & 0xffff) * \
-        (uint32_t) ((M1 >> SHR) & 0xffff)) 
-    M0 = MACU(0) + MACU(16) + MACU(32) + MACU(48);
-#undef MACU
-}
-
-void OPPROTO op_iwmmxt_addsq_M0_wRn(void)
-{
-    M0 = (int64_t) M0 + (int64_t) M1;
-}
-
-void OPPROTO op_iwmmxt_adduq_M0_wRn(void)
-{
-    M0 += M1;
-}
-
-void OPPROTO op_iwmmxt_movq_wRn_M0(void)
-{
-    M1 = M0;
-}
-
-void OPPROTO op_iwmmxt_movl_wCx_T0(void)
-{
-    env->iwmmxt.cregs[PARAM1] = T0;
-}
-
-void OPPROTO op_iwmmxt_movl_T0_wCx(void)
-{
-    T0 = env->iwmmxt.cregs[PARAM1];
-}
-
-void OPPROTO op_iwmmxt_movl_T1_wCx(void)
-{
-    T1 = env->iwmmxt.cregs[PARAM1];
-}
-
-void OPPROTO op_iwmmxt_set_mup(void)
-{
-    env->iwmmxt.cregs[ARM_IWMMXT_wCon] |= 2;
-}
-
-void OPPROTO op_iwmmxt_set_cup(void)
-{
-    env->iwmmxt.cregs[ARM_IWMMXT_wCon] |= 1;
-}
-
-void OPPROTO op_iwmmxt_setpsr_nz(void)
-{
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        SIMD64_SET((M0 == 0), SIMD_ZBIT) |
-        SIMD64_SET((M0 & (1ULL << 63)), SIMD_NBIT);
-}
-
-void OPPROTO op_iwmmxt_negq_M0(void)
-{
-    M0 = ~M0;
-}
-
-#define NZBIT8(x, i) \
-    SIMD8_SET(NBIT8((x) & 0xff), SIMD_NBIT, i) | \
-    SIMD8_SET(ZBIT8((x) & 0xff), SIMD_ZBIT, i)
-#define NZBIT16(x, i) \
-    SIMD16_SET(NBIT16((x) & 0xffff), SIMD_NBIT, i) | \
-    SIMD16_SET(ZBIT16((x) & 0xffff), SIMD_ZBIT, i)
-#define NZBIT32(x, i) \
-    SIMD32_SET(NBIT32((x) & 0xffffffff), SIMD_NBIT, i) | \
-    SIMD32_SET(ZBIT32((x) & 0xffffffff), SIMD_ZBIT, i)
-#define NZBIT64(x) \
-    SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
-    SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
-#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)			\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, b_M0_wRn))(void)	\
-{								\
-    M0 =							\
-        (((M0 >> SH0) & 0xff) << 0) | (((M1 >> SH0) & 0xff) << 8) |	\
-        (((M0 >> SH1) & 0xff) << 16) | (((M1 >> SH1) & 0xff) << 24) |	\
-        (((M0 >> SH2) & 0xff) << 32) | (((M1 >> SH2) & 0xff) << 40) |	\
-        (((M0 >> SH3) & 0xff) << 48) | (((M1 >> SH3) & 0xff) << 56);	\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |		\
-        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |		\
-        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |		\
-        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, w_M0_wRn))(void)	\
-{								\
-    M0 =							\
-        (((M0 >> SH0) & 0xffff) << 0) |				\
-        (((M1 >> SH0) & 0xffff) << 16) |			\
-        (((M0 >> SH2) & 0xffff) << 32) |			\
-        (((M1 >> SH2) & 0xffff) << 48);				\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 16, 1) |		\
-        NZBIT8(M0 >> 32, 2) | NZBIT8(M0 >> 48, 3);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, l_M0_wRn))(void)	\
-{								\
-    M0 =							\
-        (((M0 >> SH0) & 0xffffffff) << 0) |			\
-        (((M1 >> SH0) & 0xffffffff) << 32);			\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, ub_M0))(void)	\
-{								\
-    M0 =							\
-        (((M0 >> SH0) & 0xff) << 0) |				\
-        (((M0 >> SH1) & 0xff) << 16) |				\
-        (((M0 >> SH2) & 0xff) << 32) |				\
-        (((M0 >> SH3) & 0xff) << 48);				\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, uw_M0))(void)	\
-{								\
-    M0 =							\
-        (((M0 >> SH0) & 0xffff) << 0) |				\
-        (((M0 >> SH2) & 0xffff) << 32);				\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, ul_M0))(void)	\
-{								\
-    M0 = (((M0 >> SH0) & 0xffffffff) << 0);			\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0 >> 0);	\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, sb_M0))(void)	\
-{								\
-    M0 =							\
-        (EXTEND8H((M0 >> SH0) & 0xff) << 0) |			\
-        (EXTEND8H((M0 >> SH1) & 0xff) << 16) |			\
-        (EXTEND8H((M0 >> SH2) & 0xff) << 32) |			\
-        (EXTEND8H((M0 >> SH3) & 0xff) << 48);			\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, sw_M0))(void)	\
-{								\
-    M0 =							\
-        (EXTEND16((M0 >> SH0) & 0xffff) << 0) |			\
-        (EXTEND16((M0 >> SH2) & 0xffff) << 32);			\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
-}								\
-void OPPROTO glue(op_iwmmxt_unpack, glue(S, sl_M0))(void)	\
-{								\
-    M0 = EXTEND32((M0 >> SH0) & 0xffffffff);			\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0 >> 0);	\
-}
-IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
-IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
-
-#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)				\
-void OPPROTO glue(op_iwmmxt_, glue(SUFF, b_M0_wRn))(void)	\
-{								\
-    M0 =							\
-        CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |		\
-        CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) |		\
-        CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) |		\
-        CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff);		\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |		\
-        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |		\
-        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |		\
-        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);		\
-}								\
-void OPPROTO glue(op_iwmmxt_, glue(SUFF, w_M0_wRn))(void)	\
-{								\
-    M0 = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |	\
-        CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);	\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
-}								\
-void OPPROTO glue(op_iwmmxt_, glue(SUFF, l_M0_wRn))(void)	\
-{								\
-    M0 = CMP(0, Tl, O, 0xffffffff) |				\
-        CMP(32, Tl, O, 0xffffffff);				\
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
-}
-#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((M0 >> SHR) & MASK) OPER \
-            (TYPE) ((M1 >> SHR) & MASK)) ? (uint64_t) MASK : 0) << SHR)
-IWMMXT_OP_CMP(cmpeq, uint8_t, uint16_t, uint32_t, ==)
-IWMMXT_OP_CMP(cmpgts, int8_t, int16_t, int32_t, >)
-IWMMXT_OP_CMP(cmpgtu, uint8_t, uint16_t, uint32_t, >)
-#undef CMP
-#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((M0 >> SHR) & MASK) OPER \
-            (TYPE) ((M1 >> SHR) & MASK)) ? M0 : M1) & ((uint64_t) MASK << SHR))
-IWMMXT_OP_CMP(mins, int8_t, int16_t, int32_t, <)
-IWMMXT_OP_CMP(minu, uint8_t, uint16_t, uint32_t, <)
-IWMMXT_OP_CMP(maxs, int8_t, int16_t, int32_t, >)
-IWMMXT_OP_CMP(maxu, uint8_t, uint16_t, uint32_t, >)
-#undef CMP
-#define CMP(SHR, TYPE, OPER, MASK) ((uint64_t) (((TYPE) ((M0 >> SHR) & MASK) \
-            OPER (TYPE) ((M1 >> SHR) & MASK)) & MASK) << SHR)
-IWMMXT_OP_CMP(subn, uint8_t, uint16_t, uint32_t, -)
-IWMMXT_OP_CMP(addn, uint8_t, uint16_t, uint32_t, +)
-#undef CMP
-/* TODO Signed- and Unsigned-Saturation */
-#define CMP(SHR, TYPE, OPER, MASK) ((uint64_t) (((TYPE) ((M0 >> SHR) & MASK) \
-            OPER (TYPE) ((M1 >> SHR) & MASK)) & MASK) << SHR)
-IWMMXT_OP_CMP(subu, uint8_t, uint16_t, uint32_t, -)
-IWMMXT_OP_CMP(addu, uint8_t, uint16_t, uint32_t, +)
-IWMMXT_OP_CMP(subs, int8_t, int16_t, int32_t, -)
-IWMMXT_OP_CMP(adds, int8_t, int16_t, int32_t, +)
-#undef CMP
-#undef IWMMXT_OP_CMP
-
-void OPPROTO op_iwmmxt_avgb_M0_wRn(void)
-{
-#define AVGB(SHR) ((( \
-        ((M0 >> SHR) & 0xff) + ((M1 >> SHR) & 0xff) + PARAM2) >> 1) << SHR)
-    M0 =
-        AVGB(0) | AVGB(8) | AVGB(16) | AVGB(24) |
-        AVGB(32) | AVGB(40) | AVGB(48) | AVGB(56);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        SIMD8_SET(ZBIT8((M0 >> 0) & 0xff), SIMD_ZBIT, 0) |
-        SIMD8_SET(ZBIT8((M0 >> 8) & 0xff), SIMD_ZBIT, 1) |
-        SIMD8_SET(ZBIT8((M0 >> 16) & 0xff), SIMD_ZBIT, 2) |
-        SIMD8_SET(ZBIT8((M0 >> 24) & 0xff), SIMD_ZBIT, 3) |
-        SIMD8_SET(ZBIT8((M0 >> 32) & 0xff), SIMD_ZBIT, 4) |
-        SIMD8_SET(ZBIT8((M0 >> 40) & 0xff), SIMD_ZBIT, 5) |
-        SIMD8_SET(ZBIT8((M0 >> 48) & 0xff), SIMD_ZBIT, 6) |
-        SIMD8_SET(ZBIT8((M0 >> 56) & 0xff), SIMD_ZBIT, 7);
-#undef AVGB
-}
-
-void OPPROTO op_iwmmxt_avgw_M0_wRn(void)
-{
-#define AVGW(SHR) ((( \
-        ((M0 >> SHR) & 0xffff) + ((M1 >> SHR) & 0xffff) + PARAM2) >> 1) << SHR)
-    M0 = AVGW(0) | AVGW(16) | AVGW(32) | AVGW(48);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        SIMD16_SET(ZBIT16((M0 >> 0) & 0xffff), SIMD_ZBIT, 0) |
-        SIMD16_SET(ZBIT16((M0 >> 16) & 0xffff), SIMD_ZBIT, 1) |
-        SIMD16_SET(ZBIT16((M0 >> 32) & 0xffff), SIMD_ZBIT, 2) |
-        SIMD16_SET(ZBIT16((M0 >> 48) & 0xffff), SIMD_ZBIT, 3);
-#undef AVGW
-}
-
-void OPPROTO op_iwmmxt_msadb_M0_wRn(void)
-{
-    M0 = ((((M0 >> 0) & 0xffff) * ((M1 >> 0) & 0xffff) +
-           ((M0 >> 16) & 0xffff) * ((M1 >> 16) & 0xffff)) & 0xffffffff) |
-         ((((M0 >> 32) & 0xffff) * ((M1 >> 32) & 0xffff) +
-           ((M0 >> 48) & 0xffff) * ((M1 >> 48) & 0xffff)) << 32);
-}
-
-void OPPROTO op_iwmmxt_align_M0_T0_wRn(void)
-{
-    M0 >>= T0 << 3;
-    M0 |= M1 << (64 - (T0 << 3));
-}
-
-void OPPROTO op_iwmmxt_insr_M0_T0_T1(void)
-{
-    M0 &= ~((uint64_t) T1 << PARAM1);
-    M0 |= (uint64_t) (T0 & T1) << PARAM1;
-}
-
-void OPPROTO op_iwmmxt_extrsb_T0_M0(void)
-{
-    T0 = EXTEND8((M0 >> PARAM1) & 0xff);
-}
-
-void OPPROTO op_iwmmxt_extrsw_T0_M0(void)
-{
-    T0 = EXTEND16((M0 >> PARAM1) & 0xffff);
-}
-
-void OPPROTO op_iwmmxt_extru_T0_M0_T1(void)
-{
-    T0 = (M0 >> PARAM1) & T1;
-}
-
-void OPPROTO op_iwmmxt_bcstb_M0_T0(void)
-{
-    T0 &= 0xff;
-    M0 =
-        ((uint64_t) T0 << 0) | ((uint64_t) T0 << 8) |
-        ((uint64_t) T0 << 16) | ((uint64_t) T0 << 24) |
-        ((uint64_t) T0 << 32) | ((uint64_t) T0 << 40) |
-        ((uint64_t) T0 << 48) | ((uint64_t) T0 << 56);
-}
-
-void OPPROTO op_iwmmxt_bcstw_M0_T0(void)
-{
-    T0 &= 0xffff;
-    M0 =
-        ((uint64_t) T0 << 0) | ((uint64_t) T0 << 16) |
-        ((uint64_t) T0 << 32) | ((uint64_t) T0 << 48);
-}
-
-void OPPROTO op_iwmmxt_bcstl_M0_T0(void)
-{
-    M0 = ((uint64_t) T0 << 0) | ((uint64_t) T0 << 32);
-}
-
-void OPPROTO op_iwmmxt_addcb_M0(void)
-{
-    M0 =
-        ((M0 >> 0) & 0xff) + ((M0 >> 8) & 0xff) +
-        ((M0 >> 16) & 0xff) + ((M0 >> 24) & 0xff) +
-        ((M0 >> 32) & 0xff) + ((M0 >> 40) & 0xff) +
-        ((M0 >> 48) & 0xff) + ((M0 >> 56) & 0xff);
-}
-
-void OPPROTO op_iwmmxt_addcw_M0(void)
-{
-    M0 =
-        ((M0 >> 0) & 0xffff) + ((M0 >> 16) & 0xffff) +
-        ((M0 >> 32) & 0xffff) + ((M0 >> 48) & 0xffff);
-}
-
-void OPPROTO op_iwmmxt_addcl_M0(void)
-{
-    M0 = (M0 & 0xffffffff) + (M0 >> 32);
-}
-
-void OPPROTO op_iwmmxt_msbb_T0_M0(void)
-{
-    T0 =
-        ((M0 >> 7) & 0x01) | ((M0 >> 14) & 0x02) |
-        ((M0 >> 21) & 0x04) | ((M0 >> 28) & 0x08) |
-        ((M0 >> 35) & 0x10) | ((M0 >> 42) & 0x20) |
-        ((M0 >> 49) & 0x40) | ((M0 >> 56) & 0x80);
-}
-
-void OPPROTO op_iwmmxt_msbw_T0_M0(void)
-{
-    T0 =
-        ((M0 >> 15) & 0x01) | ((M0 >> 30) & 0x02) |
-        ((M0 >> 45) & 0x04) | ((M0 >> 52) & 0x08);
-}
-
-void OPPROTO op_iwmmxt_msbl_T0_M0(void)
-{
-    T0 = ((M0 >> 31) & 0x01) | ((M0 >> 62) & 0x02);
-}
-
-void OPPROTO op_iwmmxt_srlw_M0_T0(void)
-{
-    M0 =
-        (((M0 & (0xffffll << 0)) >> T0) & (0xffffll << 0)) |
-        (((M0 & (0xffffll << 16)) >> T0) & (0xffffll << 16)) |
-        (((M0 & (0xffffll << 32)) >> T0) & (0xffffll << 32)) |
-        (((M0 & (0xffffll << 48)) >> T0) & (0xffffll << 48));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_srll_M0_T0(void)
-{
-    M0 =
-        ((M0 & (0xffffffffll << 0)) >> T0) |
-        ((M0 >> T0) & (0xffffffffll << 32));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-void OPPROTO op_iwmmxt_srlq_M0_T0(void)
-{
-    M0 >>= T0;
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
-}
-
-void OPPROTO op_iwmmxt_sllw_M0_T0(void)
-{
-    M0 =
-        (((M0 & (0xffffll << 0)) << T0) & (0xffffll << 0)) |
-        (((M0 & (0xffffll << 16)) << T0) & (0xffffll << 16)) |
-        (((M0 & (0xffffll << 32)) << T0) & (0xffffll << 32)) |
-        (((M0 & (0xffffll << 48)) << T0) & (0xffffll << 48));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_slll_M0_T0(void)
-{
-    M0 =
-        ((M0 << T0) & (0xffffffffll << 0)) |
-        ((M0 & (0xffffffffll << 32)) << T0);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-void OPPROTO op_iwmmxt_sllq_M0_T0(void)
-{
-    M0 <<= T0;
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
-}
-
-void OPPROTO op_iwmmxt_sraw_M0_T0(void)
-{
-    M0 =
-        (((EXTEND16(M0 >> 0) >> T0) & 0xffff) << 0) |
-        (((EXTEND16(M0 >> 16) >> T0) & 0xffff) << 16) |
-        (((EXTEND16(M0 >> 32) >> T0) & 0xffff) << 32) |
-        (((EXTEND16(M0 >> 48) >> T0) & 0xffff) << 48);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_sral_M0_T0(void)
-{
-    M0 =
-        (((EXTEND32(M0 >> 0) >> T0) & 0xffffffff) << 0) |
-        (((EXTEND32(M0 >> 32) >> T0) & 0xffffffff) << 32);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-void OPPROTO op_iwmmxt_sraq_M0_T0(void)
-{
-    M0 = (int64_t) M0 >> T0;
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
-}
-
-void OPPROTO op_iwmmxt_rorw_M0_T0(void)
-{
-    M0 =
-        ((((M0 & (0xffffll << 0)) >> T0) |
-          ((M0 & (0xffffll << 0)) << (16 - T0))) & (0xffffll << 0)) |
-        ((((M0 & (0xffffll << 16)) >> T0) |
-          ((M0 & (0xffffll << 16)) << (16 - T0))) & (0xffffll << 16)) |
-        ((((M0 & (0xffffll << 32)) >> T0) |
-          ((M0 & (0xffffll << 32)) << (16 - T0))) & (0xffffll << 32)) |
-        ((((M0 & (0xffffll << 48)) >> T0) |
-          ((M0 & (0xffffll << 48)) << (16 - T0))) & (0xffffll << 48));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_rorl_M0_T0(void)
-{
-    M0 =
-        ((M0 & (0xffffffffll << 0)) >> T0) |
-        ((M0 >> T0) & (0xffffffffll << 32)) |
-        ((M0 << (32 - T0)) & (0xffffffffll << 0)) |
-        ((M0 & (0xffffffffll << 32)) << (32 - T0));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-void OPPROTO op_iwmmxt_rorq_M0_T0(void)
-{
-    M0 = (M0 >> T0) | (M0 << (64 - T0));
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
-}
-
-void OPPROTO op_iwmmxt_shufh_M0_T0(void)
-{
-    M0 =
-        (((M0 >> ((T0 << 4) & 0x30)) & 0xffff) << 0) |
-        (((M0 >> ((T0 << 2) & 0x30)) & 0xffff) << 16) |
-        (((M0 >> ((T0 << 0) & 0x30)) & 0xffff) << 32) |
-        (((M0 >> ((T0 >> 2) & 0x30)) & 0xffff) << 48);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-/* TODO: Unsigned-Saturation */
-void OPPROTO op_iwmmxt_packuw_M0_wRn(void)
-{
-    M0 =
-        (((M0 >> 0) & 0xff) << 0) | (((M0 >> 16) & 0xff) << 8) |
-        (((M0 >> 32) & 0xff) << 16) | (((M0 >> 48) & 0xff) << 24) |
-        (((M1 >> 0) & 0xff) << 32) | (((M1 >> 16) & 0xff) << 40) |
-        (((M1 >> 32) & 0xff) << 48) | (((M1 >> 48) & 0xff) << 56);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |
-        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |
-        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |
-        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);
-}
-
-void OPPROTO op_iwmmxt_packul_M0_wRn(void)
-{
-    M0 =
-        (((M0 >> 0) & 0xffff) << 0) | (((M0 >> 32) & 0xffff) << 16) |
-        (((M1 >> 0) & 0xffff) << 32) | (((M1 >> 32) & 0xffff) << 48);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_packuq_M0_wRn(void)
-{
-    M0 = (M0 & 0xffffffff) | ((M1 & 0xffffffff) << 32);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-/* TODO: Signed-Saturation */
-void OPPROTO op_iwmmxt_packsw_M0_wRn(void)
-{
-    M0 =
-        (((M0 >> 0) & 0xff) << 0) | (((M0 >> 16) & 0xff) << 8) |
-        (((M0 >> 32) & 0xff) << 16) | (((M0 >> 48) & 0xff) << 24) |
-        (((M1 >> 0) & 0xff) << 32) | (((M1 >> 16) & 0xff) << 40) |
-        (((M1 >> 32) & 0xff) << 48) | (((M1 >> 48) & 0xff) << 56);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |
-        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |
-        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |
-        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);
-}
-
-void OPPROTO op_iwmmxt_packsl_M0_wRn(void)
-{
-    M0 =
-        (((M0 >> 0) & 0xffff) << 0) | (((M0 >> 32) & 0xffff) << 16) |
-        (((M1 >> 0) & 0xffff) << 32) | (((M1 >> 32) & 0xffff) << 48);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
-        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
-}
-
-void OPPROTO op_iwmmxt_packsq_M0_wRn(void)
-{
-    M0 = (M0 & 0xffffffff) | ((M1 & 0xffffffff) << 32);
-    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
-        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
-}
-
-void OPPROTO op_iwmmxt_muladdsl_M0_T0_T1(void)
-{
-    M0 += EXTEND32(T0) * EXTEND32(T1);
-}
-
-void OPPROTO op_iwmmxt_muladdsw_M0_T0_T1(void)
-{
-    M0 += EXTEND32(EXTEND16((T0 >> 0) & 0xffff) *
-                   EXTEND16((T1 >> 0) & 0xffff));
-    M0 += EXTEND32(EXTEND16((T0 >> 16) & 0xffff) *
-                   EXTEND16((T1 >> 16) & 0xffff));
-}
-
-void OPPROTO op_iwmmxt_muladdswl_M0_T0_T1(void)
-{
-    M0 += EXTEND32(EXTEND16(T0 & 0xffff) * EXTEND16(T1 & 0xffff));
-}
+/* iwMMXt support */
+#include "op_iwmmxt.c"

Added: trunk/src/host/qemu-neo1973/target-arm/op_iwmmxt.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/op_iwmmxt.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/op_iwmmxt.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,707 @@
+/*
+ * iwMMXt micro operations for XScale.
+ * 
+ * Copyright (c) 2007 OpenedHand, Ltd.
+ * Written by Andrzej Zaborowski <andrew at openedhand.com>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define M1	env->iwmmxt.regs[PARAM1]
+
+/* iwMMXt macros extracted from GNU gdb.  */
+
+/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations.  */
+#define SIMD8_SET( v, n, b)	((v != 0) << ((((b) + 1) * 4) + (n)))
+#define SIMD16_SET(v, n, h)	((v != 0) << ((((h) + 1) * 8) + (n)))
+#define SIMD32_SET(v, n, w)	((v != 0) << ((((w) + 1) * 16) + (n)))
+#define SIMD64_SET(v, n)	((v != 0) << (32 + (n)))
+/* Flags to pass as "n" above.  */
+#define SIMD_NBIT	-1
+#define SIMD_ZBIT	-2
+#define SIMD_CBIT	-3
+#define SIMD_VBIT	-4
+/* Various status bit macros.  */
+#define NBIT8(x)	((x) & 0x80)
+#define NBIT16(x)	((x) & 0x8000)
+#define NBIT32(x)	((x) & 0x80000000)
+#define NBIT64(x)	((x) & 0x8000000000000000ULL)
+#define ZBIT8(x)	(((x) & 0xff) == 0)
+#define ZBIT16(x)	(((x) & 0xffff) == 0)
+#define ZBIT32(x)	(((x) & 0xffffffff) == 0)
+#define ZBIT64(x)	(x == 0)
+/* Sign extension macros.  */
+#define EXTEND8H(a)	((uint16_t) (int8_t) (a))
+#define EXTEND8(a)	((uint32_t) (int8_t) (a))
+#define EXTEND16(a)	((uint32_t) (int16_t) (a))
+#define EXTEND16S(a)	((int32_t) (int16_t) (a))
+#define EXTEND32(a)	((uint64_t) (int32_t) (a))
+
+void OPPROTO op_iwmmxt_movl_T0_T1_wRn(void)
+{
+    T0 = M1 & ~(uint32_t) 0;
+    T1 = M1 >> 32;
+}
+
+void OPPROTO op_iwmmxt_movl_wRn_T0_T1(void)
+{
+    M1 = ((uint64_t) T1 << 32) | T0;
+}
+
+void OPPROTO op_iwmmxt_movq_M0_wRn(void)
+{
+    M0 = M1;
+}
+
+void OPPROTO op_iwmmxt_orq_M0_wRn(void)
+{
+    M0 |= M1;
+}
+
+void OPPROTO op_iwmmxt_andq_M0_wRn(void)
+{
+    M0 &= M1;
+}
+
+void OPPROTO op_iwmmxt_xorq_M0_wRn(void)
+{
+    M0 ^= M1;
+}
+
+void OPPROTO op_iwmmxt_maddsq_M0_wRn(void)
+{
+    M0 = ((
+            EXTEND16S((M0 >> 0) & 0xffff) * EXTEND16S((M1 >> 0) & 0xffff) +
+            EXTEND16S((M0 >> 16) & 0xffff) * EXTEND16S((M1 >> 16) & 0xffff)
+        ) & 0xffffffff) | ((uint64_t) (
+            EXTEND16S((M0 >> 32) & 0xffff) * EXTEND16S((M1 >> 32) & 0xffff) +
+            EXTEND16S((M0 >> 48) & 0xffff) * EXTEND16S((M1 >> 48) & 0xffff)
+        ) << 32);
+}
+
+void OPPROTO op_iwmmxt_madduq_M0_wRn(void)
+{
+    M0 = ((
+            ((M0 >> 0) & 0xffff) * ((M1 >> 0) & 0xffff) +
+            ((M0 >> 16) & 0xffff) * ((M1 >> 16) & 0xffff)
+        ) & 0xffffffff) | ((
+            ((M0 >> 32) & 0xffff) * ((M1 >> 32) & 0xffff) +
+            ((M0 >> 48) & 0xffff) * ((M1 >> 48) & 0xffff)
+        ) << 32);
+}
+
+void OPPROTO op_iwmmxt_sadb_M0_wRn(void)
+{
+#define abs(x) (((x) >= 0) ? x : -x)
+#define SADB(SHR) abs((int) ((M0 >> SHR) & 0xff) - (int) ((M1 >> SHR) & 0xff))
+    M0 =
+        SADB(0) + SADB(8) + SADB(16) + SADB(24) +
+        SADB(32) + SADB(40) + SADB(48) + SADB(56);
+#undef SADB
+}
+
+void OPPROTO op_iwmmxt_sadw_M0_wRn(void)
+{
+#define SADW(SHR) \
+    abs((int) ((M0 >> SHR) & 0xffff) - (int) ((M1 >> SHR) & 0xffff))
+    M0 = SADW(0) + SADW(16) + SADW(32) + SADW(48);
+#undef SADW
+}
+
+void OPPROTO op_iwmmxt_addl_M0_wRn(void)
+{
+    M0 += env->iwmmxt.regs[PARAM1] & 0xffffffff;
+}
+
+void OPPROTO op_iwmmxt_mulsw_M0_wRn(void)
+{
+#define MULS(SHR) ((uint64_t) ((( \
+        EXTEND16S((M0 >> SHR) & 0xffff) * EXTEND16S((M1 >> SHR) & 0xffff) \
+    ) >> PARAM2) & 0xffff) << SHR)
+    M0 = MULS(0) | MULS(16) | MULS(32) | MULS(48);
+#undef MULS
+}
+
+void OPPROTO op_iwmmxt_muluw_M0_wRn(void)
+{
+#define MULU(SHR) ((uint64_t) ((( \
+        ((M0 >> SHR) & 0xffff) * ((M1 >> SHR) & 0xffff) \
+    ) >> PARAM2) & 0xffff) << SHR)
+    M0 = MULU(0) | MULU(16) | MULU(32) | MULU(48);
+#undef MULU
+}
+
+void OPPROTO op_iwmmxt_macsw_M0_wRn(void)
+{
+#define MACS(SHR) ( \
+        EXTEND16((M0 >> SHR) & 0xffff) * EXTEND16S((M1 >> SHR) & 0xffff)) 
+    M0 = (int64_t) (MACS(0) + MACS(16) + MACS(32) + MACS(48));
+#undef MACS
+}
+
+void OPPROTO op_iwmmxt_macuw_M0_wRn(void)
+{
+#define MACU(SHR) ( \
+        (uint32_t) ((M0 >> SHR) & 0xffff) * \
+        (uint32_t) ((M1 >> SHR) & 0xffff)) 
+    M0 = MACU(0) + MACU(16) + MACU(32) + MACU(48);
+#undef MACU
+}
+
+void OPPROTO op_iwmmxt_addsq_M0_wRn(void)
+{
+    M0 = (int64_t) M0 + (int64_t) M1;
+}
+
+void OPPROTO op_iwmmxt_adduq_M0_wRn(void)
+{
+    M0 += M1;
+}
+
+void OPPROTO op_iwmmxt_movq_wRn_M0(void)
+{
+    M1 = M0;
+}
+
+void OPPROTO op_iwmmxt_movl_wCx_T0(void)
+{
+    env->iwmmxt.cregs[PARAM1] = T0;
+}
+
+void OPPROTO op_iwmmxt_movl_T0_wCx(void)
+{
+    T0 = env->iwmmxt.cregs[PARAM1];
+}
+
+void OPPROTO op_iwmmxt_movl_T1_wCx(void)
+{
+    T1 = env->iwmmxt.cregs[PARAM1];
+}
+
+void OPPROTO op_iwmmxt_set_mup(void)
+{
+    env->iwmmxt.cregs[ARM_IWMMXT_wCon] |= 2;
+}
+
+void OPPROTO op_iwmmxt_set_cup(void)
+{
+    env->iwmmxt.cregs[ARM_IWMMXT_wCon] |= 1;
+}
+
+void OPPROTO op_iwmmxt_setpsr_nz(void)
+{
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        SIMD64_SET((M0 == 0), SIMD_ZBIT) |
+        SIMD64_SET((M0 & (1ULL << 63)), SIMD_NBIT);
+}
+
+void OPPROTO op_iwmmxt_negq_M0(void)
+{
+    M0 = ~M0;
+}
+
+#define NZBIT8(x, i) \
+    SIMD8_SET(NBIT8((x) & 0xff), SIMD_NBIT, i) | \
+    SIMD8_SET(ZBIT8((x) & 0xff), SIMD_ZBIT, i)
+#define NZBIT16(x, i) \
+    SIMD16_SET(NBIT16((x) & 0xffff), SIMD_NBIT, i) | \
+    SIMD16_SET(ZBIT16((x) & 0xffff), SIMD_ZBIT, i)
+#define NZBIT32(x, i) \
+    SIMD32_SET(NBIT32((x) & 0xffffffff), SIMD_NBIT, i) | \
+    SIMD32_SET(ZBIT32((x) & 0xffffffff), SIMD_ZBIT, i)
+#define NZBIT64(x) \
+    SIMD64_SET(NBIT64(x), SIMD_NBIT) | \
+    SIMD64_SET(ZBIT64(x), SIMD_ZBIT)
+#define IWMMXT_OP_UNPACK(S, SH0, SH1, SH2, SH3)			\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, b_M0_wRn))(void)	\
+{								\
+    M0 =							\
+        (((M0 >> SH0) & 0xff) << 0) | (((M1 >> SH0) & 0xff) << 8) |	\
+        (((M0 >> SH1) & 0xff) << 16) | (((M1 >> SH1) & 0xff) << 24) |	\
+        (((M0 >> SH2) & 0xff) << 32) | (((M1 >> SH2) & 0xff) << 40) |	\
+        (((M0 >> SH3) & 0xff) << 48) | (((M1 >> SH3) & 0xff) << 56);	\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |		\
+        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |		\
+        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |		\
+        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, w_M0_wRn))(void)	\
+{								\
+    M0 =							\
+        (((M0 >> SH0) & 0xffff) << 0) |				\
+        (((M1 >> SH0) & 0xffff) << 16) |			\
+        (((M0 >> SH2) & 0xffff) << 32) |			\
+        (((M1 >> SH2) & 0xffff) << 48);				\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 16, 1) |		\
+        NZBIT8(M0 >> 32, 2) | NZBIT8(M0 >> 48, 3);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, l_M0_wRn))(void)	\
+{								\
+    M0 =							\
+        (((M0 >> SH0) & 0xffffffff) << 0) |			\
+        (((M1 >> SH0) & 0xffffffff) << 32);			\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, ub_M0))(void)	\
+{								\
+    M0 =							\
+        (((M0 >> SH0) & 0xff) << 0) |				\
+        (((M0 >> SH1) & 0xff) << 16) |				\
+        (((M0 >> SH2) & 0xff) << 32) |				\
+        (((M0 >> SH3) & 0xff) << 48);				\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, uw_M0))(void)	\
+{								\
+    M0 =							\
+        (((M0 >> SH0) & 0xffff) << 0) |				\
+        (((M0 >> SH2) & 0xffff) << 32);				\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, ul_M0))(void)	\
+{								\
+    M0 = (((M0 >> SH0) & 0xffffffff) << 0);			\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0 >> 0);	\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, sb_M0))(void)	\
+{								\
+    M0 =							\
+        ((uint64_t) EXTEND8H((M0 >> SH0) & 0xff) << 0) |	\
+        ((uint64_t) EXTEND8H((M0 >> SH1) & 0xff) << 16) |	\
+        ((uint64_t) EXTEND8H((M0 >> SH2) & 0xff) << 32) |	\
+        ((uint64_t) EXTEND8H((M0 >> SH3) & 0xff) << 48);	\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, sw_M0))(void)	\
+{								\
+    M0 =							\
+        ((uint64_t) EXTEND16((M0 >> SH0) & 0xffff) << 0) |	\
+        ((uint64_t) EXTEND16((M0 >> SH2) & 0xffff) << 32);	\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
+}								\
+void OPPROTO glue(op_iwmmxt_unpack, glue(S, sl_M0))(void)	\
+{								\
+    M0 = EXTEND32((M0 >> SH0) & 0xffffffff);			\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0 >> 0);	\
+}
+IWMMXT_OP_UNPACK(l, 0, 8, 16, 24)
+IWMMXT_OP_UNPACK(h, 32, 40, 48, 56)
+
+#define IWMMXT_OP_CMP(SUFF, Tb, Tw, Tl, O)				\
+void OPPROTO glue(op_iwmmxt_, glue(SUFF, b_M0_wRn))(void)	\
+{								\
+    M0 =							\
+        CMP(0, Tb, O, 0xff) | CMP(8, Tb, O, 0xff) |		\
+        CMP(16, Tb, O, 0xff) | CMP(24, Tb, O, 0xff) |		\
+        CMP(32, Tb, O, 0xff) | CMP(40, Tb, O, 0xff) |		\
+        CMP(48, Tb, O, 0xff) | CMP(56, Tb, O, 0xff);		\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |		\
+        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |		\
+        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |		\
+        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);		\
+}								\
+void OPPROTO glue(op_iwmmxt_, glue(SUFF, w_M0_wRn))(void)	\
+{								\
+    M0 = CMP(0, Tw, O, 0xffff) | CMP(16, Tw, O, 0xffff) |	\
+        CMP(32, Tw, O, 0xffff) | CMP(48, Tw, O, 0xffff);	\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |		\
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);		\
+}								\
+void OPPROTO glue(op_iwmmxt_, glue(SUFF, l_M0_wRn))(void)	\
+{								\
+    M0 = CMP(0, Tl, O, 0xffffffff) |				\
+        CMP(32, Tl, O, 0xffffffff);				\
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =			\
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);		\
+}
+#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((M0 >> SHR) & MASK) OPER \
+            (TYPE) ((M1 >> SHR) & MASK)) ? (uint64_t) MASK : 0) << SHR)
+IWMMXT_OP_CMP(cmpeq, uint8_t, uint16_t, uint32_t, ==)
+IWMMXT_OP_CMP(cmpgts, int8_t, int16_t, int32_t, >)
+IWMMXT_OP_CMP(cmpgtu, uint8_t, uint16_t, uint32_t, >)
+#undef CMP
+#define CMP(SHR, TYPE, OPER, MASK) ((((TYPE) ((M0 >> SHR) & MASK) OPER \
+            (TYPE) ((M1 >> SHR) & MASK)) ? M0 : M1) & ((uint64_t) MASK << SHR))
+IWMMXT_OP_CMP(mins, int8_t, int16_t, int32_t, <)
+IWMMXT_OP_CMP(minu, uint8_t, uint16_t, uint32_t, <)
+IWMMXT_OP_CMP(maxs, int8_t, int16_t, int32_t, >)
+IWMMXT_OP_CMP(maxu, uint8_t, uint16_t, uint32_t, >)
+#undef CMP
+#define CMP(SHR, TYPE, OPER, MASK) ((uint64_t) (((TYPE) ((M0 >> SHR) & MASK) \
+            OPER (TYPE) ((M1 >> SHR) & MASK)) & MASK) << SHR)
+IWMMXT_OP_CMP(subn, uint8_t, uint16_t, uint32_t, -)
+IWMMXT_OP_CMP(addn, uint8_t, uint16_t, uint32_t, +)
+#undef CMP
+/* TODO Signed- and Unsigned-Saturation */
+#define CMP(SHR, TYPE, OPER, MASK) ((uint64_t) (((TYPE) ((M0 >> SHR) & MASK) \
+            OPER (TYPE) ((M1 >> SHR) & MASK)) & MASK) << SHR)
+IWMMXT_OP_CMP(subu, uint8_t, uint16_t, uint32_t, -)
+IWMMXT_OP_CMP(addu, uint8_t, uint16_t, uint32_t, +)
+IWMMXT_OP_CMP(subs, int8_t, int16_t, int32_t, -)
+IWMMXT_OP_CMP(adds, int8_t, int16_t, int32_t, +)
+#undef CMP
+#undef IWMMXT_OP_CMP
+
+void OPPROTO op_iwmmxt_avgb_M0_wRn(void)
+{
+#define AVGB(SHR) ((( \
+        ((M0 >> SHR) & 0xff) + ((M1 >> SHR) & 0xff) + PARAM2) >> 1) << SHR)
+    M0 =
+        AVGB(0) | AVGB(8) | AVGB(16) | AVGB(24) |
+        AVGB(32) | AVGB(40) | AVGB(48) | AVGB(56);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        SIMD8_SET(ZBIT8((M0 >> 0) & 0xff), SIMD_ZBIT, 0) |
+        SIMD8_SET(ZBIT8((M0 >> 8) & 0xff), SIMD_ZBIT, 1) |
+        SIMD8_SET(ZBIT8((M0 >> 16) & 0xff), SIMD_ZBIT, 2) |
+        SIMD8_SET(ZBIT8((M0 >> 24) & 0xff), SIMD_ZBIT, 3) |
+        SIMD8_SET(ZBIT8((M0 >> 32) & 0xff), SIMD_ZBIT, 4) |
+        SIMD8_SET(ZBIT8((M0 >> 40) & 0xff), SIMD_ZBIT, 5) |
+        SIMD8_SET(ZBIT8((M0 >> 48) & 0xff), SIMD_ZBIT, 6) |
+        SIMD8_SET(ZBIT8((M0 >> 56) & 0xff), SIMD_ZBIT, 7);
+#undef AVGB
+}
+
+void OPPROTO op_iwmmxt_avgw_M0_wRn(void)
+{
+#define AVGW(SHR) ((( \
+        ((M0 >> SHR) & 0xffff) + ((M1 >> SHR) & 0xffff) + PARAM2) >> 1) << SHR)
+    M0 = AVGW(0) | AVGW(16) | AVGW(32) | AVGW(48);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        SIMD16_SET(ZBIT16((M0 >> 0) & 0xffff), SIMD_ZBIT, 0) |
+        SIMD16_SET(ZBIT16((M0 >> 16) & 0xffff), SIMD_ZBIT, 1) |
+        SIMD16_SET(ZBIT16((M0 >> 32) & 0xffff), SIMD_ZBIT, 2) |
+        SIMD16_SET(ZBIT16((M0 >> 48) & 0xffff), SIMD_ZBIT, 3);
+#undef AVGW
+}
+
+void OPPROTO op_iwmmxt_msadb_M0_wRn(void)
+{
+    M0 = ((((M0 >> 0) & 0xffff) * ((M1 >> 0) & 0xffff) +
+           ((M0 >> 16) & 0xffff) * ((M1 >> 16) & 0xffff)) & 0xffffffff) |
+         ((((M0 >> 32) & 0xffff) * ((M1 >> 32) & 0xffff) +
+           ((M0 >> 48) & 0xffff) * ((M1 >> 48) & 0xffff)) << 32);
+}
+
+void OPPROTO op_iwmmxt_align_M0_T0_wRn(void)
+{
+    M0 >>= T0 << 3;
+    M0 |= M1 << (64 - (T0 << 3));
+}
+
+void OPPROTO op_iwmmxt_insr_M0_T0_T1(void)
+{
+    M0 &= ~((uint64_t) T1 << PARAM1);
+    M0 |= (uint64_t) (T0 & T1) << PARAM1;
+}
+
+void OPPROTO op_iwmmxt_extrsb_T0_M0(void)
+{
+    T0 = EXTEND8((M0 >> PARAM1) & 0xff);
+}
+
+void OPPROTO op_iwmmxt_extrsw_T0_M0(void)
+{
+    T0 = EXTEND16((M0 >> PARAM1) & 0xffff);
+}
+
+void OPPROTO op_iwmmxt_extru_T0_M0_T1(void)
+{
+    T0 = (M0 >> PARAM1) & T1;
+}
+
+void OPPROTO op_iwmmxt_bcstb_M0_T0(void)
+{
+    T0 &= 0xff;
+    M0 =
+        ((uint64_t) T0 << 0) | ((uint64_t) T0 << 8) |
+        ((uint64_t) T0 << 16) | ((uint64_t) T0 << 24) |
+        ((uint64_t) T0 << 32) | ((uint64_t) T0 << 40) |
+        ((uint64_t) T0 << 48) | ((uint64_t) T0 << 56);
+}
+
+void OPPROTO op_iwmmxt_bcstw_M0_T0(void)
+{
+    T0 &= 0xffff;
+    M0 =
+        ((uint64_t) T0 << 0) | ((uint64_t) T0 << 16) |
+        ((uint64_t) T0 << 32) | ((uint64_t) T0 << 48);
+}
+
+void OPPROTO op_iwmmxt_bcstl_M0_T0(void)
+{
+    M0 = ((uint64_t) T0 << 0) | ((uint64_t) T0 << 32);
+}
+
+void OPPROTO op_iwmmxt_addcb_M0(void)
+{
+    M0 =
+        ((M0 >> 0) & 0xff) + ((M0 >> 8) & 0xff) +
+        ((M0 >> 16) & 0xff) + ((M0 >> 24) & 0xff) +
+        ((M0 >> 32) & 0xff) + ((M0 >> 40) & 0xff) +
+        ((M0 >> 48) & 0xff) + ((M0 >> 56) & 0xff);
+}
+
+void OPPROTO op_iwmmxt_addcw_M0(void)
+{
+    M0 =
+        ((M0 >> 0) & 0xffff) + ((M0 >> 16) & 0xffff) +
+        ((M0 >> 32) & 0xffff) + ((M0 >> 48) & 0xffff);
+}
+
+void OPPROTO op_iwmmxt_addcl_M0(void)
+{
+    M0 = (M0 & 0xffffffff) + (M0 >> 32);
+}
+
+void OPPROTO op_iwmmxt_msbb_T0_M0(void)
+{
+    T0 =
+        ((M0 >> 7) & 0x01) | ((M0 >> 14) & 0x02) |
+        ((M0 >> 21) & 0x04) | ((M0 >> 28) & 0x08) |
+        ((M0 >> 35) & 0x10) | ((M0 >> 42) & 0x20) |
+        ((M0 >> 49) & 0x40) | ((M0 >> 56) & 0x80);
+}
+
+void OPPROTO op_iwmmxt_msbw_T0_M0(void)
+{
+    T0 =
+        ((M0 >> 15) & 0x01) | ((M0 >> 30) & 0x02) |
+        ((M0 >> 45) & 0x04) | ((M0 >> 52) & 0x08);
+}
+
+void OPPROTO op_iwmmxt_msbl_T0_M0(void)
+{
+    T0 = ((M0 >> 31) & 0x01) | ((M0 >> 62) & 0x02);
+}
+
+void OPPROTO op_iwmmxt_srlw_M0_T0(void)
+{
+    M0 =
+        (((M0 & (0xffffll << 0)) >> T0) & (0xffffll << 0)) |
+        (((M0 & (0xffffll << 16)) >> T0) & (0xffffll << 16)) |
+        (((M0 & (0xffffll << 32)) >> T0) & (0xffffll << 32)) |
+        (((M0 & (0xffffll << 48)) >> T0) & (0xffffll << 48));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_srll_M0_T0(void)
+{
+    M0 =
+        ((M0 & (0xffffffffll << 0)) >> T0) |
+        ((M0 >> T0) & (0xffffffffll << 32));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+void OPPROTO op_iwmmxt_srlq_M0_T0(void)
+{
+    M0 >>= T0;
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
+}
+
+void OPPROTO op_iwmmxt_sllw_M0_T0(void)
+{
+    M0 =
+        (((M0 & (0xffffll << 0)) << T0) & (0xffffll << 0)) |
+        (((M0 & (0xffffll << 16)) << T0) & (0xffffll << 16)) |
+        (((M0 & (0xffffll << 32)) << T0) & (0xffffll << 32)) |
+        (((M0 & (0xffffll << 48)) << T0) & (0xffffll << 48));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_slll_M0_T0(void)
+{
+    M0 =
+        ((M0 << T0) & (0xffffffffll << 0)) |
+        ((M0 & (0xffffffffll << 32)) << T0);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+void OPPROTO op_iwmmxt_sllq_M0_T0(void)
+{
+    M0 <<= T0;
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
+}
+
+void OPPROTO op_iwmmxt_sraw_M0_T0(void)
+{
+    M0 =
+        ((uint64_t) ((EXTEND16(M0 >> 0) >> T0) & 0xffff) << 0) |
+        ((uint64_t) ((EXTEND16(M0 >> 16) >> T0) & 0xffff) << 16) |
+        ((uint64_t) ((EXTEND16(M0 >> 32) >> T0) & 0xffff) << 32) |
+        ((uint64_t) ((EXTEND16(M0 >> 48) >> T0) & 0xffff) << 48);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_sral_M0_T0(void)
+{
+    M0 =
+        (((EXTEND32(M0 >> 0) >> T0) & 0xffffffff) << 0) |
+        (((EXTEND32(M0 >> 32) >> T0) & 0xffffffff) << 32);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+void OPPROTO op_iwmmxt_sraq_M0_T0(void)
+{
+    M0 = (int64_t) M0 >> T0;
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
+}
+
+void OPPROTO op_iwmmxt_rorw_M0_T0(void)
+{
+    M0 =
+        ((((M0 & (0xffffll << 0)) >> T0) |
+          ((M0 & (0xffffll << 0)) << (16 - T0))) & (0xffffll << 0)) |
+        ((((M0 & (0xffffll << 16)) >> T0) |
+          ((M0 & (0xffffll << 16)) << (16 - T0))) & (0xffffll << 16)) |
+        ((((M0 & (0xffffll << 32)) >> T0) |
+          ((M0 & (0xffffll << 32)) << (16 - T0))) & (0xffffll << 32)) |
+        ((((M0 & (0xffffll << 48)) >> T0) |
+          ((M0 & (0xffffll << 48)) << (16 - T0))) & (0xffffll << 48));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_rorl_M0_T0(void)
+{
+    M0 =
+        ((M0 & (0xffffffffll << 0)) >> T0) |
+        ((M0 >> T0) & (0xffffffffll << 32)) |
+        ((M0 << (32 - T0)) & (0xffffffffll << 0)) |
+        ((M0 & (0xffffffffll << 32)) << (32 - T0));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+void OPPROTO op_iwmmxt_rorq_M0_T0(void)
+{
+    M0 = (M0 >> T0) | (M0 << (64 - T0));
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(M0);
+}
+
+void OPPROTO op_iwmmxt_shufh_M0_T0(void)
+{
+    M0 =
+        (((M0 >> ((T0 << 4) & 0x30)) & 0xffff) << 0) |
+        (((M0 >> ((T0 << 2) & 0x30)) & 0xffff) << 16) |
+        (((M0 >> ((T0 << 0) & 0x30)) & 0xffff) << 32) |
+        (((M0 >> ((T0 >> 2) & 0x30)) & 0xffff) << 48);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+/* TODO: Unsigned-Saturation */
+void OPPROTO op_iwmmxt_packuw_M0_wRn(void)
+{
+    M0 =
+        (((M0 >> 0) & 0xff) << 0) | (((M0 >> 16) & 0xff) << 8) |
+        (((M0 >> 32) & 0xff) << 16) | (((M0 >> 48) & 0xff) << 24) |
+        (((M1 >> 0) & 0xff) << 32) | (((M1 >> 16) & 0xff) << 40) |
+        (((M1 >> 32) & 0xff) << 48) | (((M1 >> 48) & 0xff) << 56);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |
+        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |
+        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |
+        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);
+}
+
+void OPPROTO op_iwmmxt_packul_M0_wRn(void)
+{
+    M0 =
+        (((M0 >> 0) & 0xffff) << 0) | (((M0 >> 32) & 0xffff) << 16) |
+        (((M1 >> 0) & 0xffff) << 32) | (((M1 >> 32) & 0xffff) << 48);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_packuq_M0_wRn(void)
+{
+    M0 = (M0 & 0xffffffff) | ((M1 & 0xffffffff) << 32);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+/* TODO: Signed-Saturation */
+void OPPROTO op_iwmmxt_packsw_M0_wRn(void)
+{
+    M0 =
+        (((M0 >> 0) & 0xff) << 0) | (((M0 >> 16) & 0xff) << 8) |
+        (((M0 >> 32) & 0xff) << 16) | (((M0 >> 48) & 0xff) << 24) |
+        (((M1 >> 0) & 0xff) << 32) | (((M1 >> 16) & 0xff) << 40) |
+        (((M1 >> 32) & 0xff) << 48) | (((M1 >> 48) & 0xff) << 56);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT8(M0 >> 0, 0) | NZBIT8(M0 >> 8, 1) |
+        NZBIT8(M0 >> 16, 2) | NZBIT8(M0 >> 24, 3) |
+        NZBIT8(M0 >> 32, 4) | NZBIT8(M0 >> 40, 5) |
+        NZBIT8(M0 >> 48, 6) | NZBIT8(M0 >> 56, 7);
+}
+
+void OPPROTO op_iwmmxt_packsl_M0_wRn(void)
+{
+    M0 =
+        (((M0 >> 0) & 0xffff) << 0) | (((M0 >> 32) & 0xffff) << 16) |
+        (((M1 >> 0) & 0xffff) << 32) | (((M1 >> 32) & 0xffff) << 48);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT16(M0 >> 0, 0) | NZBIT16(M0 >> 16, 1) |
+        NZBIT16(M0 >> 32, 2) | NZBIT16(M0 >> 48, 3);
+}
+
+void OPPROTO op_iwmmxt_packsq_M0_wRn(void)
+{
+    M0 = (M0 & 0xffffffff) | ((M1 & 0xffffffff) << 32);
+    env->iwmmxt.cregs[ARM_IWMMXT_wCASF] =
+        NZBIT32(M0 >> 0, 0) | NZBIT32(M0 >> 32, 1);
+}
+
+void OPPROTO op_iwmmxt_muladdsl_M0_T0_T1(void)
+{
+    M0 += (int32_t) EXTEND32(T0) * (int32_t) EXTEND32(T1);
+}
+
+void OPPROTO op_iwmmxt_muladdsw_M0_T0_T1(void)
+{
+    M0 += EXTEND32(EXTEND16S((T0 >> 0) & 0xffff) *
+                   EXTEND16S((T1 >> 0) & 0xffff));
+    M0 += EXTEND32(EXTEND16S((T0 >> 16) & 0xffff) *
+                   EXTEND16S((T1 >> 16) & 0xffff));
+}
+
+void OPPROTO op_iwmmxt_muladdswl_M0_T0_T1(void)
+{
+    M0 += EXTEND32(EXTEND16S(T0 & 0xffff) *
+                   EXTEND16S(T1 & 0xffff));
+}

Modified: trunk/src/host/qemu-neo1973/target-arm/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-arm/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-arm/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -46,6 +46,7 @@
     struct TranslationBlock *tb;
     int singlestep_enabled;
     int thumb;
+    int is_mem;
 #if !defined(CONFIG_USER_ONLY)
     int user;
 #endif
@@ -291,6 +292,7 @@
 #define gen_ldst(name, s) gen_op_##name##_raw()
 #else
 #define gen_ldst(name, s) do { \
+    s->is_mem = 1; \
     if (IS_USER(s)) \
         gen_op_##name##_user(); \
     else \
@@ -392,9 +394,9 @@
     if (insn & (1 << 22)) {
         /* immediate */
         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
-        val += extra;
         if (!(insn & (1 << 23)))
             val = -val;
+        val += extra;
         if (val != 0)
             gen_op_addl_T1_im(val);
     } else {
@@ -501,7 +503,7 @@
     rd = (insn >> 16) & 0xf;
     gen_movl_T1_reg(s, rd);
 
-    offset = (insn & 0xff) << ((insn >> 6) & 4);
+    offset = (insn & 0xff) << ((insn >> 7) & 2);
     if (insn & (1 << 24)) {
         /* Pre indexed */
         if (insn & (1 << 23))
@@ -548,9 +550,6 @@
     int rd, wrd;
     int rdhi, rdlo, rd0, rd1, i;
 
-    if (!arm_feature(env, ARM_FEATURE_IWMMXT))
-        return 1;
-
     if ((insn & 0x0e000e00) == 0x0c000000) {
         if ((insn & 0x0fe00ff0) == 0x0c400000) {
             wrd = insn & 0xf;
@@ -1482,32 +1481,110 @@
     return 0;
 }
 
+/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
+   (ie. an undefined instruction).  */
+static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
+{
+    int acc, rd0, rd1, rdhi, rdlo;
+
+    if ((insn & 0x0ff00f10) == 0x0e200010) {
+        /* Multiply with Internal Accumulate Format */
+        rd0 = (insn >> 12) & 0xf;
+        rd1 = insn & 0xf;
+        acc = (insn >> 5) & 7;
+
+        if (acc != 0)
+            return 1;
+
+        switch ((insn >> 16) & 0xf) {
+        case 0x0:					/* MIA */
+            gen_op_movl_TN_reg[0][rd0]();
+            gen_op_movl_TN_reg[1][rd1]();
+            gen_op_iwmmxt_muladdsl_M0_T0_T1();
+            break;
+        case 0x8:					/* MIAPH */
+            gen_op_movl_TN_reg[0][rd0]();
+            gen_op_movl_TN_reg[1][rd1]();
+            gen_op_iwmmxt_muladdsw_M0_T0_T1();
+            break;
+        case 0xc:					/* MIABB */
+        case 0xd:					/* MIABT */
+        case 0xe:					/* MIATB */
+        case 0xf:					/* MIATT */
+            gen_op_movl_TN_reg[1][rd0]();
+            if (insn & (1 << 16))
+                gen_op_shrl_T1_im(16);
+            gen_op_movl_T0_T1();
+            gen_op_movl_TN_reg[1][rd1]();
+            if (insn & (1 << 17))
+                gen_op_shrl_T1_im(16);
+            gen_op_iwmmxt_muladdswl_M0_T0_T1();
+            break;
+        default:
+            return 1;
+        }
+
+        gen_op_iwmmxt_movq_wRn_M0(acc);
+        return 0;
+    }
+
+    if ((insn & 0x0fe00ff8) == 0x0c400000) {
+        /* Internal Accumulator Access Format */
+        rdhi = (insn >> 16) & 0xf;
+        rdlo = (insn >> 12) & 0xf;
+        acc = insn & 7;
+
+        if (acc != 0)
+            return 1;
+
+        if (insn & ARM_CP_RW_BIT) {			/* MRA */
+            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
+            gen_op_movl_reg_TN[0][rdlo]();
+            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
+            gen_op_andl_T0_T1();
+            gen_op_movl_reg_TN[0][rdhi]();
+        } else {					/* MAR */
+            gen_op_movl_TN_reg[0][rdlo]();
+            gen_op_movl_TN_reg[1][rdhi]();
+            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
+        }
+        return 0;
+    }
+
+    return 1;
+}
+
 /* Disassemble system coprocessor instruction.  Return nonzero if
    instruction is not defined.  */
-static int disas_cp_insn(DisasContext *s, uint32_t insn)
+static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd = (insn >> 12) & 0xf;
+    uint32_t cp = (insn >> 8) & 0xf;
     if (IS_USER(s)) {
         return 1;
     }
 
     if (insn & ARM_CP_RW_BIT) {
+        if (!env->cp[cp].cp_read)
+            return 1;
+        gen_op_movl_T0_im((uint32_t) s->pc);
+        gen_op_movl_reg_TN[0][15]();
         gen_op_movl_T0_cp(insn);
         gen_movl_reg_T0(s, rd);
     } else {
+        if (!env->cp[cp].cp_write)
+            return 1;
         gen_op_movl_T0_im((uint32_t) s->pc);
         gen_op_movl_reg_TN[0][15]();
         gen_movl_T0_reg(s, rd);
         gen_op_movl_cp_T0(insn);
-        s->is_jmp = DISAS_UPDATE;
     }
-
     return 0;
 }
 
 /* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
    instruction is not defined.  */
-static int disas_cp15_insn(DisasContext *s, uint32_t insn)
+static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
 {
     uint32_t rd;
 
@@ -1533,10 +1610,13 @@
     } else {
         gen_movl_T0_reg(s, rd);
         gen_op_movl_cp15_T0(insn);
+        /* Normally we would always end the TB here, but Linux
+         * arch/arm/mach-pxa/sleep.S expects two instructions following
+         * an MMU enable to execute from cache.  Imitate this behaviour.  */
+        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
+                (insn & 0x0fff0fff) != 0x0e010f10)
+            gen_lookup_tb(s);
     }
-#if 0
-    gen_lookup_tb(s);
-#endif
     return 0;
 }
 
@@ -2552,6 +2632,7 @@
                 }
             } else {
                 int address_offset;
+                int load;
                 /* Misc load/store */
                 rn = (insn >> 16) & 0xf;
                 rd = (insn >> 12) & 0xf;
@@ -2573,7 +2654,7 @@
                         gen_ldst(ldsw, s);
                         break;
                     }
-                    gen_movl_reg_T0(s, rd);
+                    load = 1;
                 } else if (sh & 2) {
                     /* doubleword */
                     if (sh & 1) {
@@ -2583,20 +2664,27 @@
                         gen_op_addl_T1_im(4);
                         gen_movl_T0_reg(s, rd + 1);
                         gen_ldst(stl, s);
+                        load = 0;
                     } else {
                         /* load */
                         gen_ldst(ldl, s);
                         gen_movl_reg_T0(s, rd);
                         gen_op_addl_T1_im(4);
                         gen_ldst(ldl, s);
-                        gen_movl_reg_T0(s, rd + 1);
+                        rd++;
+                        load = 1;
                     }
                     address_offset = -4;
                 } else {
                     /* store */
                     gen_movl_T0_reg(s, rd);
                     gen_ldst(stw, s);
+                    load = 0;
                 }
+                /* Perform base writeback before the loaded value to
+                   ensure correct behavior with overlapping index registers.
+                   ldrd with base writeback is is undefined if the
+                   destination and index registers overlap.  */
                 if (!(insn & (1 << 24))) {
                     gen_add_datah_offset(s, insn, address_offset);
                     gen_movl_reg_T1(s, rn);
@@ -2605,6 +2693,10 @@
                         gen_op_addl_T1_im(address_offset);
                     gen_movl_reg_T1(s, rn);
                 }
+                if (load) {
+                    /* Complete the load.  */
+                    gen_movl_reg_T0(s, rd);
+                }
             }
             break;
         case 0x4:
@@ -2629,6 +2721,7 @@
                 gen_add_data_offset(s, insn);
             if (insn & (1 << 20)) {
                 /* load */
+                s->is_mem = 1;
 #if defined(CONFIG_USER_ONLY)
                 if (insn & (1 << 22))
                     gen_op_ldub_raw();
@@ -2647,10 +2740,6 @@
                         gen_op_ldl_kernel();
                 }
 #endif
-                if (rd == 15)
-                    gen_bx(s);
-                else
-                    gen_movl_reg_T0(s, rd);
             } else {
                 /* store */
                 gen_movl_T0_reg(s, rd);
@@ -2679,6 +2768,13 @@
             } else if (insn & (1 << 21))
                 gen_movl_reg_T1(s, rn); {
             }
+            if (insn & (1 << 20)) {
+                /* Complete the load.  */
+                if (rd == 15)
+                    gen_bx(s);
+                else
+                    gen_movl_reg_T0(s, rd);
+            }
             break;
         case 0x08:
         case 0x09:
@@ -2816,12 +2912,18 @@
                 goto illegal_op;
             switch (op1) {
             case 0 ... 1:
-                if (disas_iwmmxt_insn(env, s, insn))
+                if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
+                    if (disas_iwmmxt_insn(env, s, insn))
+                        goto illegal_op;
+                } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+                    if (disas_dsp_insn(env, s, insn))
+                        goto illegal_op;
+                } else
                     goto illegal_op;
                 break;
             case 2 ... 9:
             case 12 ... 14:
-                if (disas_cp_insn(s, insn))
+                if (disas_cp_insn (env, s, insn))
                     goto illegal_op;
                 break;
             case 10:
@@ -2830,7 +2932,7 @@
                     goto illegal_op;
                 break;
             case 15:
-                if (disas_cp15_insn (s, insn))
+                if (disas_cp15_insn (env, s, insn))
                     goto illegal_op;
                 break;
             default:
@@ -3438,6 +3540,7 @@
     dc->singlestep_enabled = env->singlestep_enabled;
     dc->condjmp = 0;
     dc->thumb = env->thumb;
+    dc->is_mem = 0;
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
 #endif
@@ -3476,6 +3579,12 @@
             gen_set_label(dc->condlabel);
             dc->condjmp = 0;
         }
+        /* Terminate the TB on memory ops if watchpoints are present.  */
+        /* FIXME: This should be replacd by the deterministic execution
+         * IRQ raising bits.  */
+        if (dc->is_mem && env->nb_watchpoints)
+            break;
+
         /* Translation stops when a conditional branch is enoutered.
          * Otherwise the subsequent code could get translated several times.
          * Also stop translation when a page boundary is reached.  This
@@ -3587,8 +3696,8 @@
             cpu_fprintf(f, " ");
     }
     psr = cpsr_read(env);
-    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n", 
-                psr, 
+    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
+                psr,
                 psr & (1 << 31) ? 'N' : '-',
                 psr & (1 << 30) ? 'Z' : '-',
                 psr & (1 << 29) ? 'C' : '-',

Modified: trunk/src/host/qemu-neo1973/target-i386/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -46,7 +46,7 @@
 
 #include "softfloat.h"
 
-#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
+#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(__APPLE__)
 #define USE_CODE_COPY
 #endif
 
@@ -515,6 +515,7 @@
     uint32_t smbase;
     int interrupt_request; 
     int user_mode_only; /* user mode only simulation */
+    int old_exception;  /* exception in flight */
 
     CPU_COMMON
 
@@ -529,6 +530,7 @@
     uint32_t cpuid_xlevel;
     uint32_t cpuid_model[12];
     uint32_t cpuid_ext2_features;
+    uint32_t cpuid_apic_id;
     
 #ifdef USE_KQEMU
     int kqemu_enabled;
@@ -628,8 +630,7 @@
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
-struct siginfo;
-int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_x86_signal_handler(int host_signum, void *pinfo, 
                            void *puc);
 void cpu_x86_set_a20(CPUX86State *env, int a20_state);
 

Modified: trunk/src/host/qemu-neo1973/target-i386/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -977,7 +977,7 @@
         cpu_x86_set_cpl(env, 0);
         cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
                            0, 0xffffffff, 
-                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_G_MASK | DESC_P_MASK |
                                DESC_S_MASK |
                                DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
         cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
@@ -1028,7 +1028,7 @@
         if (dflag == 2) {
             cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
                                    0, 0xffffffff, 
-                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                                   DESC_G_MASK | DESC_P_MASK |
                                    DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                                    DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
                                    DESC_L_MASK);
@@ -1193,6 +1193,40 @@
 }
 
 /*
+ * Check nested exceptions and change to double or triple fault if
+ * needed. It should only be called, if this is not an interrupt.
+ * Returns the new exception number.
+ */
+int check_exception(int intno, int *error_code)
+{
+    char first_contributory = env->old_exception == 0 ||
+                              (env->old_exception >= 10 &&
+                               env->old_exception <= 13);
+    char second_contributory = intno == 0 ||
+                               (intno >= 10 && intno <= 13);
+
+    if (loglevel & CPU_LOG_INT)
+        fprintf(logfile, "check_exception old: %x new %x\n",
+                env->old_exception, intno);
+
+    if (env->old_exception == EXCP08_DBLE)
+        cpu_abort(env, "triple fault");
+
+    if ((first_contributory && second_contributory)
+        || (env->old_exception == EXCP0E_PAGE &&
+            (second_contributory || (intno == EXCP0E_PAGE)))) {
+        intno = EXCP08_DBLE;
+        *error_code = 0;
+    }
+
+    if (second_contributory || (intno == EXCP0E_PAGE) ||
+        (intno == EXCP08_DBLE))
+        env->old_exception = intno;
+
+    return intno;
+}
+
+/*
  * Signal an interruption. It is executed in the main CPU loop.
  * is_int is TRUE if coming from the int instruction. next_eip is the
  * EIP value AFTER the interrupt instruction. It is only relevant if
@@ -1201,6 +1235,9 @@
 void raise_interrupt(int intno, int is_int, int error_code, 
                      int next_eip_addend)
 {
+    if (!is_int)
+        intno = check_exception(intno, &error_code);
+
     env->exception_index = intno;
     env->error_code = error_code;
     env->exception_is_int = is_int;
@@ -1211,6 +1248,8 @@
 /* same as raise_exception_err, but do not restore global registers */
 static void raise_exception_err_norestore(int exception_index, int error_code)
 {
+    exception_index = check_exception(exception_index, &error_code);
+
     env->exception_index = exception_index;
     env->error_code = error_code;
     env->exception_is_int = 0;
@@ -1614,7 +1653,7 @@
         break;
     case 1:
         EAX = env->cpuid_version;
-        EBX = 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
         ECX = env->cpuid_ext_features;
         EDX = env->cpuid_features;
         break;
@@ -1825,8 +1864,11 @@
             raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
 #ifdef TARGET_X86_64
         if (env->hflags & HF_LMA_MASK) {
-            uint32_t e3;
+            uint32_t e3, e4;
             e3 = ldl_kernel(ptr + 8);
+            e4 = ldl_kernel(ptr + 12);
+            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)
+                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
             load_seg_cache_raw_dt(&env->tr, e1, e2);
             env->tr.base |= (target_ulong)e3 << 32;
         } else 
@@ -2422,12 +2464,14 @@
         if ((new_ss & 0xfffc) == 0) {
 #ifdef TARGET_X86_64
             /* NULL ss is allowed in long mode if cpl != 3*/
+            /* XXX: test CS64 ? */
             if ((env->hflags & HF_LMA_MASK) && rpl != 3) {
                 cpu_x86_load_seg_cache(env, R_SS, new_ss, 
                                        0, 0xffffffff,
                                        DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                                        DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
                                        DESC_W_MASK | DESC_A_MASK);
+                ss_e2 = DESC_B_MASK; /* XXX: should not be needed ? */
             } else 
 #endif
             {
@@ -3095,30 +3139,51 @@
     CPU86_LDouble dblq, fpsrcop, fptemp;
     CPU86_LDoubleU fpsrcop1, fptemp1;
     int expdif;
-    int q;
+    signed long long int q;
 
+    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
+        ST0 = 0.0 / 0.0; /* NaN */
+        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+        return;
+    }
+
     fpsrcop = ST0;
     fptemp = ST1;
     fpsrcop1.d = fpsrcop;
     fptemp1.d = fptemp;
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
+
+    if (expdif < 0) {
+        /* optimisation? taken from the AMD docs */
+        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+        /* ST0 is unchanged */
+        return;
+    }
+
     if (expdif < 53) {
         dblq = fpsrcop / fptemp;
-        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
-        ST0 = fpsrcop - fptemp*dblq;
-        q = (int)dblq; /* cutting off top bits is assumed here */
+        /* round dblq towards nearest integer */
+        dblq = rint(dblq);
+        ST0 = fpsrcop - fptemp * dblq;
+
+        /* convert dblq to q by truncating towards zero */
+        if (dblq < 0.0)
+           q = (signed long long int)(-dblq);
+        else
+           q = (signed long long int)dblq;
+
         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
-				/* (C0,C1,C3) <-- (q2,q1,q0) */
-        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
-        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
-        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
+                                /* (C0,C3,C1) <-- (q2,q1,q0) */
+        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
+        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
+        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
     } else {
         env->fpus |= 0x400;  /* C2 <-- 1 */
-        fptemp = pow(2.0, expdif-50);
+        fptemp = pow(2.0, expdif - 50);
         fpsrcop = (ST0 / ST1) / fptemp;
-        /* fpsrcop = integer obtained by rounding to the nearest */
-        fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
-            floor(fpsrcop): ceil(fpsrcop);
+        /* fpsrcop = integer obtained by chopping */
+        fpsrcop = (fpsrcop < 0.0) ?
+                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
         ST0 -= (ST1 * fpsrcop * fptemp);
     }
 }
@@ -3128,30 +3193,52 @@
     CPU86_LDouble dblq, fpsrcop, fptemp;
     CPU86_LDoubleU fpsrcop1, fptemp1;
     int expdif;
-    int q;
-    
-    fpsrcop = ST0;
-    fptemp = ST1;
+    signed long long int q;
+
+    if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
+       ST0 = 0.0 / 0.0; /* NaN */
+       env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+       return;
+    }
+
+    fpsrcop = (CPU86_LDouble)ST0;
+    fptemp = (CPU86_LDouble)ST1;
     fpsrcop1.d = fpsrcop;
     fptemp1.d = fptemp;
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
+
+    if (expdif < 0) {
+        /* optimisation? taken from the AMD docs */
+        env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+        /* ST0 is unchanged */
+        return;
+    }
+
     if ( expdif < 53 ) {
-        dblq = fpsrcop / fptemp;
-        dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
-        ST0 = fpsrcop - fptemp*dblq;
-        q = (int)dblq; /* cutting off top bits is assumed here */
+        dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
+        /* round dblq towards zero */
+        dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
+        ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
+
+        /* convert dblq to q by truncating towards zero */
+        if (dblq < 0.0)
+           q = (signed long long int)(-dblq);
+        else
+           q = (signed long long int)dblq;
+
         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
-				/* (C0,C1,C3) <-- (q2,q1,q0) */
-        env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
-        env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
-        env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
+                                /* (C0,C3,C1) <-- (q2,q1,q0) */
+        env->fpus |= (q & 0x4) << (8 - 2);  /* (C0) <-- q2 */
+        env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
+        env->fpus |= (q & 0x1) << (9 - 0);  /* (C1) <-- q0 */
     } else {
+        int N = 32 + (expdif % 32); /* as per AMD docs */
         env->fpus |= 0x400;  /* C2 <-- 1 */
-        fptemp = pow(2.0, expdif-50);
+        fptemp = pow(2.0, (double)(expdif - N));
         fpsrcop = (ST0 / ST1) / fptemp;
         /* fpsrcop = integer obtained by chopping */
-        fpsrcop = (fpsrcop < 0.0)?
-            -(floor(fabs(fpsrcop))): floor(fpsrcop);
+        fpsrcop = (fpsrcop < 0.0) ?
+                  -(floor(fabs(fpsrcop))) : floor(fpsrcop);
         ST0 -= (ST1 * fpsrcop * fptemp);
     }
 }
@@ -3716,14 +3803,14 @@
 
 void helper_monitor(void)
 {
-    if (ECX != 0)
+    if ((uint32_t)ECX != 0)
         raise_exception(EXCP0D_GPF);
     /* XXX: store address ? */
 }
 
 void helper_mwait(void)
 {
-    if (ECX != 0)
+    if ((uint32_t)ECX != 0)
         raise_exception(EXCP0D_GPF);
     /* XXX: not complete but not completely erroneous */
     if (env->cpu_index != 0 || env->next_cpu != NULL) {

Modified: trunk/src/host/qemu-neo1973/target-i386/helper2.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -578,7 +578,7 @@
     return 1;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
@@ -670,7 +670,7 @@
 #endif
         {
             /* XXX: load them when cr3 is loaded ? */
-            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
+            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & 
                 env->a20_mask;
             pdpe = ldq_phys(pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK)) {
@@ -765,7 +765,7 @@
         uint32_t pde;
 
         /* page directory entry */
-        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & 
+        pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & 
             env->a20_mask;
         pde = ldl_phys(pde_addr);
         if (!(pde & PG_PRESENT_MASK)) {
@@ -876,7 +876,7 @@
     return 1;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     uint32_t pde_addr, pte_addr;
     uint32_t pde, pte, paddr, page_offset, page_size;
@@ -910,7 +910,7 @@
         } else 
 #endif
         {
-            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & 
+            pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & 
                 env->a20_mask;
             pdpe = ldl_phys(pdpe_addr);
             if (!(pdpe & PG_PRESENT_MASK))
@@ -940,7 +940,7 @@
             page_size = 4096;
         } else {
             /* page directory entry */
-            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask;
+            pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & env->a20_mask;
             pde = ldl_phys(pde_addr);
             if (!(pde & PG_PRESENT_MASK)) 
                 return -1;

Modified: trunk/src/host/qemu-neo1973/target-i386/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -788,7 +788,7 @@
 
 void OPPROTO op_movswl_EAX_AX(void)
 {
-    EAX = (int16_t)EAX;
+    EAX = (uint32_t)((int16_t)EAX);
 }
 
 #ifdef TARGET_X86_64
@@ -810,7 +810,7 @@
 
 void OPPROTO op_movslq_EDX_EAX(void)
 {
-    EDX = (int32_t)EAX >> 31;
+    EDX = (uint32_t)((int32_t)EAX >> 31);
 }
 
 void OPPROTO op_movswl_DX_AX(void)

Modified: trunk/src/host/qemu-neo1973/target-i386/ops_sse.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/ops_sse.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/ops_sse.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -558,6 +558,25 @@
     T0 = s->L(0);
 }
 
+#ifdef TARGET_X86_64
+void OPPROTO glue(op_movq_mm_T0, SUFFIX) (void)
+{
+    Reg *d;
+    d = (Reg *)((char *)env + PARAM1);
+    d->Q(0) = T0;
+#if SHIFT == 1
+    d->Q(1) = 0;
+#endif
+}
+
+void OPPROTO glue(op_movq_T0_mm, SUFFIX) (void)
+{
+    Reg *s;
+    s = (Reg *)((char *)env + PARAM1);
+    T0 = s->Q(0);
+}
+#endif
+
 #if SHIFT == 0
 void OPPROTO glue(op_pshufw, SUFFIX) (void)
 {

Modified: trunk/src/host/qemu-neo1973/target-i386/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2621,12 +2621,28 @@
             gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg]));
             break;
         case 0x6e: /* movd mm, ea */
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
-            gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_op_movq_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+            } else 
+#endif
+            {
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_op_movl_mm_T0_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+            }
             break;
         case 0x16e: /* movd xmm, ea */
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
-            gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 0);
+                gen_op_movq_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+            } else 
+#endif
+            {
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 0);
+                gen_op_movl_mm_T0_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+            }
             break;
         case 0x6f: /* movq mm, ea */
             if (mod != 3) {
@@ -2750,12 +2766,28 @@
                         offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
             break;
         case 0x7e: /* movd ea, mm */
-            gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_op_movq_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+            } else 
+#endif
+            {
+                gen_op_movl_T0_mm_mmx(offsetof(CPUX86State,fpregs[reg].mmx));
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+            }
             break;
         case 0x17e: /* movd ea, xmm */
-            gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
-            gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+#ifdef TARGET_X86_64
+            if (s->dflag == 2) {
+                gen_op_movq_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+                gen_ldst_modrm(s, modrm, OT_QUAD, OR_TMP0, 1);
+            } else 
+#endif
+            {
+                gen_op_movl_T0_mm_xmm(offsetof(CPUX86State,xmm_regs[reg]));
+                gen_ldst_modrm(s, modrm, OT_LONG, OR_TMP0, 1);
+            }
             break;
         case 0x27e: /* movq xmm, ea */
             if (mod != 3) {
@@ -3765,6 +3797,7 @@
         mod = (modrm >> 6) & 3;
         if (mod == 3)
             goto illegal_op;
+        gen_jmp_im(pc_start - s->cs_base);
         if (s->cc_op != CC_OP_DYNAMIC)
             gen_op_set_cc_op(s->cc_op);
         gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);

Modified: trunk/src/host/qemu-neo1973/target-m68k/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-m68k/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -97,8 +97,7 @@
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
-struct siginfo;
-int cpu_m68k_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_m68k_signal_handler(int host_signum, void *pinfo, 
                            void *puc);
 void cpu_m68k_flush_flags(CPUM68KState *, int);
 

Modified: trunk/src/host/qemu-neo1973/target-m68k/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-m68k/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-m68k/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2551,8 +2551,9 @@
 #endif
 
 /* generate intermediate code for basic block 'tb'.  */
-int gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
-                                   int search_pc)
+static inline int
+gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+                               int search_pc)
 {
     DisasContext dc1, *dc = &dc1;
     uint16_t *gen_opc_end;
@@ -2737,7 +2738,7 @@
 }
 
 /* ??? */
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }

Added: trunk/src/host/qemu-neo1973/target-mips/TODO
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/TODO	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/TODO	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,33 @@
+Unsolved issues/bugs in the mips/mipsel backend
+-----------------------------------------------
+
+General
+-------
+- [ls][dw][lr] report broken (aligned) BadVAddr
+- Missing per-CPU instruction decoding, currently all implemented
+  instructions are regarded as valid
+- Applications running on top of a emulated Linux segfault sometimes
+  when the Qemu FPU emulation is disabled. Also gdb inside the emulated
+  system does not work. Both problems are caused by insufficient
+  handling of self-modifying code.
+- Floating point exception emulation is incomplete.
+
+MIPS64
+------
+- No 64bit TLB support
+- 64bit FPU not fully implemented
+- 64bit mul/div handling broken
+
+"Generic" 4Kc system emulation
+------------------------------
+- Doesn't correspond to any real hardware.
+
+PICA 61 system emulation
+------------------------
+- No framebuffer support yet.
+
+MALTA system emulation
+----------------------
+- We fake firmware support instead of doing the real thing
+- Real firmware falls over when trying to init RAM, presumably due
+  to lacking system controller emulation.

Modified: trunk/src/host/qemu-neo1973/target-mips/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -12,23 +12,16 @@
 
 // uint_fast8_t and uint_fast16_t not in <sys/int_types.h>
 // XXX: move that elsewhere
-#if defined(HOST_SOLARIS) && SOLARISREV < 10
+#if defined(HOST_SOLARIS) && HOST_SOLARIS < 10
 typedef unsigned char           uint_fast8_t;
 typedef unsigned int            uint_fast16_t;
 #endif
 
-/* target_ulong size spec */
-#ifdef MIPS_HAS_MIPS64
-#define TLSZ "%016llx"
-#else
-#define TLSZ "%08x"
-#endif
-
 typedef union fpr_t fpr_t;
 union fpr_t {
     float64  fd;   /* ieee double precision */
     float32  fs[2];/* ieee single precision */
-    uint64_t d;    /* binary single fixed-point */
+    uint64_t d;    /* binary double fixed-point */
     uint32_t w[2]; /* binary single fixed-point */
 };
 /* define FP_ENDIAN_IDX to access the same location
@@ -44,8 +37,7 @@
 typedef struct tlb_t tlb_t;
 struct tlb_t {
     target_ulong VPN;
-    target_ulong end;
-    target_ulong end2;
+    uint32_t PageMask;
     uint_fast8_t ASID;
     uint_fast16_t G:1;
     uint_fast16_t C0:3;
@@ -70,61 +62,63 @@
     target_ulong t2;
 #endif
     target_ulong HI, LO;
-    uint32_t DCR; /* ? */
-#if defined(MIPS_USES_FPU)
     /* Floating point registers */
-    fpr_t fpr[16];
-#define FPR(cpu, n) ((fpr_t*)&(cpu)->fpr[(n) / 2])
-#define FPR_FD(cpu, n) (FPR(cpu, n)->fd)
-#define FPR_FS(cpu, n) (FPR(cpu, n)->fs[((n) & 1) ^ FP_ENDIAN_IDX])
-#define FPR_D(cpu, n)  (FPR(cpu, n)->d)
-#define FPR_W(cpu, n)  (FPR(cpu, n)->w[((n) & 1) ^ FP_ENDIAN_IDX])
-
+    fpr_t fpr[32];
 #ifndef USE_HOST_FLOAT_REGS
     fpr_t ft0;
     fpr_t ft1;
     fpr_t ft2;
 #endif
     float_status fp_status;
-    /* fpu implementation/revision register */
+    /* fpu implementation/revision register (fir) */
     uint32_t fcr0;
+#define FCR0_F64 22
+#define FCR0_L 21
+#define FCR0_W 20
+#define FCR0_3D 19
+#define FCR0_PS 18
+#define FCR0_D 17
+#define FCR0_S 16
+#define FCR0_PRID 8
+#define FCR0_REV 0
     /* fcsr */
     uint32_t fcr31;
-#define SET_FP_COND(reg)     do { (reg) |= (1<<23); } while(0)
-#define CLEAR_FP_COND(reg)   do { (reg) &= ~(1<<23); } while(0)
-#define IS_FP_COND_SET(reg)  (((reg) & (1<<23)) != 0)
-#define GET_FP_CAUSE(reg)    (((reg) >> 12) & 0x3f)
-#define GET_FP_ENABLE(reg)   (((reg) >>  7) & 0x1f)
-#define GET_FP_FLAGS(reg)    (((reg) >>  2) & 0x1f)
-#define SET_FP_CAUSE(reg,v)  do { (reg) = ((reg) & ~(0x3f << 12)) | ((v) << 12); } while(0)
-#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f <<  7)) | ((v) << 7); } while(0)
-#define SET_FP_FLAGS(reg,v)  do { (reg) = ((reg) & ~(0x1f <<  2)) | ((v) << 2); } while(0)
+#define SET_FP_COND(num,env)     do { (env->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
+#define CLEAR_FP_COND(num,env)   do { (env->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23))); } while(0)
+#define IS_FP_COND_SET(num,env)  (((env->fcr31) & ((num) ? (1 << ((num) + 24)) : (1 << ((num) + 23)))) != 0)
+#define GET_FP_CAUSE(reg)        (((reg) >> 12) & 0x3f)
+#define GET_FP_ENABLE(reg)       (((reg) >>  7) & 0x1f)
+#define GET_FP_FLAGS(reg)        (((reg) >>  2) & 0x1f)
+#define SET_FP_CAUSE(reg,v)      do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
+#define SET_FP_ENABLE(reg,v)     do { (reg) = ((reg) & ~(0x1f <<  7)) | ((v & 0x1f) << 7); } while(0)
+#define SET_FP_FLAGS(reg,v)      do { (reg) = ((reg) & ~(0x1f <<  2)) | ((v & 0x1f) << 2); } while(0)
+#define UPDATE_FP_FLAGS(reg,v)   do { (reg) |= ((v & 0x1f) << 2); } while(0)
 #define FP_INEXACT        1
 #define FP_UNDERFLOW      2
 #define FP_OVERFLOW       4
 #define FP_DIV0           8
 #define FP_INVALID        16
 #define FP_UNIMPLEMENTED  32
-		
-#endif
+
 #if defined(MIPS_USES_R4K_TLB)
     tlb_t tlb[MIPS_TLB_MAX];
     uint32_t tlb_in_use;
+    uint32_t nb_tlb;
 #endif
-    uint32_t CP0_index;
-    uint32_t CP0_random;
-    uint64_t CP0_EntryLo0;
-    uint64_t CP0_EntryLo1;
-    uint64_t CP0_Context;
-    uint32_t CP0_PageMask;
-    uint32_t CP0_PageGrain;
-    uint32_t CP0_Wired;
-    uint32_t CP0_HWREna;
+    int32_t CP0_Index;
+    int32_t CP0_Random;
+    target_ulong CP0_EntryLo0;
+    target_ulong CP0_EntryLo1;
+    target_ulong CP0_Context;
+    int32_t CP0_PageMask;
+    int32_t CP0_PageGrain;
+    int32_t CP0_Wired;
+    int32_t CP0_HWREna;
     target_ulong CP0_BadVAddr;
-    uint32_t CP0_Count;
-    uint64_t CP0_EntryHi;
-    uint32_t CP0_Compare;
-    uint32_t CP0_Status;
+    int32_t CP0_Count;
+    target_ulong CP0_EntryHi;
+    int32_t CP0_Compare;
+    int32_t CP0_Status;
 #define CP0St_CU3   31
 #define CP0St_CU2   30
 #define CP0St_CU1   29
@@ -147,9 +141,10 @@
 #define CP0St_ERL   2
 #define CP0St_EXL   1
 #define CP0St_IE    0
-    uint32_t CP0_IntCtl;
-    uint32_t CP0_SRSCtl;
-    uint32_t CP0_Cause;
+    int32_t CP0_IntCtl;
+    int32_t CP0_SRSCtl;
+    int32_t CP0_SRSMap;
+    int32_t CP0_Cause;
 #define CP0Ca_BD   31
 #define CP0Ca_TI   30
 #define CP0Ca_CE   28
@@ -158,11 +153,12 @@
 #define CP0Ca_IV   23
 #define CP0Ca_WP   22
 #define CP0Ca_IP    8
+#define CP0Ca_IP_mask 0x0000FF00
 #define CP0Ca_EC    2
     target_ulong CP0_EPC;
-    uint32_t CP0_PRid;
-    target_ulong CP0_EBase;
-    uint32_t CP0_Config0;
+    int32_t CP0_PRid;
+    int32_t CP0_EBase;
+    int32_t CP0_Config0;
 #define CP0C0_M    31
 #define CP0C0_K23  28
 #define CP0C0_KU   25
@@ -175,7 +171,7 @@
 #define CP0C0_MT   7
 #define CP0C0_VI   3
 #define CP0C0_K0   0
-    uint32_t CP0_Config1;
+    int32_t CP0_Config1;
 #define CP0C1_M    31
 #define CP0C1_MMU  25
 #define CP0C1_IS   22
@@ -191,7 +187,7 @@
 #define CP0C1_CA   2
 #define CP0C1_EP   1
 #define CP0C1_FP   0
-    uint32_t CP0_Config2;
+    int32_t CP0_Config2;
 #define CP0C2_M    31
 #define CP0C2_TU   28
 #define CP0C2_TS   24
@@ -201,7 +197,7 @@
 #define CP0C2_SS   8
 #define CP0C2_SL   4
 #define CP0C2_SA   0
-    uint32_t CP0_Config3;
+    int32_t CP0_Config3;
 #define CP0C3_M    31
 #define CP0C3_DSPP 10
 #define CP0C3_LPA  7
@@ -211,12 +207,14 @@
 #define CP0C3_MT   2
 #define CP0C3_SM   1
 #define CP0C3_TL   0
+    int32_t CP0_Config6;
+    int32_t CP0_Config7;
     target_ulong CP0_LLAddr;
-    uint32_t CP0_WatchLo;
-    uint32_t CP0_WatchHi;
-    uint32_t CP0_XContext;
-    uint32_t CP0_Framemask;
-    uint32_t CP0_Debug;
+    target_ulong CP0_WatchLo;
+    int32_t CP0_WatchHi;
+    target_ulong CP0_XContext;
+    int32_t CP0_Framemask;
+    int32_t CP0_Debug;
 #define CPDB_DBD   31
 #define CP0DB_DM   30
 #define CP0DB_LSNM 28
@@ -236,13 +234,13 @@
 #define CP0DB_DBp  1
 #define CP0DB_DSS  0
     target_ulong CP0_DEPC;
-    uint32_t CP0_Performance0;
-    uint32_t CP0_TagLo;
-    uint32_t CP0_DataLo;
-    uint32_t CP0_TagHi;
-    uint32_t CP0_DataHi;
+    int32_t CP0_Performance0;
+    int32_t CP0_TagLo;
+    int32_t CP0_DataLo;
+    int32_t CP0_TagHi;
+    int32_t CP0_DataHi;
     target_ulong CP0_ErrorEPC;
-    uint32_t CP0_DESAVE;
+    int32_t CP0_DESAVE;
     /* Qemu */
     int interrupt_request;
     jmp_buf jmp_env;
@@ -254,8 +252,6 @@
 #define MIPS_HFLAG_TMASK  0x007F
 #define MIPS_HFLAG_MODE   0x001F /* execution modes                    */
 #define MIPS_HFLAG_UM     0x0001 /* user mode                          */
-#define MIPS_HFLAG_ERL    0x0002 /* Error mode                         */
-#define MIPS_HFLAG_EXL    0x0004 /* Exception mode                     */
 #define MIPS_HFLAG_DM     0x0008 /* Debug mode                         */
 #define MIPS_HFLAG_SM     0x0010 /* Supervisor mode                    */
 #define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
@@ -275,7 +271,14 @@
 
     int SYNCI_Step; /* Address step size for SYNCI */
     int CCRes; /* Cycle count resolution/divisor */
+    int Status_rw_bitmask; /* Read/write bits in CP0_Status */
 
+#if defined(CONFIG_USER_ONLY)
+    target_ulong tls_value;
+#else
+    void *irq[8];
+#endif
+
     CPU_COMMON
 
     int ram_size;
@@ -286,6 +289,11 @@
     struct QEMUTimer *timer; /* Internal timer */
 };
 
+typedef struct mips_def_t mips_def_t;
+int mips_find_by_name (const unsigned char *name, mips_def_t **def);
+void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
+int cpu_mips_register (CPUMIPSState *env, mips_def_t *def);
+
 #include "cpu-all.h"
 
 /* Memory access type :
@@ -327,10 +335,11 @@
     EXCP_RI,
     EXCP_OVERFLOW,
     EXCP_TRAP,
+    EXCP_FPE,
     EXCP_DDBS,
     EXCP_DWATCH,
-    EXCP_LAE,
-    EXCP_SAE, /* 24 */
+    EXCP_LAE, /* 24 */
+    EXCP_SAE,
     EXCP_LTLBL,
     EXCP_TLBL,
     EXCP_TLBS,

Modified: trunk/src/host/qemu-neo1973/target-mips/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -6,25 +6,18 @@
 #include "config.h"
 #include "mips-defs.h"
 #include "dyngen-exec.h"
+#include "cpu-defs.h"
 
 register struct CPUMIPSState *env asm(AREG0);
 
-#if defined (USE_64BITS_REGS)
-typedef int64_t host_int_t;
-typedef uint64_t host_uint_t;
-#else
-typedef int32_t host_int_t;
-typedef uint32_t host_uint_t;
-#endif
-
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 #define T0 (env->t0)
 #define T1 (env->t1)
 #define T2 (env->t2)
 #else
-register host_uint_t T0 asm(AREG1);
-register host_uint_t T1 asm(AREG2);
-register host_uint_t T2 asm(AREG3);
+register target_ulong T0 asm(AREG1);
+register target_ulong T1 asm(AREG2);
+register target_ulong T2 asm(AREG3);
 #endif
 
 #if defined (USE_HOST_FLOAT_REGS)
@@ -36,12 +29,18 @@
 #define FST0 (env->ft0.fs[FP_ENDIAN_IDX])
 #define FST1 (env->ft1.fs[FP_ENDIAN_IDX])
 #define FST2 (env->ft2.fs[FP_ENDIAN_IDX])
+#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX])
+#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX])
+#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX])
 #define DT0 (env->ft0.d)
 #define DT1 (env->ft1.d)
 #define DT2 (env->ft2.d)
 #define WT0 (env->ft0.w[FP_ENDIAN_IDX])
 #define WT1 (env->ft1.w[FP_ENDIAN_IDX])
 #define WT2 (env->ft2.w[FP_ENDIAN_IDX])
+#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX])
+#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX])
+#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX])
 #endif
 
 #if defined (DEBUG_OP)
@@ -65,7 +64,7 @@
 {
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 void do_dsll (void);
 void do_dsll32 (void);
@@ -82,6 +81,9 @@
 #endif
 #endif
 
+#if HOST_LONG_BITS < 64
+void do_div (void);
+#endif
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 void do_mult (void);
 void do_multu (void);
@@ -89,10 +91,12 @@
 void do_maddu (void);
 void do_msub (void);
 void do_msubu (void);
+#endif
+#ifdef TARGET_MIPS64
 void do_ddiv (void);
+#if TARGET_LONG_BITS > HOST_LONG_BITS
 void do_ddivu (void);
 #endif
-#ifdef MIPS_HAS_MIPS64
 void do_dmult (void);
 void do_dmultu (void);
 #endif
@@ -105,18 +109,16 @@
 void do_tlbwr (void);
 void do_tlbp (void);
 void do_tlbr (void);
-#ifdef MIPS_USES_FPU
 void dump_fpu(CPUState *env);
 void fpu_dump_state(CPUState *env, FILE *f, 
                     int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags);
-#endif
 void dump_sc (void);
 void do_lwl_raw (uint32_t);
 void do_lwr_raw (uint32_t);
 uint32_t do_swl_raw (uint32_t);
 uint32_t do_swr_raw (uint32_t);
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 void do_ldl_raw (uint64_t);
 void do_ldr_raw (uint64_t);
 uint64_t do_sdl_raw (uint64_t);
@@ -131,7 +133,7 @@
 uint32_t do_swl_kernel (uint32_t);
 uint32_t do_swr_user (uint32_t);
 uint32_t do_swr_kernel (uint32_t);
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 void do_ldl_user (uint64_t);
 void do_ldl_kernel (uint64_t);
 void do_ldr_user (uint64_t);
@@ -154,6 +156,7 @@
 void cpu_loop_exit(void);
 void do_raise_exception_err (uint32_t exception, int error_code);
 void do_raise_exception (uint32_t exception);
+void do_raise_exception_direct_err (uint32_t exception, int error_code);
 void do_raise_exception_direct (uint32_t exception);
 
 void cpu_dump_state(CPUState *env, FILE *f, 
@@ -164,6 +167,7 @@
 uint32_t cpu_mips_get_count (CPUState *env);
 void cpu_mips_store_count (CPUState *env, uint32_t value);
 void cpu_mips_store_compare (CPUState *env, uint32_t value);
+void cpu_mips_update_irq (CPUState *env);
 void cpu_mips_clock_init (CPUState *env);
 void cpu_mips_tlb_flush (CPUState *env, int flush_global);
 

Modified: trunk/src/host/qemu-neo1973/target-mips/fop_template.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/fop_template.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/fop_template.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -19,75 +19,103 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#if defined(SFREG)
+#if defined(FREG)
 
-#define OP_WLOAD_FREG(treg, tregname, SFREG)      \
-    void glue(glue(op_load_fpr_,tregname), SFREG) (void) \
-    {                                                   \
-        treg = FPR_W(env, SFREG);     \
-        RETURN();                                       \
+#define OP_WLOAD_FREG(treg, tregname, FREG)              \
+    void glue(glue(op_load_fpr_,tregname), FREG) (void)  \
+    {                                                    \
+        treg = env->fpr[FREG].fs[FP_ENDIAN_IDX];         \
+        RETURN();                                        \
     }
 
-#define OP_WSTORE_FREG(treg, tregname, SFREG)            \
-    void glue(glue(op_store_fpr_,tregname), SFREG) (void)\
-    {                                                   \
-        FPR_W(env, SFREG) = treg;     \
-        RETURN();                                       \
+#define OP_WSTORE_FREG(treg, tregname, FREG)             \
+    void glue(glue(op_store_fpr_,tregname), FREG) (void) \
+    {                                                    \
+        env->fpr[FREG].fs[FP_ENDIAN_IDX] = treg;         \
+        RETURN();                                        \
     }
 
-/* WT0 = SFREG.w: op_load_fpr_WT0_fprSFREG */
-OP_WLOAD_FREG(WT0, WT0_fpr, SFREG)
-/* SFREG.w = WT0: op_store_fpr_WT0_fprSFREG */
-OP_WSTORE_FREG(WT0, WT0_fpr, SFREG)
+/* WT0 = FREG.w: op_load_fpr_WT0_fprFREG */
+OP_WLOAD_FREG(WT0, WT0_fpr, FREG)
+/* FREG.w = WT0: op_store_fpr_WT0_fprFREG */
+OP_WSTORE_FREG(WT0, WT0_fpr, FREG)
 
-OP_WLOAD_FREG(WT1, WT1_fpr, SFREG)
-OP_WSTORE_FREG(WT1, WT1_fpr, SFREG)
+OP_WLOAD_FREG(WT1, WT1_fpr, FREG)
+OP_WSTORE_FREG(WT1, WT1_fpr, FREG)
 
-OP_WLOAD_FREG(WT2, WT2_fpr, SFREG)
-OP_WSTORE_FREG(WT2, WT2_fpr, SFREG)
+OP_WLOAD_FREG(WT2, WT2_fpr, FREG)
+OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
 
-#endif
+#define OP_DLOAD_FREG(treg, tregname, FREG)              \
+    void glue(glue(op_load_fpr_,tregname), FREG) (void)  \
+    {                                                    \
+        if (env->CP0_Status & (1 << CP0St_FR))           \
+            treg = env->fpr[FREG].fd;                    \
+        else                                             \
+            treg = (uint64_t)(env->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \
+                   env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \
+        RETURN();                                        \
+    }
 
-#if defined(DFREG)
+#define OP_DSTORE_FREG(treg, tregname, FREG)             \
+    void glue(glue(op_store_fpr_,tregname), FREG) (void) \
+    {                                                    \
+        if (env->CP0_Status & (1 << CP0St_FR))           \
+            env->fpr[FREG].fd = treg;                    \
+        else {                                           \
+            env->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \
+            env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \
+        }                                                \
+        RETURN();                                        \
+    }
 
-#define OP_DLOAD_FREG(treg, tregname, DFREG)      \
-    void glue(glue(op_load_fpr_,tregname), DFREG) (void) \
-    {                                                   \
-        treg = FPR_D(env, DFREG);                    \
-        RETURN();                                       \
+OP_DLOAD_FREG(DT0, DT0_fpr, FREG)
+OP_DSTORE_FREG(DT0, DT0_fpr, FREG)
+
+OP_DLOAD_FREG(DT1, DT1_fpr, FREG)
+OP_DSTORE_FREG(DT1, DT1_fpr, FREG)
+
+OP_DLOAD_FREG(DT2, DT2_fpr, FREG)
+OP_DSTORE_FREG(DT2, DT2_fpr, FREG)
+
+#define OP_PSLOAD_FREG(treg, tregname, FREG)             \
+    void glue(glue(op_load_fpr_,tregname), FREG) (void)  \
+    {                                                    \
+        treg = env->fpr[FREG].fs[!FP_ENDIAN_IDX];        \
+        RETURN();                                        \
     }
 
-#define OP_DSTORE_FREG(treg, tregname, DFREG)            \
-    void glue(glue(op_store_fpr_,tregname), DFREG) (void)\
-    {                                                   \
-        FPR_D(env, DFREG) = treg;                    \
-        RETURN();                                       \
+#define OP_PSSTORE_FREG(treg, tregname, FREG)            \
+    void glue(glue(op_store_fpr_,tregname), FREG) (void) \
+    {                                                    \
+        env->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg;        \
+        RETURN();                                        \
     }
 
-OP_DLOAD_FREG(DT0, DT0_fpr, DFREG)
-OP_DSTORE_FREG(DT0, DT0_fpr, DFREG)
+OP_PSLOAD_FREG(WTH0, WTH0_fpr, FREG)
+OP_PSSTORE_FREG(WTH0, WTH0_fpr, FREG)
 
-OP_DLOAD_FREG(DT1, DT1_fpr, DFREG)
-OP_DSTORE_FREG(DT1, DT1_fpr, DFREG)
+OP_PSLOAD_FREG(WTH1, WTH1_fpr, FREG)
+OP_PSSTORE_FREG(WTH1, WTH1_fpr, FREG)
 
-OP_DLOAD_FREG(DT2, DT2_fpr, DFREG)
-OP_DSTORE_FREG(DT2, DT2_fpr, DFREG)
+OP_PSLOAD_FREG(WTH2, WTH2_fpr, FREG)
+OP_PSSTORE_FREG(WTH2, WTH2_fpr, FREG)
 
 #endif
 
 #if defined (FTN)
 
-#define SET_RESET(treg, tregname)    \
+#define SET_RESET(treg, tregname)        \
     void glue(op_set, tregname)(void)    \
-    {                                \
-        treg = PARAM1;               \
-        RETURN();                    \
-    }                                \
+    {                                    \
+        treg = PARAM1;                   \
+        RETURN();                        \
+    }                                    \
     void glue(op_reset, tregname)(void)  \
-    {                                \
-        treg = 0;                    \
-        RETURN();                    \
-    }                                \
+    {                                    \
+        treg = 0;                        \
+        RETURN();                        \
+    }
 
 SET_RESET(WT0, _WT0)
 SET_RESET(WT1, _WT1)
@@ -95,6 +123,9 @@
 SET_RESET(DT0, _DT0)
 SET_RESET(DT1, _DT1)
 SET_RESET(DT2, _DT2)
+SET_RESET(WTH0, _WTH0)
+SET_RESET(WTH1, _WTH1)
+SET_RESET(WTH2, _WTH2)
 
 #undef SET_RESET
 #endif

Modified: trunk/src/host/qemu-neo1973/target-mips/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -41,23 +41,26 @@
 static int map_address (CPUState *env, target_ulong *physical, int *prot,
                         target_ulong address, int rw, int access_type)
 {
-    target_ulong tag = address & (TARGET_PAGE_MASK << 1);
     uint8_t ASID = env->CP0_EntryHi & 0xFF;
-    tlb_t *tlb;
-    int i, n;
+    int i;
 
     for (i = 0; i < env->tlb_in_use; i++) {
-        tlb = &env->tlb[i];
+        tlb_t *tlb = &env->tlb[i];
+        /* 1k pages are not supported. */
+        target_ulong mask = tlb->PageMask | 0x1FFF;
+        target_ulong tag = address & ~mask;
+        int n;
+
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) &&
-            tlb->VPN == tag && address < tlb->end2) {
+            tlb->VPN == tag) {
             /* TLB match */
-            n = (address >> TARGET_PAGE_BITS) & 1;
+            n = !!(address & mask & ~(mask >> 1));
             /* Check access rights */
            if (!(n ? tlb->V1 : tlb->V0))
                 return TLBRET_INVALID;
            if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
-                *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK);
+                *physical = tlb->PFN[n] | (address & (mask >> 1));
                 *prot = PAGE_READ;
                 if (n ? tlb->D1 : tlb->D0)
                     *prot |= PAGE_WRITE;
@@ -74,8 +77,13 @@
                                 int *prot, target_ulong address,
                                 int rw, int access_type)
 {
-    /* User mode can only access useg */
+    /* User mode can only access useg/xuseg */
     int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
+#ifdef TARGET_MIPS64
+    int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
+    int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
+    int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
+#endif
     int ret = TLBRET_MATCH;
 
 #if 0
@@ -84,10 +92,18 @@
                 user_mode, env->hflags);
     }
 #endif
+
+#ifdef TARGET_MIPS64
+    if (user_mode && address > 0x3FFFFFFFFFFFFFFFULL)
+        return TLBRET_BADADDR;
+#else
     if (user_mode && address > 0x7FFFFFFFUL)
         return TLBRET_BADADDR;
-    if (address < (int32_t)0x80000000UL) {
-        if (!(env->hflags & MIPS_HFLAG_ERL)) {
+#endif
+
+    if (address <= (int32_t)0x7FFFFFFFUL) {
+        /* useg */
+        if (!(env->CP0_Status & (1 << CP0St_ERL) && user_mode)) {
 #ifdef MIPS_USES_R4K_TLB
             ret = map_address(env, physical, prot, address, rw, access_type);
 #else
@@ -98,6 +114,45 @@
             *physical = address;
             *prot = PAGE_READ | PAGE_WRITE;
         }
+#ifdef TARGET_MIPS64
+/*
+   XXX: Assuming :
+   - PABITS = 36 (correct for MIPS64R1)
+   - SEGBITS = 40
+*/
+    } else if (address < 0x3FFFFFFFFFFFFFFFULL) {
+        /* xuseg */
+	if (UX && address < 0x000000FFFFFFFFFFULL) {
+            ret = map_address(env, physical, prot, address, rw, access_type);
+	} else {
+	    ret = TLBRET_BADADDR;
+        }
+    } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
+        /* xsseg */
+	if (SX && address < 0x400000FFFFFFFFFFULL) {
+            ret = map_address(env, physical, prot, address, rw, access_type);
+	} else {
+	    ret = TLBRET_BADADDR;
+        }
+    } else if (address < 0xBFFFFFFFFFFFFFFFULL) {
+        /* xkphys */
+        /* XXX: check supervisor mode */
+        if (KX && (address & 0x03FFFFFFFFFFFFFFULL) < 0X0000000FFFFFFFFFULL)
+	{
+            *physical = address & 0X000000FFFFFFFFFFULL;
+            *prot = PAGE_READ | PAGE_WRITE;
+	} else {
+	    ret = TLBRET_BADADDR;
+	}
+    } else if (address < 0xFFFFFFFF7FFFFFFFULL) {
+        /* xkseg */
+        /* XXX: check supervisor mode */
+	if (KX && address < 0xC00000FF7FFFFFFFULL) {
+            ret = map_address(env, physical, prot, address, rw, access_type);
+	} else {
+	    ret = TLBRET_BADADDR;
+	}
+#endif
     } else if (address < (int32_t)0xA0000000UL) {
         /* kseg0 */
         /* XXX: check supervisor mode */
@@ -113,7 +168,7 @@
 #ifdef MIPS_USES_R4K_TLB
         ret = map_address(env, physical, prot, address, rw, access_type);
 #else
-        *physical = address;
+        *physical = address & 0xFFFFFFFF;
         *prot = PAGE_READ | PAGE_WRITE;
 #endif
     } else {
@@ -123,13 +178,13 @@
 #ifdef MIPS_USES_R4K_TLB
         ret = map_address(env, physical, prot, address, rw, access_type);
 #else
-        *physical = address;
+        *physical = address & 0xFFFFFFFF;
         *prot = PAGE_READ | PAGE_WRITE;
 #endif
     }
 #if 0
     if (logfile) {
-        fprintf(logfile, TLSZ " %d %d => " TLSZ " %d (%d)\n",
+        fprintf(logfile, TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n",
 		address, rw, access_type, *physical, *prot, ret);
     }
 #endif
@@ -138,12 +193,12 @@
 }
 
 #if defined(CONFIG_USER_ONLY) 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
 #else
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     target_ulong phys_addr;
     int prot;
@@ -171,7 +226,7 @@
 #if 0
         cpu_dump_state(env, logfile, fprintf, 0);
 #endif
-        fprintf(logfile, "%s pc " TLSZ " ad " TLSZ " rw %d is_user %d smmu %d\n",
+        fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d is_user %d smmu %d\n",
                 __func__, env->PC, address, rw, is_user, is_softmmu);
     }
 
@@ -189,7 +244,7 @@
     ret = get_physical_address(env, &physical, &prot,
                                address, rw, access_type);
     if (logfile) {
-        fprintf(logfile, "%s address=" TLSZ " ret %d physical " TLSZ " prot %d\n",
+        fprintf(logfile, "%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_lx " prot %d\n",
                 __func__, address, ret, physical, prot);
     }
     if (ret == TLBRET_MATCH) {
@@ -255,7 +310,7 @@
     int cause = -1;
 
     if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
-        fprintf(logfile, "%s enter: PC " TLSZ " EPC " TLSZ " cause %d excp %d\n",
+        fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n",
                 __func__, env->PC, env->CP0_EPC, cause, env->exception_index);
     }
     if (env->exception_index == EXCP_EXT_INTERRUPT &&
@@ -286,7 +341,6 @@
         goto set_DEPC;
     case EXCP_DDBL:
         env->CP0_Debug |= 1 << CP0DB_DDBL;
-        goto set_DEPC;
     set_DEPC:
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
@@ -298,18 +352,21 @@
         }
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM;
+        env->hflags &= ~MIPS_HFLAG_UM;
         /* EJTAG probe trap enable is not implemented... */
+        if (!(env->CP0_Status & (1 << CP0St_EXL)))
+            env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC = (int32_t)0xBFC00480;
         break;
     case EXCP_RESET:
         cpu_reset(env);
         break;
     case EXCP_SRESET:
-        env->CP0_Status = (1 << CP0St_SR);
+        env->CP0_Status |= (1 << CP0St_SR);
         env->CP0_WatchLo = 0;
         goto set_error_EPC;
     case EXCP_NMI:
-        env->CP0_Status = (1 << CP0St_NMI);
+        env->CP0_Status |= (1 << CP0St_NMI);
     set_error_EPC:
         if (env->hflags & MIPS_HFLAG_BMASK) {
             /* If the exception was raised from a delay slot,
@@ -319,8 +376,10 @@
         } else {
             env->CP0_ErrorEPC = env->PC;
         }
-        env->hflags |= MIPS_HFLAG_ERL;
-	env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+        env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+        env->hflags &= ~MIPS_HFLAG_UM;
+        if (!(env->CP0_Status & (1 << CP0St_EXL)))
+            env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC = (int32_t)0xBFC00000;
         break;
     case EXCP_MCHECK:
@@ -336,12 +395,14 @@
         /* XXX: TODO: manage defered watch exceptions */
         goto set_EPC;
     case EXCP_AdEL:
-    case EXCP_AdES:
         cause = 4;
         goto set_EPC;
+    case EXCP_AdES:
+        cause = 5;
+        goto set_EPC;
     case EXCP_TLBL:
         cause = 2;
-        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
+        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
             offset = 0x000;
         goto set_EPC;
     case EXCP_IBE:
@@ -361,7 +422,8 @@
         goto set_EPC;
     case EXCP_CpU:
         cause = 11;
-        env->CP0_Cause = (env->CP0_Cause & ~0x03000000) | (env->error_code << 28);
+        env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
+                         (env->error_code << CP0Ca_CE);
         goto set_EPC;
     case EXCP_OVERFLOW:
         cause = 12;
@@ -369,34 +431,38 @@
     case EXCP_TRAP:
         cause = 13;
         goto set_EPC;
+    case EXCP_FPE:
+        cause = 15;
+        goto set_EPC;
     case EXCP_LTLBL:
         cause = 1;
         goto set_EPC;
     case EXCP_TLBS:
         cause = 3;
-        if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
+        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
             offset = 0x000;
-        goto set_EPC;
     set_EPC:
-        if (env->hflags & MIPS_HFLAG_BMASK) {
-            /* If the exception was raised from a delay slot,
-               come back to the jump.  */
-            env->CP0_EPC = env->PC - 4;
-            env->CP0_Cause |= 0x80000000;
-            env->hflags &= ~MIPS_HFLAG_BMASK;
-        } else {
-            env->CP0_EPC = env->PC;
-            env->CP0_Cause &= ~0x80000000;
+        if (!(env->CP0_Status & (1 << CP0St_EXL))) {
+            if (env->hflags & MIPS_HFLAG_BMASK) {
+                /* If the exception was raised from a delay slot,
+                   come back to the jump.  */
+                env->CP0_EPC = env->PC - 4;
+                env->CP0_Cause |= (1 << CP0Ca_BD);
+            } else {
+                env->CP0_EPC = env->PC;
+                env->CP0_Cause &= ~(1 << CP0Ca_BD);
+            }
+            env->CP0_Status |= (1 << CP0St_EXL);
+            env->hflags &= ~MIPS_HFLAG_UM;
         }
+        env->hflags &= ~MIPS_HFLAG_BMASK;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
             env->PC = (int32_t)0xBFC00200;
         } else {
-            env->PC = (int32_t)0x80000000;
+            env->PC = (int32_t)(env->CP0_EBase & ~0x3ff);
         }
-        env->hflags |= MIPS_HFLAG_EXL;
-        env->CP0_Status |= (1 << CP0St_EXL);
         env->PC += offset;
-        env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2);
+        env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
         break;
     default:
         if (logfile) {
@@ -407,8 +473,8 @@
         exit(1);
     }
     if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
-        fprintf(logfile, "%s: PC " TLSZ " EPC " TLSZ " cause %d excp %d\n"
-                "    S %08x C %08x A " TLSZ " D " TLSZ "\n",
+        fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n"
+                "    S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
                 __func__, env->PC, env->CP0_EPC, cause, env->exception_index,
                 env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
                 env->CP0_DEPC);
@@ -421,10 +487,10 @@
 {
     tlb_t *tlb;
     target_ulong addr;
-    uint8_t ASID;
+    target_ulong end;
+    uint8_t ASID = env->CP0_EntryHi & 0xFF;
+    target_ulong mask;
 
-    ASID = env->CP0_EntryHi & 0xFF;
-
     tlb = &env->tlb[idx];
     /* The qemu TLB is flushed then the ASID changes, so no need to
        flush these entries again.  */
@@ -441,19 +507,23 @@
         return;
     }
 
+    /* 1k pages are not supported. */
+    mask = tlb->PageMask | 0x1FFF;
     if (tlb->V0) {
         addr = tlb->VPN;
-        while (addr < tlb->end) {
+        end = addr | (mask >> 1);
+        while (addr < end) {
             tlb_flush_page (env, addr);
             addr += TARGET_PAGE_SIZE;
         }
     }
     if (tlb->V1) {
-        addr = tlb->end;
-        while (addr < tlb->end2) {
+        addr = tlb->VPN | ((mask >> 1) + 1);
+        addr = tlb->VPN + TARGET_PAGE_SIZE;
+        end = addr | mask;
+        while (addr < end) {
             tlb_flush_page (env, addr);
             addr += TARGET_PAGE_SIZE;
         }
     }
 }
-

Modified: trunk/src/host/qemu-neo1973/target-mips/mips-defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/mips-defs.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/mips-defs.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,93 +1,24 @@
 #if !defined (__QEMU_MIPS_DEFS_H__)
 #define __QEMU_MIPS_DEFS_H__
 
-/* If we want to use 64 bits host regs... */
-//#define USE_64BITS_REGS
 /* If we want to use host float regs... */
 //#define USE_HOST_FLOAT_REGS
 
-#define MIPS_R4Kc 0x00018000
-#define MIPS_R4Kp 0x00018300
-
-/* Emulate MIPS R4Kc for now */
-#define MIPS_CPU MIPS_R4Kc
-
-#if (MIPS_CPU == MIPS_R4Kc)
-/* 32 bits target */
-#undef MIPS_HAS_MIPS64
-//#define MIPS_HAS_MIPS64 1
 /* real pages are variable size... */
 #define TARGET_PAGE_BITS 12
-/* Uses MIPS R4Kx enhancements to MIPS32 architecture */
-#define MIPS_USES_R4K_EXT
 /* Uses MIPS R4Kc TLB model */
 #define MIPS_USES_R4K_TLB
-#define MIPS_TLB_NB 16
 #define MIPS_TLB_MAX 128
-/* basic FPU register support */
-#define MIPS_USES_FPU 1
-/* Define a implementation number of 1.
- * Define a major version 1, minor version 0.
- */
-#define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0)
-  /* Have config1, is MIPS32R1, uses TLB, no virtual icache,
-     uncached coherency */
-#define MIPS_CONFIG0_1                                            \
-  ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) |      \
-   (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) |    \
-   (0x2 << CP0C0_K0))
-#ifdef TARGET_WORDS_BIGENDIAN
-#define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE))
-#else
-#define MIPS_CONFIG0 MIPS_CONFIG0_1
-#endif
-/* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line,
-   2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache,
-   no coprocessor2 attached, no MDMX support attached,
-   no performance counters, watch registers present,
-   no code compression, EJTAG present, FPU enable bit depending on
-   MIPS_USES_FPU */
-#define MIPS_CONFIG1_1                                            \
-((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) |              \
- (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) |      \
- (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) |      \
- (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |            \
- (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP))
-#ifdef MIPS_USES_FPU
-#define MIPS_CONFIG1  (MIPS_CONFIG1_1 | (1 << CP0C1_FP))
-#else
-#define MIPS_CONFIG1  (MIPS_CONFIG1_1 | (0 << CP0C1_FP))
-#endif
-/* Have config3, no tertiary/secondary caches implemented */
-#define MIPS_CONFIG2                                              \
-((1 << CP0C2_M))
-/* No config4, no DSP ASE, no large physaddr,
-   no external interrupt controller, no vectored interupts,
-   no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */
-#define MIPS_CONFIG3                                              \
-((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |          \
- (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |        \
- (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL))
-#elif (MIPS_CPU == MIPS_R4Kp)
-/* 32 bits target */
-#undef MIPS_HAS_MIPS64
-/* real pages are variable size... */
-#define TARGET_PAGE_BITS 12
-/* Uses MIPS R4Kx enhancements to MIPS32 architecture */
-#define MIPS_USES_R4K_EXT
-/* Uses MIPS R4Km FPM MMU model */
-#define MIPS_USES_R4K_FPM
-#else
-#error "MIPS CPU not defined"
-/* Reminder for other flags */
-//#undef MIPS_HAS_MIPS64
-//#define MIPS_USES_FPU
-#endif
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 #define TARGET_LONG_BITS 64
 #else
 #define TARGET_LONG_BITS 32
 #endif
 
+/* Strictly follow the architecture standard:
+   - Disallow "special" instruction handling for PMON/SPIM.
+   Note that we still maintain Count/Compare to match the host clock. */
+//#define MIPS_STRICT_STANDARD 1
+
 #endif /* !defined (__QEMU_MIPS_DEFS_H__) */

Modified: trunk/src/host/qemu-neo1973/target-mips/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -23,27 +23,27 @@
 #include "exec.h"
 
 #ifndef CALL_FROM_TB0
-#define CALL_FROM_TB0(func) func();
+#define CALL_FROM_TB0(func) func()
 #endif
 #ifndef CALL_FROM_TB1
-#define CALL_FROM_TB1(func, arg0) func(arg0);
+#define CALL_FROM_TB1(func, arg0) func(arg0)
 #endif
 #ifndef CALL_FROM_TB1_CONST16
-#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
+#define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
 #endif
 #ifndef CALL_FROM_TB2
-#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
+#define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
 #endif
 #ifndef CALL_FROM_TB2_CONST16
 #define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
-CALL_FROM_TB2(func, arg0, arg1);
+        CALL_FROM_TB2(func, arg0, arg1)
 #endif
 #ifndef CALL_FROM_TB3
-#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
+#define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
 #endif
 #ifndef CALL_FROM_TB4
 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
-        func(arg0, arg1, arg2, arg3);
+        func(arg0, arg1, arg2, arg3)
 #endif
 
 #define REG 1
@@ -144,143 +144,107 @@
 #include "op_template.c"
 #undef TN
 
-#ifdef MIPS_USES_FPU
-
-#define SFREG 0
-#define DFREG 0
+#define FREG 0
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 1
+#undef FREG
+#define FREG 1
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 2
-#define DFREG 2
+#undef FREG
+#define FREG 2
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 3
+#undef FREG
+#define FREG 3
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 4
-#define DFREG 4
+#undef FREG
+#define FREG 4
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 5
+#undef FREG
+#define FREG 5
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 6
-#define DFREG 6
+#undef FREG
+#define FREG 6
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 7
+#undef FREG
+#define FREG 7
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 8
-#define DFREG 8
+#undef FREG
+#define FREG 8
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 9
+#undef FREG
+#define FREG 9
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 10
-#define DFREG 10
+#undef FREG
+#define FREG 10
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 11
+#undef FREG
+#define FREG 11
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 12
-#define DFREG 12
+#undef FREG
+#define FREG 12
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 13
+#undef FREG
+#define FREG 13
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 14
-#define DFREG 14
+#undef FREG
+#define FREG 14
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 15
+#undef FREG
+#define FREG 15
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 16
-#define DFREG 16
+#undef FREG
+#define FREG 16
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 17
+#undef FREG
+#define FREG 17
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 18
-#define DFREG 18
+#undef FREG
+#define FREG 18
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 19
+#undef FREG
+#define FREG 19
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 20
-#define DFREG 20
+#undef FREG
+#define FREG 20
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 21
+#undef FREG
+#define FREG 21
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 22
-#define DFREG 22
+#undef FREG
+#define FREG 22
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 23
+#undef FREG
+#define FREG 23
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 24
-#define DFREG 24
+#undef FREG
+#define FREG 24
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 25
+#undef FREG
+#define FREG 25
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 26
-#define DFREG 26
+#undef FREG
+#define FREG 26
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 27
+#undef FREG
+#define FREG 27
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 28
-#define DFREG 28
+#undef FREG
+#define FREG 28
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 29
+#undef FREG
+#define FREG 29
 #include "fop_template.c"
-#undef SFREG
-#define SFREG 30
-#define DFREG 30
+#undef FREG
+#define FREG 30
 #include "fop_template.c"
-#undef SFREG
-#undef DFREG
-#define SFREG 31
+#undef FREG
+#define FREG 31
 #include "fop_template.c"
-#undef SFREG
+#undef FREG
 
 #define FTN
 #include "fop_template.c"
 #undef FTN
 
-#endif
-
 void op_dup_T0 (void)
 {
     T2 = T0;
@@ -325,6 +289,22 @@
 #undef MEMSUFFIX
 #endif
 
+/* Addresses computation */
+void op_addr_add (void)
+{
+/* For compatibility with 32-bit code, data reference in user mode
+   with Status_UX = 0 should be casted to 32-bit and sign extended.
+   See the MIPS64 PRA manual, section 4.10. */
+#ifdef TARGET_MIPS64
+    if ((env->CP0_Status & (1 << CP0St_UM)) &&
+        !(env->CP0_Status & (1 << CP0St_UX)))
+        T0 = (int64_t)(int32_t)(T0 + T1);
+    else
+#endif
+        T0 += T1;
+    RETURN();
+}
+
 /* Arithmetic */
 void op_add (void)
 {
@@ -340,7 +320,7 @@
     T0 = (int32_t)T0 + (int32_t)T1;
     if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
         /* operands of same sign, result different sign */
-        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
     }
     T0 = (int32_t)T0;
     RETURN();
@@ -360,7 +340,7 @@
     T0 = (int32_t)T0 - (int32_t)T1;
     if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
         /* operands of different sign, first operand and result different sign */
-        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
     }
     T0 = (int32_t)T0;
     RETURN();
@@ -372,14 +352,22 @@
     RETURN();
 }
 
+#if HOST_LONG_BITS < 64
 void op_div (void)
 {
+    CALL_FROM_TB0(do_div);
+    RETURN();
+}
+#else
+void op_div (void)
+{
     if (T1 != 0) {
-        env->LO = (int32_t)((int32_t)T0 / (int32_t)T1);
-        env->HI = (int32_t)((int32_t)T0 % (int32_t)T1);
+        env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
+        env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
     }
     RETURN();
 }
+#endif
 
 void op_divu (void)
 {
@@ -390,7 +378,7 @@
     RETURN();
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 /* Arithmetic */
 void op_dadd (void)
 {
@@ -406,7 +394,7 @@
     T0 += T1;
     if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
         /* operands of same sign, result different sign */
-        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
     }
     RETURN();
 }
@@ -425,7 +413,7 @@
     T0 = (int64_t)T0 - (int64_t)T1;
     if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
         /* operands of different sign, first operand and result different sign */
-        CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
+        CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
     }
     RETURN();
 }
@@ -436,7 +424,6 @@
     RETURN();
 }
 
-#if TARGET_LONG_BITS > HOST_LONG_BITS
 /* Those might call libgcc functions.  */
 void op_ddiv (void)
 {
@@ -444,21 +431,13 @@
     RETURN();
 }
 
+#if TARGET_LONG_BITS > HOST_LONG_BITS
 void op_ddivu (void)
 {
     do_ddivu();
     RETURN();
 }
 #else
-void op_ddiv (void)
-{
-    if (T1 != 0) {
-        env->LO = (int64_t)T0 / (int64_t)T1;
-        env->HI = (int64_t)T0 % (int64_t)T1;
-    }
-    RETURN();
-}
-
 void op_ddivu (void)
 {
     if (T1 != 0) {
@@ -468,7 +447,7 @@
     RETURN();
 }
 #endif
-#endif /* MIPS_HAS_MIPS64 */
+#endif /* TARGET_MIPS64 */
 
 /* Logical */
 void op_and (void)
@@ -497,19 +476,19 @@
 
 void op_sll (void)
 {
-    T0 = (int32_t)((uint32_t)T0 << (uint32_t)T1);
+    T0 = (int32_t)((uint32_t)T0 << T1);
     RETURN();
 }
 
 void op_sra (void)
 {
-    T0 = (int32_t)((int32_t)T0 >> (uint32_t)T1);
+    T0 = (int32_t)((int32_t)T0 >> T1);
     RETURN();
 }
 
 void op_srl (void)
 {
-    T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1);
+    T0 = (int32_t)((uint32_t)T0 >> T1);
     RETURN();
 }
 
@@ -518,10 +497,9 @@
     target_ulong tmp;
 
     if (T1) {
-       tmp = (int32_t)((uint32_t)T0 << (0x20 - (uint32_t)T1));
-       T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1) | tmp;
-    } else
-       T0 = T1;
+       tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
+       T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
+    }
     RETURN();
 }
 
@@ -590,7 +568,7 @@
     RETURN();
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 /* Those might call libgcc functions.  */
@@ -711,8 +689,7 @@
     if (T1) {
        tmp = T0 << (0x40 - T1);
        T0 = (T0 >> T1) | tmp;
-    } else
-       T0 = T1;
+    }
     RETURN();
 }
 
@@ -723,8 +700,7 @@
     if (T1) {
        tmp = T0 << (0x40 - (32 + T1));
        T0 = (T0 >> (32 + T1)) | tmp;
-    } else
-       T0 = T1;
+    }
     RETURN();
 }
 
@@ -895,7 +871,7 @@
 }
 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 void op_dmult (void)
 {
     CALL_FROM_TB0(do_dmult);
@@ -924,21 +900,19 @@
     RETURN();
 }
 
-#ifdef MIPS_USES_FPU
 void op_movf (void)
 {
     if (!(env->fcr31 & PARAM1))
-        env->gpr[PARAM2] = env->gpr[PARAM3];
+        T0 = T1;
     RETURN();
 }
 
 void op_movt (void)
 {
     if (env->fcr31 & PARAM1)
-        env->gpr[PARAM2] = env->gpr[PARAM3];
+        T0 = T1;
     RETURN();
 }
-#endif
 
 /* Tests */
 #define OP_COND(name, cond) \
@@ -1032,7 +1006,7 @@
 /* CP0 functions */
 void op_mfc0_index (void)
 {
-    T0 = (int32_t)(env->CP0_index);
+    T0 = env->CP0_Index;
     RETURN();
 }
 
@@ -1044,49 +1018,49 @@
 
 void op_mfc0_entrylo0 (void)
 {
-    T0 = env->CP0_EntryLo0;
+    T0 = (int32_t)env->CP0_EntryLo0;
     RETURN();
 }
 
 void op_mfc0_entrylo1 (void)
 {
-    T0 = env->CP0_EntryLo1;
+    T0 = (int32_t)env->CP0_EntryLo1;
     RETURN();
 }
 
 void op_mfc0_context (void)
 {
-    T0 = env->CP0_Context;
+    T0 = (int32_t)env->CP0_Context;
     RETURN();
 }
 
 void op_mfc0_pagemask (void)
 {
-    T0 = (int32_t)env->CP0_PageMask;
+    T0 = env->CP0_PageMask;
     RETURN();
 }
 
 void op_mfc0_pagegrain (void)
 {
-    T0 = (int32_t)env->CP0_PageGrain;
+    T0 = env->CP0_PageGrain;
     RETURN();
 }
 
 void op_mfc0_wired (void)
 {
-    T0 = (int32_t)env->CP0_Wired;
+    T0 = env->CP0_Wired;
     RETURN();
 }
 
 void op_mfc0_hwrena (void)
 {
-    T0 = (int32_t)env->CP0_HWREna;
+    T0 = env->CP0_HWREna;
     RETURN();
 }
 
 void op_mfc0_badvaddr (void)
 {
-    T0 = env->CP0_BadVAddr;
+    T0 = (int32_t)env->CP0_BadVAddr;
     RETURN();
 }
 
@@ -1098,55 +1072,55 @@
 
 void op_mfc0_entryhi (void)
 {
-    T0 = env->CP0_EntryHi;
+    T0 = (int32_t)env->CP0_EntryHi;
     RETURN();
 }
 
 void op_mfc0_compare (void)
 {
-    T0 = (int32_t)env->CP0_Compare;
+    T0 = env->CP0_Compare;
     RETURN();
 }
 
 void op_mfc0_status (void)
 {
-    T0 = (int32_t)env->CP0_Status;
-    if (env->hflags & MIPS_HFLAG_UM)
-        T0 |= (1 << CP0St_UM);
-    if (env->hflags & MIPS_HFLAG_ERL)
-        T0 |= (1 << CP0St_ERL);
-    if (env->hflags & MIPS_HFLAG_EXL)
-        T0 |= (1 << CP0St_EXL);
+    T0 = env->CP0_Status;
     RETURN();
 }
 
 void op_mfc0_intctl (void)
 {
-    T0 = (int32_t)env->CP0_IntCtl;
+    T0 = env->CP0_IntCtl;
     RETURN();
 }
 
 void op_mfc0_srsctl (void)
 {
-    T0 = (int32_t)env->CP0_SRSCtl;
+    T0 = env->CP0_SRSCtl;
     RETURN();
 }
 
+void op_mfc0_srsmap (void)
+{
+    T0 = env->CP0_SRSMap;
+    RETURN();
+}
+
 void op_mfc0_cause (void)
 {
-    T0 = (int32_t)env->CP0_Cause;
+    T0 = env->CP0_Cause;
     RETURN();
 }
 
 void op_mfc0_epc (void)
 {
-    T0 = env->CP0_EPC;
+    T0 = (int32_t)env->CP0_EPC;
     RETURN();
 }
 
 void op_mfc0_prid (void)
 {
-    T0 = (int32_t)env->CP0_PRid;
+    T0 = env->CP0_PRid;
     RETURN();
 }
 
@@ -1158,31 +1132,43 @@
 
 void op_mfc0_config0 (void)
 {
-    T0 = (int32_t)env->CP0_Config0;
+    T0 = env->CP0_Config0;
     RETURN();
 }
 
 void op_mfc0_config1 (void)
 {
-    T0 = (int32_t)env->CP0_Config1;
+    T0 = env->CP0_Config1;
     RETURN();
 }
 
 void op_mfc0_config2 (void)
 {
-    T0 = (int32_t)env->CP0_Config2;
+    T0 = env->CP0_Config2;
     RETURN();
 }
 
 void op_mfc0_config3 (void)
 {
-    T0 = (int32_t)env->CP0_Config3;
+    T0 = env->CP0_Config3;
     RETURN();
 }
 
+void op_mfc0_config6 (void)
+{
+    T0 = env->CP0_Config6;
+    RETURN();
+}
+
+void op_mfc0_config7 (void)
+{
+    T0 = env->CP0_Config7;
+    RETURN();
+}
+
 void op_mfc0_lladdr (void)
 {
-    T0 = env->CP0_LLAddr >> 4;
+    T0 = (int32_t)env->CP0_LLAddr >> 4;
     RETURN();
 }
 
@@ -1194,13 +1180,13 @@
 
 void op_mfc0_watchhi0 (void)
 {
-    T0 = (int32_t)env->CP0_WatchHi;
+    T0 = env->CP0_WatchHi;
     RETURN();
 }
 
 void op_mfc0_xcontext (void)
 {
-    T0 = env->CP0_XContext;
+    T0 = (int32_t)env->CP0_XContext;
     RETURN();
 }
 
@@ -1212,7 +1198,7 @@
 
 void op_mfc0_debug (void)
 {
-    T0 = (int32_t)env->CP0_Debug;
+    T0 = env->CP0_Debug;
     if (env->hflags & MIPS_HFLAG_DM)
         T0 |= 1 << CP0DB_DM;
     RETURN();
@@ -1220,55 +1206,55 @@
 
 void op_mfc0_depc (void)
 {
-    T0 = env->CP0_DEPC;
+    T0 = (int32_t)env->CP0_DEPC;
     RETURN();
 }
 
 void op_mfc0_performance0 (void)
 {
-    T0 = (int32_t)env->CP0_Performance0;
+    T0 = env->CP0_Performance0;
     RETURN();
 }
 
 void op_mfc0_taglo (void)
 {
-    T0 = (int32_t)env->CP0_TagLo;
+    T0 = env->CP0_TagLo;
     RETURN();
 }
 
 void op_mfc0_datalo (void)
 {
-    T0 = (int32_t)env->CP0_DataLo;
+    T0 = env->CP0_DataLo;
     RETURN();
 }
 
 void op_mfc0_taghi (void)
 {
-    T0 = (int32_t)env->CP0_TagHi;
+    T0 = env->CP0_TagHi;
     RETURN();
 }
 
 void op_mfc0_datahi (void)
 {
-    T0 = (int32_t)env->CP0_DataHi;
+    T0 = env->CP0_DataHi;
     RETURN();
 }
 
 void op_mfc0_errorepc (void)
 {
-    T0 = env->CP0_ErrorEPC;
+    T0 = (int32_t)env->CP0_ErrorEPC;
     RETURN();
 }
 
 void op_mfc0_desave (void)
 {
-    T0 = (int32_t)env->CP0_DESAVE;
+    T0 = env->CP0_DESAVE;
     RETURN();
 }
 
 void op_mtc0_index (void)
 {
-    env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
+    env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
     RETURN();
 }
 
@@ -1276,7 +1262,7 @@
 {
     /* Large physaddr not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo0 = T0 & (int32_t)0x3FFFFFFF;
+    env->CP0_EntryLo0 = (int32_t)T0 & 0x3FFFFFFF;
     RETURN();
 }
 
@@ -1284,13 +1270,13 @@
 {
     /* Large physaddr not implemented */
     /* 1k pages not implemented */
-    env->CP0_EntryLo1 = T0 & (int32_t)0x3FFFFFFF;
+    env->CP0_EntryLo1 = (int32_t)T0 & 0x3FFFFFFF;
     RETURN();
 }
 
 void op_mtc0_context (void)
 {
-    env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
+    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
     RETURN();
 }
 
@@ -1312,7 +1298,7 @@
 
 void op_mtc0_wired (void)
 {
-    env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
+    env->CP0_Wired = T0 % env->nb_tlb;
     RETURN();
 }
 
@@ -1334,7 +1320,7 @@
 
     /* 1k pages not implemented */
     /* Ignore MIPS64 TLB for now */
-    val = T0 & (int32_t)0xFFFFE0FF;
+    val = (target_ulong)(int32_t)T0 & ~(target_ulong)0x1F00;
     old = env->CP0_EntryHi;
     env->CP0_EntryHi = val;
     /* If the ASID changes, flush qemu's TLB.  */
@@ -1351,45 +1337,30 @@
 
 void op_mtc0_status (void)
 {
-    uint32_t val, old, mask;
+    uint32_t val, old;
+    uint32_t mask = env->Status_rw_bitmask;
 
-    val = T0 & (int32_t)0xFA78FF01;
+    /* No reverse endianness, no MDMX/DSP, no 64bit ops,
+       no 64bit addressing implemented. */
+    val = (int32_t)T0 & mask;
     old = env->CP0_Status;
-    if (T0 & (1 << CP0St_UM))
+    if (!(val & (1 << CP0St_EXL)) &&
+        !(val & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (val & (1 << CP0St_UM)))
         env->hflags |= MIPS_HFLAG_UM;
-    else
-        env->hflags &= ~MIPS_HFLAG_UM;
-    if (T0 & (1 << CP0St_ERL))
-        env->hflags |= MIPS_HFLAG_ERL;
-    else
-        env->hflags &= ~MIPS_HFLAG_ERL;
-    if (T0 & (1 << CP0St_EXL))
-        env->hflags |= MIPS_HFLAG_EXL;
-    else
-        env->hflags &= ~MIPS_HFLAG_EXL;
-    env->CP0_Status = val;
-    /* If we unmasked an asserted IRQ, raise it */
-    mask = 0x0000FF00;
-    if (loglevel & CPU_LOG_TB_IN_ASM)
-       CALL_FROM_TB2(do_mtc0_status_debug, old, val);
-    if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
-        !(env->hflags & MIPS_HFLAG_EXL) &&
-        !(env->hflags & MIPS_HFLAG_ERL) &&
-        !(env->hflags & MIPS_HFLAG_DM) &&
-        (env->CP0_Status & env->CP0_Cause & mask)) {
-        env->interrupt_request |= CPU_INTERRUPT_HARD;
-       if (logfile)
-           CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-    } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-    }
+    env->CP0_Status = (env->CP0_Status & ~mask) | val;
+    if (loglevel & CPU_LOG_EXEC)
+        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
 void op_mtc0_intctl (void)
 {
-    /* vectored interrupts not implemented */
-    env->CP0_IntCtl = 0;
+    /* vectored interrupts not implemented, timer on int 7,
+       no performance counters. */
+    env->CP0_IntCtl |= T0 & 0x000002e0;
     RETURN();
 }
 
@@ -1400,30 +1371,33 @@
     RETURN();
 }
 
+void op_mtc0_srsmap (void)
+{
+    /* shadow registers not implemented */
+    env->CP0_SRSMap = 0;
+    RETURN();
+}
+
 void op_mtc0_cause (void)
 {
-    uint32_t val, old;
+    uint32_t mask = 0x00C00300;
 
-    val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x00C00300);
-    old = env->CP0_Cause;
-    env->CP0_Cause = val;
-#if 0
-    {
-        int i, mask;
-       /* Check if we ever asserted a software IRQ */
-        for (i = 0; i < 2; i++) {
-            mask = 0x100 << i;
-            if ((val & mask) & !(old & mask))
-                CALL_FROM_TB1(mips_set_irq, i);
-        }
+    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+        mask |= 1 << CP0Ca_DC;
+
+    env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
+
+    /* Handle the software interrupt as an hardware one, as they
+       are very similar */
+    if (T0 & CP0Ca_IP_mask) {
+        CALL_FROM_TB1(cpu_mips_update_irq, env);
     }
-#endif
     RETURN();
 }
 
 void op_mtc0_epc (void)
 {
-    env->CP0_EPC = T0;
+    env->CP0_EPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1431,7 +1405,7 @@
 {
     /* vectored interrupts not implemented */
     /* Multi-CPU not implemented */
-    env->CP0_EBase = (int32_t)0x80000000 | (T0 & 0x3FFFF000);
+    env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
     RETURN();
 }
 
@@ -1455,22 +1429,19 @@
 
 void op_mtc0_watchlo0 (void)
 {
-    env->CP0_WatchLo = T0;
+    /* Watch exceptions for instructions, data loads, data stores
+       not implemented. */
+    env->CP0_WatchLo = (int32_t)(T0 & ~0x7);
     RETURN();
 }
 
 void op_mtc0_watchhi0 (void)
 {
-    env->CP0_WatchHi = T0 & 0x40FF0FF8;
+    env->CP0_WatchHi = (T0 & 0x40FF0FF8);
+    env->CP0_WatchHi &= ~(env->CP0_WatchHi & T0 & 0x7);
     RETURN();
 }
 
-void op_mtc0_xcontext (void)
-{
-    env->CP0_XContext = T0; /* XXX */
-    RETURN();
-}
-
 void op_mtc0_framemask (void)
 {
     env->CP0_Framemask = T0; /* XXX */
@@ -1489,7 +1460,7 @@
 
 void op_mtc0_depc (void)
 {
-    env->CP0_DEPC = T0;
+    env->CP0_DEPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1501,7 +1472,7 @@
 
 void op_mtc0_taglo (void)
 {
-    env->CP0_TagLo = T0 & (int32_t)0xFFFFFCF6;
+    env->CP0_TagLo = T0 & 0xFFFFFCF6;
     RETURN();
 }
 
@@ -1525,7 +1496,7 @@
 
 void op_mtc0_errorepc (void)
 {
-    env->CP0_ErrorEPC = T0;
+    env->CP0_ErrorEPC = (int32_t)T0;
     RETURN();
 }
 
@@ -1535,33 +1506,149 @@
     RETURN();
 }
 
-#ifdef MIPS_USES_FPU
+#ifdef TARGET_MIPS64
+void op_dmfc0_entrylo0 (void)
+{
+    T0 = env->CP0_EntryLo0;
+    RETURN();
+}
 
+void op_dmfc0_entrylo1 (void)
+{
+    T0 = env->CP0_EntryLo1;
+    RETURN();
+}
+
+void op_dmfc0_context (void)
+{
+    T0 = env->CP0_Context;
+    RETURN();
+}
+
+void op_dmfc0_badvaddr (void)
+{
+    T0 = env->CP0_BadVAddr;
+    RETURN();
+}
+
+void op_dmfc0_entryhi (void)
+{
+    T0 = env->CP0_EntryHi;
+    RETURN();
+}
+
+void op_dmfc0_epc (void)
+{
+    T0 = env->CP0_EPC;
+    RETURN();
+}
+
+void op_dmfc0_lladdr (void)
+{
+    T0 = env->CP0_LLAddr >> 4;
+    RETURN();
+}
+
+void op_dmfc0_watchlo0 (void)
+{
+    T0 = env->CP0_WatchLo;
+    RETURN();
+}
+
+void op_dmfc0_xcontext (void)
+{
+    T0 = env->CP0_XContext;
+    RETURN();
+}
+
+void op_dmfc0_depc (void)
+{
+    T0 = env->CP0_DEPC;
+    RETURN();
+}
+
+void op_dmfc0_errorepc (void)
+{
+    T0 = env->CP0_ErrorEPC;
+    RETURN();
+}
+
+void op_dmtc0_entrylo0 (void)
+{
+    /* Large physaddr not implemented */
+    /* 1k pages not implemented */
+    env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_dmtc0_entrylo1 (void)
+{
+    /* Large physaddr not implemented */
+    /* 1k pages not implemented */
+    env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
+    RETURN();
+}
+
+void op_dmtc0_context (void)
+{
+    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
+    RETURN();
+}
+
+void op_dmtc0_epc (void)
+{
+    env->CP0_EPC = T0;
+    RETURN();
+}
+
+void op_dmtc0_watchlo0 (void)
+{
+    /* Watch exceptions for instructions, data loads, data stores
+       not implemented. */
+    env->CP0_WatchLo = T0 & ~0x7;
+    RETURN();
+}
+
+void op_dmtc0_xcontext (void)
+{
+    env->CP0_XContext = (env->CP0_XContext & 0xffffffff) | (T0 & ~0xffffffff);
+    RETURN();
+}
+
+void op_dmtc0_depc (void)
+{
+    env->CP0_DEPC = T0;
+    RETURN();
+}
+
+void op_dmtc0_errorepc (void)
+{
+    env->CP0_ErrorEPC = T0;
+    RETURN();
+}
+#endif /* TARGET_MIPS64 */
+
+/* CP1 functions */
 #if 0
 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
 #else
 # define DEBUG_FPU_STATE() do { } while(0)
 #endif
 
-void op_cp1_enabled(void)
+void op_cp0_enabled(void)
 {
-    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
-        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
+    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
+	(env->hflags & MIPS_HFLAG_UM)) {
+        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
     }
     RETURN();
 }
 
-/* CP1 functions */
-void op_cfc1 (void)
+void op_cp1_enabled(void)
 {
-    if (T1 == 0) {
-        T0 = env->fcr0;
+    if (!(env->CP0_Status & (1 << CP0St_CU1))) {
+        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
     }
-    else {
-        /* fetch fcr31, masking unused bits */
-        T0 = env->fcr31 & 0x0183FFFF;
-    }
-    DEBUG_FPU_STATE();
     RETURN();
 }
 
@@ -1576,30 +1663,97 @@
 #define RESTORE_ROUNDING_MODE \
     set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
 
-void op_ctc1 (void)
+inline char ieee_ex_to_mips(char xcpt)
 {
-    if (T1 == 0) {
-        /* XXX should this throw an exception?
-         * don't write to FCR0.
-         * env->fcr0 = T0; 
-         */
-    }
-    else {
-        /* store new fcr31, masking unused bits */  
-        env->fcr31 = T0 & 0x0183FFFF;
+    return (xcpt & float_flag_inexact) >> 5 |
+           (xcpt & float_flag_underflow) >> 3 |
+           (xcpt & float_flag_overflow) >> 1 |
+           (xcpt & float_flag_divbyzero) << 1 |
+           (xcpt & float_flag_invalid) << 4;
+}
 
-        /* set rounding mode */
-        RESTORE_ROUNDING_MODE;
+inline char mips_ex_to_ieee(char xcpt)
+{
+    return (xcpt & FP_INEXACT) << 5 |
+           (xcpt & FP_UNDERFLOW) << 3 |
+           (xcpt & FP_OVERFLOW) << 1 |
+           (xcpt & FP_DIV0) >> 1 |
+           (xcpt & FP_INVALID) >> 4;
+}
 
-#ifndef CONFIG_SOFTFLOAT
-        /* no floating point exception for native float */
-        SET_FP_ENABLE(env->fcr31, 0);
-#endif
+inline void update_fcr31(void)
+{
+    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
+
+    SET_FP_CAUSE(env->fcr31, tmp);
+    if (GET_FP_ENABLE(env->fcr31) & tmp)
+        CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
+    else
+        UPDATE_FP_FLAGS(env->fcr31, tmp);
+}
+
+
+void op_cfc1 (void)
+{
+    switch (T1) {
+    case 0:
+        T0 = (int32_t)env->fcr0;
+        break;
+    case 25:
+        T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
+        break;
+    case 26:
+        T0 = env->fcr31 & 0x0003f07c;
+        break;
+    case 28:
+        T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
+        break;
+    default:
+        T0 = (int32_t)env->fcr31;
+        break;
     }
     DEBUG_FPU_STATE();
     RETURN();
 }
 
+void op_ctc1 (void)
+{
+    switch(T1) {
+    case 25:
+        if (T0 & 0xffffff00)
+            goto leave;
+        env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
+                     ((T0 & 0x1) << 23);
+        break;
+    case 26:
+        if (T0 & 0x007c0000)
+            goto leave;
+        env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
+        break;
+    case 28:
+        if (T0 & 0x007c0000)
+            goto leave;
+        env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
+                     ((T0 & 0x4) << 22);
+        break;
+    case 31:
+        if (T0 & 0x007c0000)
+            goto leave;
+        env->fcr31 = T0;
+        break;
+    default:
+        goto leave;
+    }
+    /* set rounding mode */
+    RESTORE_ROUNDING_MODE;
+    set_float_exception_flags(0, &env->fp_status);
+    if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
+        CALL_FROM_TB1(do_raise_exception, EXCP_FPE);
+ leave:
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
 void op_mfc1 (void)
 {
     T0 = WT0;
@@ -1614,55 +1768,219 @@
     RETURN();
 }
 
+void op_dmfc1 (void)
+{
+    T0 = DT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
+void op_dmtc1 (void)
+{
+    DT0 = T0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
+void op_mfhc1 (void)
+{
+    T0 = WTH0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
+void op_mthc1 (void)
+{
+    WTH0 = T0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
 /* Float support.
    Single precition routines have a "s" suffix, double precision a
-   "d" suffix.  */
+   "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
+   paired single lowwer "pl", paired single upper "pu".  */
 
 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
 
 FLOAT_OP(cvtd, s)
 {
-    FDT2 = float32_to_float64(WT0, &env->fp_status);
+    set_float_exception_flags(0, &env->fp_status);
+    FDT2 = float32_to_float64(FST0, &env->fp_status);
+    update_fcr31();
     DEBUG_FPU_STATE();
     RETURN();
 }
 FLOAT_OP(cvtd, w)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FDT2 = int32_to_float64(WT0, &env->fp_status);
+    update_fcr31();
     DEBUG_FPU_STATE();
     RETURN();
 }
+FLOAT_OP(cvtd, l)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    FDT2 = int64_to_float64(DT0, &env->fp_status);
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvtl, d)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    DT2 = float64_to_int64(FDT0, &env->fp_status);
+    update_fcr31();
+    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+        DT2 = 0x7fffffffffffffffULL;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvtl, s)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    DT2 = float32_to_int64(FST0, &env->fp_status);
+    update_fcr31();
+    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+        DT2 = 0x7fffffffffffffffULL;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvtps, s)
+{
+    WT2 = WT0;
+    WTH2 = WT1;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvtps, pw)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    FST2 = int32_to_float32(WT0, &env->fp_status);
+    FSTH2 = int32_to_float32(WTH0, &env->fp_status);
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvtpw, ps)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    WT2 = float32_to_int32(FST0, &env->fp_status);
+    WTH2 = float32_to_int32(FSTH0, &env->fp_status);
+    update_fcr31();
+    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+        WT2 = 0x7fffffff;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(cvts, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FST2 = float64_to_float32(FDT0, &env->fp_status);
+    update_fcr31();
     DEBUG_FPU_STATE();
     RETURN();
 }
 FLOAT_OP(cvts, w)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FST2 = int32_to_float32(WT0, &env->fp_status);
+    update_fcr31();
     DEBUG_FPU_STATE();
     RETURN();
 }
+FLOAT_OP(cvts, l)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    FST2 = int64_to_float32(DT0, &env->fp_status);
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvts, pl)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    WT2 = WT0;
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(cvts, pu)
+{
+    set_float_exception_flags(0, &env->fp_status);
+    WT2 = WTH0;
+    update_fcr31();
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(cvtw, s)
 {
+    set_float_exception_flags(0, &env->fp_status);
     WT2 = float32_to_int32(FST0, &env->fp_status);
+    update_fcr31();
+    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+        WT2 = 0x7fffffff;
     DEBUG_FPU_STATE();
     RETURN();
 }
 FLOAT_OP(cvtw, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     WT2 = float64_to_int32(FDT0, &env->fp_status);
+    update_fcr31();
+    if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+        WT2 = 0x7fffffff;
     DEBUG_FPU_STATE();
     RETURN();
 }
 
+FLOAT_OP(pll, ps)
+{
+    DT2 = ((uint64_t)WT0 << 32) | WT1;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(plu, ps)
+{
+    DT2 = ((uint64_t)WT0 << 32) | WTH1;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(pul, ps)
+{
+    DT2 = ((uint64_t)WTH0 << 32) | WT1;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(puu, ps)
+{
+    DT2 = ((uint64_t)WTH0 << 32) | WTH1;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
+FLOAT_OP(roundl, d)
+{
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    DT2 = float64_round_to_int(FDT0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(roundl, s)
+{
+    set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+    DT2 = float32_round_to_int(FST0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(roundw, d)
 {
     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
     WT2 = float64_round_to_int(FDT0, &env->fp_status);
     RESTORE_ROUNDING_MODE;
-
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -1675,6 +1993,18 @@
     RETURN();
 }
 
+FLOAT_OP(truncl, d)
+{
+    DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(truncl, s)
+{
+    DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(truncw, d)
 {
     WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
@@ -1688,12 +2018,27 @@
     RETURN();
 }
 
+FLOAT_OP(ceill, d)
+{
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    DT2 = float64_round_to_int(FDT0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(ceill, s)
+{
+    set_float_rounding_mode(float_round_up, &env->fp_status);
+    DT2 = float32_round_to_int(FST0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(ceilw, d)
 {
     set_float_rounding_mode(float_round_up, &env->fp_status);
     WT2 = float64_round_to_int(FDT0, &env->fp_status);
     RESTORE_ROUNDING_MODE;
-
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -1706,12 +2051,27 @@
     RETURN();
 }
 
+FLOAT_OP(floorl, d)
+{
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    DT2 = float64_round_to_int(FDT0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(floorl, s)
+{
+    set_float_rounding_mode(float_round_down, &env->fp_status);
+    DT2 = float32_round_to_int(FST0, &env->fp_status);
+    RESTORE_ROUNDING_MODE;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 FLOAT_OP(floorw, d)
 {
     set_float_rounding_mode(float_round_down, &env->fp_status);
     WT2 = float64_round_to_int(FDT0, &env->fp_status);
     RESTORE_ROUNDING_MODE;
-
     DEBUG_FPU_STATE();
     RETURN();
 }
@@ -1724,17 +2084,122 @@
     RETURN();
 }
 
+FLOAT_OP(movf, d)
+{
+    if (!(env->fcr31 & PARAM1))
+        DT2 = DT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movf, s)
+{
+    if (!(env->fcr31 & PARAM1))
+        WT2 = WT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movf, ps)
+{
+    if (!(env->fcr31 & PARAM1)) {
+        WT2 = WT0;
+        WTH2 = WTH0;
+    }
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movt, d)
+{
+    if (env->fcr31 & PARAM1)
+        DT2 = DT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movt, s)
+{
+    if (env->fcr31 & PARAM1)
+        WT2 = WT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movt, ps)
+{
+    if (env->fcr31 & PARAM1) {
+        WT2 = WT0;
+        WTH2 = WTH0;
+    }
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movz, d)
+{
+    if (!T0)
+        DT2 = DT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movz, s)
+{
+    if (!T0)
+        WT2 = WT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movz, ps)
+{
+    if (!T0) {
+        WT2 = WT0;
+        WTH2 = WTH0;
+    }
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movn, d)
+{
+    if (T0)
+        DT2 = DT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movn, s)
+{
+    if (T0)
+        WT2 = WT0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(movn, ps)
+{
+    if (T0) {
+        WT2 = WT0;
+        WTH2 = WTH0;
+    }
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+
 /* binary operations */
 #define FLOAT_BINOP(name) \
 FLOAT_OP(name, d)         \
 {                         \
+    set_float_exception_flags(0, &env->fp_status);            \
     FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
+    update_fcr31();       \
     DEBUG_FPU_STATE();    \
 }                         \
 FLOAT_OP(name, s)         \
 {                         \
+    set_float_exception_flags(0, &env->fp_status);            \
     FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
+    update_fcr31();       \
     DEBUG_FPU_STATE();    \
+}                         \
+FLOAT_OP(name, ps)        \
+{                         \
+    set_float_exception_flags(0, &env->fp_status);            \
+    FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
+    FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
+    update_fcr31();       \
+    DEBUG_FPU_STATE();    \
 }
 FLOAT_BINOP(add)
 FLOAT_BINOP(sub)
@@ -1742,6 +2207,32 @@
 FLOAT_BINOP(div)
 #undef FLOAT_BINOP
 
+/* ternary operations */
+#define FLOAT_TERNOP(name1, name2) \
+FLOAT_OP(name1 ## name2, d)        \
+{                                  \
+    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status);    \
+    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status);    \
+    DEBUG_FPU_STATE();             \
+}                                  \
+FLOAT_OP(name1 ## name2, s)        \
+{                                  \
+    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
+    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
+    DEBUG_FPU_STATE();             \
+}                                  \
+FLOAT_OP(name1 ## name2, ps)       \
+{                                  \
+    FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status);    \
+    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
+    FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status);    \
+    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
+    DEBUG_FPU_STATE();             \
+}
+FLOAT_TERNOP(mul, add)
+FLOAT_TERNOP(mul, sub)
+#undef FLOAT_TERNOP
+
 /* unary operations, modifying fp status  */
 #define FLOAT_UNOP(name)  \
 FLOAT_OP(name, d)         \
@@ -1753,6 +2244,12 @@
 {                         \
     FST2 = float32_ ## name(FST0, &env->fp_status);   \
     DEBUG_FPU_STATE();    \
+}                         \
+FLOAT_OP(name, ps)        \
+{                         \
+    FST2 = float32_ ## name(FST0, &env->fp_status);   \
+    FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
+    DEBUG_FPU_STATE();    \
 }
 FLOAT_UNOP(sqrt)
 #undef FLOAT_UNOP
@@ -1768,6 +2265,12 @@
 {                         \
     FST2 = float32_ ## name(FST0);   \
     DEBUG_FPU_STATE();    \
+}                         \
+FLOAT_OP(name, ps)        \
+{                         \
+    FST2 = float32_ ## name(FST0);   \
+    FSTH2 = float32_ ## name(FSTH0); \
+    DEBUG_FPU_STATE();    \
 }
 FLOAT_UNOP(abs)
 FLOAT_UNOP(chs)
@@ -1785,6 +2288,35 @@
     DEBUG_FPU_STATE();
     RETURN();
 }
+FLOAT_OP(mov, ps)
+{
+    FST2 = FST0;
+    FSTH2 = FSTH0;
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+FLOAT_OP(alnv, ps)
+{
+    switch (T0 & 0x7) {
+    case 0:
+        FST2 = FST0;
+        FSTH2 = FSTH0;
+        break;
+    case 4:
+#ifdef TARGET_WORDS_BIGENDIAN
+        FSTH2 = FST0;
+        FST2 = FSTH1;
+#else
+        FSTH2 = FST1;
+        FST2 = FSTH0;
+#endif
+        break;
+    default: /* unpredictable */
+        break;
+    }
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 
 #ifdef CONFIG_SOFTFLOAT
 #define clear_invalid() do {                                \
@@ -1798,100 +2330,203 @@
 
 extern void dump_fpu_s(CPUState *env);
 
-#define FOP_COND(fmt, op, sig, cond)           \
-void op_cmp_ ## fmt ## _ ## op (void)          \
+#define FOP_COND_D(op, cond)                   \
+void op_cmp_d_ ## op (void)                    \
 {                                              \
-    if (cond)                                  \
-        SET_FP_COND(env->fcr31);               \
+    int c = cond;                              \
+    update_fcr31();                            \
+    if (c)                                     \
+        SET_FP_COND(PARAM1, env);              \
     else                                       \
-        CLEAR_FP_COND(env->fcr31);             \
-    if (!sig)                                  \
-        clear_invalid();                       \
-    /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
+        CLEAR_FP_COND(PARAM1, env);            \
     DEBUG_FPU_STATE();                         \
     RETURN();                                  \
 }
 
-int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
+int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
 {
-    if (float64_is_nan(a) || float64_is_nan(b)) {
+    if (float64_is_signaling_nan(a) ||
+        float64_is_signaling_nan(b) ||
+        (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
         float_raise(float_flag_invalid, status);
         return 1;
-    }
-    else {
+    } else if (float64_is_nan(a) || float64_is_nan(b)) {
+        return 1;
+    } else {
         return 0;
     }
 }
 
-FOP_COND(d, f,   0,                                                      0) 
-FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
-FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called
- */
-FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
-FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
-FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
-FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
+ * but float*_is_unordered() is still called. */
+FOP_COND_D(f,   (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
+FOP_COND_D(un,  float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
+FOP_COND_D(eq,  !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_eq(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_lt(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status)  || float64_le(FDT0, FDT1, &env->fp_status))
+/* NOTE: the comma operator will make "cond" to eval to false,
+ * but float*_is_unordered() is still called. */
+FOP_COND_D(sf,  (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
+FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
+FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_eq(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(lt,  !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_lt(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(le,  !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status)  || float64_le(FDT0, FDT1, &env->fp_status))
 
-flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
+#define FOP_COND_S(op, cond)                   \
+void op_cmp_s_ ## op (void)                    \
+{                                              \
+    int c = cond;                              \
+    update_fcr31();                            \
+    if (c)                                     \
+        SET_FP_COND(PARAM1, env);              \
+    else                                       \
+        CLEAR_FP_COND(PARAM1, env);            \
+    DEBUG_FPU_STATE();                         \
+    RETURN();                                  \
+}
+
+flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
 {
-    extern flag float32_is_nan( float32 a );
-    if (float32_is_nan(a) || float32_is_nan(b)) {
+    extern flag float32_is_nan(float32 a);
+    if (float32_is_signaling_nan(a) ||
+        float32_is_signaling_nan(b) ||
+        (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
         float_raise(float_flag_invalid, status);
         return 1;
-    }
-    else {
+    } else if (float32_is_nan(a) || float32_is_nan(b)) {
+        return 1;
+    } else {
         return 0;
     }
 }
 
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called
- */
-FOP_COND(s, f,   0,                                                      0) 
-FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
-FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
-FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
+ * but float*_is_unordered() is still called. */
+FOP_COND_S(f,   (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
+FOP_COND_S(un,  float32_is_unordered(0, FST1, FST0, &env->fp_status))
+FOP_COND_S(eq,  !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
+FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_eq(FST0, FST1, &env->fp_status))
+FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
+FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_lt(FST0, FST1, &env->fp_status))
+FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
+FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status)  || float32_le(FST0, FST1, &env->fp_status))
 /* NOTE: the comma operator will make "cond" to eval to false,
- * but float*_is_unordered() is still called
- */
-FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
-FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
-FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
-FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
+ * but float*_is_unordered() is still called. */
+FOP_COND_S(sf,  (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
+FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
+FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
+FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_eq(FST0, FST1, &env->fp_status))
+FOP_COND_S(lt,  !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
+FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_lt(FST0, FST1, &env->fp_status))
+FOP_COND_S(le,  !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
+FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status)  || float32_le(FST0, FST1, &env->fp_status))
 
+#define FOP_COND_PS(op, condl, condh)          \
+void op_cmp_ps_ ## op (void)                   \
+{                                              \
+    int cl = condl;                            \
+    int ch = condh;                            \
+    update_fcr31();                            \
+    if (cl)                                    \
+        SET_FP_COND(PARAM1, env);              \
+    else                                       \
+        CLEAR_FP_COND(PARAM1, env);            \
+    if (ch)                                    \
+        SET_FP_COND(PARAM1 + 1, env);          \
+    else                                       \
+        CLEAR_FP_COND(PARAM1 + 1, env);        \
+    DEBUG_FPU_STATE();                         \
+    RETURN();                                  \
+}
+
+/* NOTE: the comma operator will make "cond" to eval to false,
+ * but float*_is_unordered() is still called. */
+FOP_COND_PS(f,   (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
+                 (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
+FOP_COND_PS(un,  float32_is_unordered(0, FST1, FST0, &env->fp_status),
+                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
+FOP_COND_PS(eq,  !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_eq(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_eq(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_lt(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_lt(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status)   && float32_le(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status)    || float32_le(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status)  || float32_le(FSTH0, FSTH1, &env->fp_status))
+/* NOTE: the comma operator will make "cond" to eval to false,
+ * but float*_is_unordered() is still called. */
+FOP_COND_PS(sf,  (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
+                 (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
+FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
+                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
+FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_eq(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_eq(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(lt,  !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_lt(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_lt(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(le,  !float32_is_unordered(1, FST1, FST0, &env->fp_status)   && float32_le(FST0, FST1, &env->fp_status),
+                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status)    || float32_le(FST0, FST1, &env->fp_status),
+                 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status)  || float32_le(FSTH0, FSTH1, &env->fp_status))
+
 void op_bc1f (void)
 {
-    T0 = ! IS_FP_COND_SET(env->fcr31);
+    T0 = !IS_FP_COND_SET(PARAM1, env);
     DEBUG_FPU_STATE();
     RETURN();
 }
+void op_bc1fany2 (void)
+{
+    T0 = (!IS_FP_COND_SET(PARAM1, env) ||
+          !IS_FP_COND_SET(PARAM1 + 1, env));
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+void op_bc1fany4 (void)
+{
+    T0 = (!IS_FP_COND_SET(PARAM1, env) ||
+          !IS_FP_COND_SET(PARAM1 + 1, env) ||
+          !IS_FP_COND_SET(PARAM1 + 2, env) ||
+          !IS_FP_COND_SET(PARAM1 + 3, env));
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 
 void op_bc1t (void)
 {
-    T0 = IS_FP_COND_SET(env->fcr31);
+    T0 = IS_FP_COND_SET(PARAM1, env);
     DEBUG_FPU_STATE();
     RETURN();
 }
-#endif /* MIPS_USES_FPU */
+void op_bc1tany2 (void)
+{
+    T0 = (IS_FP_COND_SET(PARAM1, env) ||
+          IS_FP_COND_SET(PARAM1 + 1, env));
+    DEBUG_FPU_STATE();
+    RETURN();
+}
+void op_bc1tany4 (void)
+{
+    T0 = (IS_FP_COND_SET(PARAM1, env) ||
+          IS_FP_COND_SET(PARAM1 + 1, env) ||
+          IS_FP_COND_SET(PARAM1 + 2, env) ||
+          IS_FP_COND_SET(PARAM1 + 3, env));
+    DEBUG_FPU_STATE();
+    RETURN();
+}
 
 #if defined(MIPS_USES_R4K_TLB)
 void op_tlbwi (void)
@@ -1920,6 +2555,13 @@
 #endif
 
 /* Specials */
+#if defined (CONFIG_USER_ONLY)
+void op_tls_value (void)
+{
+    T0 = env->tls_value;
+}
+#endif
+
 void op_pmon (void)
 {
     CALL_FROM_TB1(do_pmon, PARAM1);
@@ -1928,43 +2570,24 @@
 
 void op_di (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 & ~(1 << CP0St_IE);
-    if (val != T0) {
-        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-        env->CP0_Status = val;
-    }
+    env->CP0_Status = T0 & ~(1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
 void op_ei (void)
 {
-    uint32_t val;
-
     T0 = env->CP0_Status;
-    val = T0 | (1 << CP0St_IE);
-    if (val != T0) {
-       const uint32_t mask = 0x0000FF00;
-
-       env->CP0_Status = val;
-       if (!(env->hflags & MIPS_HFLAG_EXL) &&
-           !(env->hflags & MIPS_HFLAG_ERL) &&
-           !(env->hflags & MIPS_HFLAG_DM) &&
-           (env->CP0_Status & env->CP0_Cause & mask)) {
-               env->interrupt_request |= CPU_INTERRUPT_HARD;
-               if (logfile)
-                   CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
-       }
-    }
+    env->CP0_Status = T0 | (1 << CP0St_IE);
+    CALL_FROM_TB1(cpu_mips_update_irq, env);
     RETURN();
 }
 
 void op_trap (void)
 {
     if (T0) {
-        CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
+        CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
     }
     RETURN();
 }
@@ -1981,63 +2604,88 @@
     RETURN();
 }
 
-void debug_eret (void);
+void debug_pre_eret (void);
+void debug_post_eret (void);
 void op_eret (void)
 {
-    CALL_FROM_TB0(debug_eret);
-    if (env->hflags & MIPS_HFLAG_ERL) {
+    if (loglevel & CPU_LOG_EXEC)
+        CALL_FROM_TB0(debug_pre_eret);
+    if (env->CP0_Status & (1 << CP0St_ERL)) {
         env->PC = env->CP0_ErrorEPC;
-        env->hflags &= ~MIPS_HFLAG_ERL;
-	env->CP0_Status &= ~(1 << CP0St_ERL);
+        env->CP0_Status &= ~(1 << CP0St_ERL);
     } else {
         env->PC = env->CP0_EPC;
-        env->hflags &= ~MIPS_HFLAG_EXL;
-	env->CP0_Status &= ~(1 << CP0St_EXL);
+        env->CP0_Status &= ~(1 << CP0St_EXL);
     }
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (env->CP0_Status & (1 << CP0St_UM)))
+        env->hflags |= MIPS_HFLAG_UM;
+    if (loglevel & CPU_LOG_EXEC)
+        CALL_FROM_TB0(debug_post_eret);
     env->CP0_LLAddr = 1;
     RETURN();
 }
 
 void op_deret (void)
 {
-    CALL_FROM_TB0(debug_eret);
+    if (loglevel & CPU_LOG_EXEC)
+        CALL_FROM_TB0(debug_pre_eret);
     env->PC = env->CP0_DEPC;
+    env->hflags |= MIPS_HFLAG_DM;
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (env->CP0_Status & (1 << CP0St_UM)))
+        env->hflags |= MIPS_HFLAG_UM;
+    if (loglevel & CPU_LOG_EXEC)
+        CALL_FROM_TB0(debug_post_eret);
+    env->CP0_LLAddr = 1;
     RETURN();
 }
 
 void op_rdhwr_cpunum(void)
 {
-    if (env->CP0_HWREna & (1 << 0))
-       T0 = env->CP0_EBase & 0x2ff;
+    if (!(env->hflags & MIPS_HFLAG_UM) ||
+        (env->CP0_HWREna & (1 << 0)) ||
+        (env->CP0_Status & (1 << CP0St_CU0)))
+        T0 = env->CP0_EBase & 0x3ff;
     else
-       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
+        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
     RETURN();
 }
 
 void op_rdhwr_synci_step(void)
 {
-    if (env->CP0_HWREna & (1 << 1))
-       T0 = env->SYNCI_Step;
+    if (!(env->hflags & MIPS_HFLAG_UM) ||
+        (env->CP0_HWREna & (1 << 1)) ||
+        (env->CP0_Status & (1 << CP0St_CU0)))
+        T0 = env->SYNCI_Step;
     else
-       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
+        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
     RETURN();
 }
 
 void op_rdhwr_cc(void)
 {
-    if (env->CP0_HWREna & (1 << 2))
-       T0 = env->CP0_Count;
+    if (!(env->hflags & MIPS_HFLAG_UM) ||
+        (env->CP0_HWREna & (1 << 2)) ||
+        (env->CP0_Status & (1 << CP0St_CU0)))
+        T0 = env->CP0_Count;
     else
-       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
+        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
     RETURN();
 }
 
 void op_rdhwr_ccres(void)
 {
-    if (env->CP0_HWREna & (1 << 3))
-       T0 = env->CCRes;
+    if (!(env->hflags & MIPS_HFLAG_UM) ||
+        (env->CP0_HWREna & (1 << 3)) ||
+        (env->CP0_Status & (1 << CP0St_CU0)))
+        T0 = env->CCRes;
     else
-       CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
+        CALL_FROM_TB1(do_raise_exception, EXCP_RI);
     RETURN();
 }
 
@@ -2053,6 +2701,30 @@
     RETURN();
 }
 
+void op_save_fp_status (void)
+{
+    union fps {
+        uint32_t i;
+        float_status f;
+    } fps;
+    fps.i = PARAM1;
+    env->fp_status = fps.f;
+    RETURN();
+}
+
+void op_interrupt_restart (void)
+{
+    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
+        !(env->CP0_Status & (1 << CP0St_ERL)) &&
+        !(env->hflags & MIPS_HFLAG_DM) &&
+        (env->CP0_Status & (1 << CP0St_IE)) &&
+        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
+        env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
+        CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
+    }
+    RETURN();
+}
+
 void op_raise_exception (void)
 {
     CALL_FROM_TB1(do_raise_exception, PARAM1);
@@ -2084,7 +2756,7 @@
     unsigned int pos = PARAM1;
     unsigned int size = PARAM2;
 
-    T0 = ((uint32_t)T1 >> pos) & ((1 << size) - 1);
+    T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
     RETURN();
 }
 
@@ -2092,9 +2764,9 @@
 {
     unsigned int pos = PARAM1;
     unsigned int size = PARAM2;
-    target_ulong mask = ((1 << size) - 1) << pos;
+    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
 
-    T0 = (T2 & ~mask) | (((uint32_t)T1 << pos) & mask);
+    T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
     RETURN();
 }
 
@@ -2104,13 +2776,13 @@
     RETURN();
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 void op_dext(void)
 {
     unsigned int pos = PARAM1;
     unsigned int size = PARAM2;
 
-    T0 = (T1 >> pos) & ((1 << size) - 1);
+    T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
     RETURN();
 }
 
@@ -2118,9 +2790,9 @@
 {
     unsigned int pos = PARAM1;
     unsigned int size = PARAM2;
-    target_ulong mask = ((1 << size) - 1) << pos;
+    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
 
-    T0 = (T2 & ~mask) | ((T1 << pos) & mask);
+    T0 = (T0 & ~mask) | ((T1 << pos) & mask);
     RETURN();
 }
 

Modified: trunk/src/host/qemu-neo1973/target-mips/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -17,10 +17,9 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include <stdlib.h>
 #include "exec.h"
 
-#define MIPS_DEBUG_DISAS
-
 #define GETPC() (__builtin_return_address(0))
 
 /*****************************************************************************/
@@ -56,12 +55,17 @@
   cpu_restore_state (tb, env, pc, NULL);
 }
 
-void do_raise_exception_direct (uint32_t exception)
+void do_raise_exception_direct_err (uint32_t exception, int error_code)
 {
     do_restore_state (GETPC ());
-    do_raise_exception_err (exception, 0);
+    do_raise_exception_err (exception, error_code);
 }
 
+void do_raise_exception_direct (uint32_t exception)
+{
+    do_raise_exception_direct_err (exception, 0);
+}
+
 #define MEMSUFFIX _raw
 #include "op_helper_mem.c"
 #undef MEMSUFFIX
@@ -74,7 +78,7 @@
 #undef MEMSUFFIX
 #endif
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 #if TARGET_LONG_BITS > HOST_LONG_BITS
 /* Those might call libgcc functions.  */
 void do_dsll (void)
@@ -114,8 +118,7 @@
     if (T1) {
        tmp = T0 << (0x40 - T1);
        T0 = (T0 >> T1) | tmp;
-    } else
-       T0 = T1;
+    }
 }
 
 void do_drotr32 (void)
@@ -125,8 +128,7 @@
     if (T1) {
        tmp = T0 << (0x40 - (32 + T1));
        T0 = (T0 >> (32 + T1)) | tmp;
-    } else
-       T0 = T1;
+    }
 }
 
 void do_dsllv (void)
@@ -156,7 +158,7 @@
        T0 = T1;
 }
 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-#endif /* MIPS_HAS_MIPS64 */
+#endif /* TARGET_MIPS64 */
 
 /* 64 bits arithmetic for 32 bits hosts */
 #if TARGET_LONG_BITS > HOST_LONG_BITS
@@ -214,32 +216,48 @@
 }
 #endif
 
-#ifdef MIPS_HAS_MIPS64
+#if HOST_LONG_BITS < 64
+void do_div (void)
+{
+    /* 64bit datatypes because we may see overflow/underflow. */
+    if (T1 != 0) {
+        env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
+        env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
+    }
+}
+#endif
+
+#ifdef TARGET_MIPS64
 void do_dmult (void)
 {
+    env->LO = (int64_t)T0 * (int64_t)T1;
     /* XXX */
-    set_HILO((int64_t)T0 * (int64_t)T1);
+    env->HI = (env->LO | (1ULL << 63)) ? ~0ULL : 0ULL;
 }
 
 void do_dmultu (void)
 {
+    env->LO = T0 * T1;
     /* XXX */
-    set_HILO((uint64_t)T0 * (uint64_t)T1);
+    env->HI = 0;
 }
 
 void do_ddiv (void)
 {
     if (T1 != 0) {
-        env->LO = (int64_t)T0 / (int64_t)T1;
-        env->HI = (int64_t)T0 % (int64_t)T1;
+        lldiv_t res = lldiv((int64_t)T0, (int64_t)T1);
+        env->LO = res.quot;
+        env->HI = res.rem;
     }
 }
 
 void do_ddivu (void)
 {
     if (T1 != 0) {
-        env->LO = T0 / T1;
-        env->HI = T0 % T1;
+        /* XXX: lldivu? */
+        lldiv_t res = lldiv(T0, T1);
+        env->LO = (uint64_t)res.quot;
+        env->HI = (uint64_t)res.rem;
     }
 }
 #endif
@@ -265,6 +283,11 @@
     cpu_abort(env, "mtc0 compare\n");
 }
 
+void cpu_mips_update_irq(CPUState *env)
+{
+    cpu_abort(env, "mtc0 status / mtc0 cause\n");
+}
+
 void do_mtc0_status_debug(uint32_t old, uint32_t val)
 {
     cpu_abort(env, "mtc0 status debug\n");
@@ -315,10 +338,12 @@
 
 void do_mtc0_status_debug(uint32_t old, uint32_t val)
 {
-    const uint32_t mask = 0x0000FF00;
-    fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
-            old, val, env->CP0_Cause, old & mask, val & mask,
-            env->CP0_Cause & mask);
+    fprintf(logfile, "Status %08x (%08x) => %08x (%08x) Cause %08x",
+            old, old & env->CP0_Cause & CP0Ca_IP_mask,
+            val, val & env->CP0_Cause & CP0Ca_IP_mask,
+            env->CP0_Cause);
+    (env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile)
+                                  : fputs("\n", logfile);
 }
 
 void do_mtc0_status_irqraise_debug(void)
@@ -326,9 +351,6 @@
     fprintf(logfile, "Raise pending IRQs\n");
 }
 
-#ifdef MIPS_USES_FPU
-#include "softfloat.h"
-
 void fpu_handle_exception(void)
 {
 #ifdef CONFIG_SOFTFLOAT
@@ -365,7 +387,6 @@
     SET_FP_CAUSE(env->fcr31, 0);
 #endif
 }
-#endif /* MIPS_USES_FPU */
 
 /* TLB management */
 #if defined(MIPS_USES_R4K_TLB)
@@ -373,7 +394,7 @@
 {
     /* Flush qemu's TLB and discard all shadowed entries.  */
     tlb_flush (env, flush_global);
-    env->tlb_in_use = MIPS_TLB_NB;
+    env->tlb_in_use = env->nb_tlb;
 }
 
 static void mips_tlb_flush_extra (CPUState *env, int first)
@@ -387,16 +408,12 @@
 static void fill_tlb (int idx)
 {
     tlb_t *tlb;
-    int size;
 
     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
     tlb = &env->tlb[idx];
-    tlb->VPN = env->CP0_EntryHi & (int32_t)0xFFFFE000;
+    tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF;
     tlb->ASID = env->CP0_EntryHi & 0xFF;
-    size = env->CP0_PageMask >> 13;
-    size = 4 * (size + 1);
-    tlb->end = tlb->VPN + (1 << (8 + size));
-    tlb->end2 = tlb->end + (1 << (8 + size));
+    tlb->PageMask = env->CP0_PageMask;
     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
     tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
@@ -413,12 +430,10 @@
     /* Discard cached TLB entries.  We could avoid doing this if the
        tlbwi is just upgrading access permissions on the current entry;
        that might be a further win.  */
-    mips_tlb_flush_extra (env, MIPS_TLB_NB);
+    mips_tlb_flush_extra (env, env->nb_tlb);
 
-    /* Wildly undefined effects for CP0_index containing a too high value and
-       MIPS_TLB_NB not being a power of two.  But so does real silicon.  */
-    invalidate_tlb(env, env->CP0_index & (MIPS_TLB_NB - 1), 0);
-    fill_tlb(env->CP0_index & (MIPS_TLB_NB - 1));
+    invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
+    fill_tlb(env->CP0_Index % env->nb_tlb);
 }
 
 void do_tlbwr (void)
@@ -438,18 +453,18 @@
 
     tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
     ASID = env->CP0_EntryHi & 0xFF;
-    for (i = 0; i < MIPS_TLB_NB; i++) {
+    for (i = 0; i < env->nb_tlb; i++) {
         tlb = &env->tlb[i];
         /* Check ASID, virtual page number & size */
         if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
             /* TLB match */
-            env->CP0_index = i;
+            env->CP0_Index = i;
             break;
         }
     }
-    if (i == MIPS_TLB_NB) {
+    if (i == env->nb_tlb) {
         /* No match.  Discard any shadow entries, if any of them match.  */
-        for (i = MIPS_TLB_NB; i < env->tlb_in_use; i++) {
+        for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
 	    tlb = &env->tlb[i];
 
 	    /* Check ASID, virtual page number & size */
@@ -459,7 +474,7 @@
 	    }
 	}
 
-        env->CP0_index |= 0x80000000;
+        env->CP0_Index |= 0x80000000;
     }
 }
 
@@ -467,20 +482,18 @@
 {
     tlb_t *tlb;
     uint8_t ASID;
-    int size;
 
     ASID = env->CP0_EntryHi & 0xFF;
-    tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
+    tlb = &env->tlb[env->CP0_Index % env->nb_tlb];
 
     /* If this will change the current ASID, flush qemu's TLB.  */
     if (ASID != tlb->ASID)
         cpu_mips_tlb_flush (env, 1);
 
-    mips_tlb_flush_extra(env, MIPS_TLB_NB);
+    mips_tlb_flush_extra(env, env->nb_tlb);
 
     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
-    size = (tlb->end - tlb->VPN) >> 12;
-    env->CP0_PageMask = (size - 1) << 13;
+    env->CP0_PageMask = tlb->PageMask;
     env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                         (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
     env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
@@ -493,26 +506,42 @@
 void dump_ldst (const unsigned char *func)
 {
     if (loglevel)
-        fprintf(logfile, "%s => " TLSZ " " TLSZ "\n", __func__, T0, T1);
+        fprintf(logfile, "%s => " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, T0, T1);
 }
 
 void dump_sc (void)
 {
     if (loglevel) {
-        fprintf(logfile, "%s " TLSZ " at " TLSZ " (" TLSZ ")\n", __func__,
+        fprintf(logfile, "%s " TARGET_FMT_lx " at " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", __func__,
                 T1, T0, env->CP0_LLAddr);
     }
 }
 
-void debug_eret (void)
+void debug_pre_eret (void)
 {
-    if (loglevel) {
-        fprintf(logfile, "ERET: pc " TLSZ " EPC " TLSZ " ErrorEPC " TLSZ " (%d)\n",
-                env->PC, env->CP0_EPC, env->CP0_ErrorEPC,
-                env->hflags & MIPS_HFLAG_ERL ? 1 : 0);
-    }
+    fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
+            env->PC, env->CP0_EPC);
+    if (env->CP0_Status & (1 << CP0St_ERL))
+        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
+    if (env->hflags & MIPS_HFLAG_DM)
+        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
+    fputs("\n", logfile);
 }
 
+void debug_post_eret (void)
+{
+    fprintf(logfile, "  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
+            env->PC, env->CP0_EPC);
+    if (env->CP0_Status & (1 << CP0St_ERL))
+        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
+    if (env->hflags & MIPS_HFLAG_DM)
+        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
+    if (env->hflags & MIPS_HFLAG_UM)
+        fputs(", UM\n", logfile);
+    else
+        fputs("\n", logfile);
+}
+
 void do_pmon (int function)
 {
     function /= 2;

Modified: trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/op_helper_mem.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -28,7 +28,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - %08x " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, sav, tmp, T1, T0);
     }
 #endif
@@ -57,7 +57,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - %08x " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - %08x " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, sav, tmp, T1, T0);
     }
 #endif
@@ -86,7 +86,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => %08x\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
                 __func__, T0, sav, T1, tmp);
     }
 #endif
@@ -116,7 +116,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => %08x\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => %08x\n",
                 __func__, T0, sav, T1, tmp);
     }
 #endif
@@ -124,12 +124,12 @@
     return tmp;
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 
-# ifdef TARGET_WORDS_BIGENDIAN
-#define GET_LMASK64(v) ((v) & 4)
+#ifdef TARGET_WORDS_BIGENDIAN
+#define GET_LMASK64(v) ((v) & 7)
 #else
-#define GET_LMASK64(v) (((v) & 4) ^ 4)
+#define GET_LMASK64(v) (((v) & 7) ^ 7)
 #endif
 
 void glue(do_ldl, MEMSUFFIX) (uint64_t tmp)
@@ -166,7 +166,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, sav, tmp, T1, T0);
     }
 #endif
@@ -207,7 +207,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, sav, tmp, T1, T0);
     }
 #endif
@@ -248,7 +248,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, T0, sav, T1, tmp);
     }
 #endif
@@ -290,7 +290,7 @@
     }
 #if defined (DEBUG_OP)
     if (logfile) {
-        fprintf(logfile, "%s: " TLSZ " - " TLSZ " " TLSZ " => " TLSZ "\n",
+        fprintf(logfile, "%s: " TARGET_FMT_lx " - " TARGET_FMT_lx " " TARGET_FMT_lx " => " TARGET_FMT_lx "\n",
                 __func__, T0, sav, T1, tmp);
     }
 #endif
@@ -298,4 +298,4 @@
     return tmp;
 }
 
-#endif /* MIPS_HAS_MIPS64 */
+#endif /* TARGET_MIPS64 */

Modified: trunk/src/host/qemu-neo1973/target-mips/op_mem.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_mem.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/op_mem.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -117,6 +117,10 @@
 void glue(op_sc, MEMSUFFIX) (void)
 {
     CALL_FROM_TB0(dump_sc);
+    if (T0 & 0x3) {
+        env->CP0_BadVAddr = T0;
+        CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
+    }
     if (T0 == env->CP0_LLAddr) {
         glue(stl, MEMSUFFIX)(T0, T1);
         T0 = 1;
@@ -126,7 +130,7 @@
     RETURN();
 }
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 void glue(op_ld, MEMSUFFIX) (void)
 {
     T0 = glue(ldq, MEMSUFFIX)(T0);
@@ -182,6 +186,10 @@
 void glue(op_scd, MEMSUFFIX) (void)
 {
     CALL_FROM_TB0(dump_sc);
+    if (T0 & 0x7) {
+        env->CP0_BadVAddr = T0;
+        CALL_FROM_TB1(do_raise_exception, EXCP_AdES);
+    }
     if (T0 == env->CP0_LLAddr) {
         glue(stq, MEMSUFFIX)(T0, T1);
         T0 = 1;
@@ -190,9 +198,8 @@
     }
     RETURN();
 }
-#endif /* MIPS_HAS_MIPS64 */
+#endif /* TARGET_MIPS64 */
 
-#ifdef MIPS_USES_FPU
 void glue(op_lwc1, MEMSUFFIX) (void)
 {
     WT0 = glue(ldl, MEMSUFFIX)(T0);
@@ -213,4 +220,35 @@
     glue(stq, MEMSUFFIX)(T0, DT0);
     RETURN();
 }
-#endif
+void glue(op_lwxc1, MEMSUFFIX) (void)
+{
+    WT0 = glue(ldl, MEMSUFFIX)(T0 + T1);
+    RETURN();
+}
+void glue(op_swxc1, MEMSUFFIX) (void)
+{
+    glue(stl, MEMSUFFIX)(T0 + T1, WT0);
+    RETURN();
+}
+void glue(op_ldxc1, MEMSUFFIX) (void)
+{
+    DT0 = glue(ldq, MEMSUFFIX)(T0 + T1);
+    RETURN();
+}
+void glue(op_sdxc1, MEMSUFFIX) (void)
+{
+    glue(stq, MEMSUFFIX)(T0 + T1, DT0);
+    RETURN();
+}
+void glue(op_luxc1, MEMSUFFIX) (void)
+{
+    /* XXX: is defined as unaligned */
+    DT0 = glue(ldq, MEMSUFFIX)(T0 + T1);
+    RETURN();
+}
+void glue(op_suxc1, MEMSUFFIX) (void)
+{
+    /* XXX: is defined as unaligned */
+    glue(stq, MEMSUFFIX)(T0 + T1, DT0);
+    RETURN();
+}

Modified: trunk/src/host/qemu-neo1973/target-mips/op_template.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/op_template.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/op_template.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -54,7 +54,7 @@
 #define SET_RESET(treg, tregname)        \
     void glue(op_set, tregname)(void)    \
     {                                    \
-        treg = PARAM1;                   \
+        treg = (int32_t)PARAM1;          \
         RETURN();                        \
     }                                    \
     void glue(op_reset, tregname)(void)  \

Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -305,7 +305,7 @@
 };
 
 /* MFMC0 opcodes */
-#define MASK_MFMC0(op)     MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5)))
+#define MASK_MFMC0(op)     MASK_CP0(op) | (op & 0xFFFF)
 
 enum {
     OPC_DI       = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
@@ -333,20 +333,26 @@
     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
     OPC_CFC1     = (0x02 << 21) | OPC_CP1,
-    OPC_MFHCI    = (0x03 << 21) | OPC_CP1,
+    OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
     OPC_MTC1     = (0x04 << 21) | OPC_CP1,
     OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
     OPC_CTC1     = (0x06 << 21) | OPC_CP1,
-    OPC_MTHCI    = (0x07 << 21) | OPC_CP1,
+    OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
+    OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
+    OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
     OPC_S_FMT    = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
     OPC_D_FMT    = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
     OPC_E_FMT    = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
     OPC_Q_FMT    = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
     OPC_W_FMT    = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
     OPC_L_FMT    = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
+    OPC_PS_FMT   = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
 };
 
+#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
+#define MASK_BC1(op)            MASK_CP1(op) | (op & (0x3 << 16))
+
 enum {
     OPC_BC1F     = (0x00 << 16) | OPC_BC1,
     OPC_BC1T     = (0x01 << 16) | OPC_BC1,
@@ -354,12 +360,56 @@
     OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
 };
 
-#define MASK_CP1_BCOND(op)      MASK_CP1(op) | (op & (0x3 << 16))
-#define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
+enum {
+    OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
+    OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
+};
 
+enum {
+    OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
+    OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
+};
+
 #define MASK_CP2(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
-#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & (0x1F << 21))
 
+enum {
+    OPC_MFC2    = (0x00 << 21) | OPC_CP2,
+    OPC_DMFC2   = (0x01 << 21) | OPC_CP2,
+    OPC_CFC2    = (0x02 << 21) | OPC_CP2,
+    OPC_MFHC2   = (0x03 << 21) | OPC_CP2,
+    OPC_MTC2    = (0x04 << 21) | OPC_CP2,
+    OPC_DMTC2   = (0x05 << 21) | OPC_CP2,
+    OPC_CTC2    = (0x06 << 21) | OPC_CP2,
+    OPC_MTHC2   = (0x07 << 21) | OPC_CP2,
+    OPC_BC2     = (0x08 << 21) | OPC_CP2,
+};
+
+#define MASK_CP3(op)       MASK_OP_MAJOR(op) | (op & 0x3F)
+
+enum {
+    OPC_LWXC1   = 0x00 | OPC_CP3,
+    OPC_LDXC1   = 0x01 | OPC_CP3,
+    OPC_LUXC1   = 0x05 | OPC_CP3,
+    OPC_SWXC1   = 0x08 | OPC_CP3,
+    OPC_SDXC1   = 0x09 | OPC_CP3,
+    OPC_SUXC1   = 0x0D | OPC_CP3,
+    OPC_PREFX   = 0x0F | OPC_CP3,
+    OPC_ALNV_PS = 0x1E | OPC_CP3,
+    OPC_MADD_S  = 0x20 | OPC_CP3,
+    OPC_MADD_D  = 0x21 | OPC_CP3,
+    OPC_MADD_PS = 0x26 | OPC_CP3,
+    OPC_MSUB_S  = 0x28 | OPC_CP3,
+    OPC_MSUB_D  = 0x29 | OPC_CP3,
+    OPC_MSUB_PS = 0x2E | OPC_CP3,
+    OPC_NMADD_S = 0x30 | OPC_CP3,
+    OPC_NMADD_D = 0x32 | OPC_CP3,
+    OPC_NMADD_PS= 0x36 | OPC_CP3,
+    OPC_NMSUB_S = 0x38 | OPC_CP3,
+    OPC_NMSUB_D = 0x39 | OPC_CP3,
+    OPC_NMSUB_PS= 0x3E | OPC_CP3,
+};
+
+
 const unsigned char *regnames[] =
     { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
@@ -367,20 +417,20 @@
       "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
 
 /* Warning: no function for r0 register (hard wired to zero) */
-#define GEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [32] = {                                     \
-NULL,       NAME ## 1, NAME ## 2, NAME ## 3,                                  \
-NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,                                  \
-NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,                                \
-NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
-NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
-NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
-NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
-NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
-};                                                                            \
-static inline void func(int n)                                                \
-{                                                                             \
-    NAME ## _table[n]();                                                      \
+#define GEN32(func, NAME)                        \
+static GenOpFunc *NAME ## _table [32] = {        \
+NULL,       NAME ## 1, NAME ## 2, NAME ## 3,     \
+NAME ## 4,  NAME ## 5, NAME ## 6, NAME ## 7,     \
+NAME ## 8,  NAME ## 9, NAME ## 10, NAME ## 11,   \
+NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,  \
+NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,  \
+NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,  \
+NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
+NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
+};                                               \
+static inline void func(int n)                   \
+{                                                \
+    NAME ## _table[n]();                         \
 }
 
 /* General purpose registers moves */
@@ -391,66 +441,57 @@
 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
 
-#ifdef MIPS_USES_FPU
-
 static const char *fregnames[] =
     { "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
 
-# define SFGEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [32] = {                                     \
-NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,                                \
-NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,                                \
-NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,                               \
-NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
-NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
-NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
-NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
-NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
-};                                                                            \
-static inline void func(int n)                                                \
-{                                                                             \
-    NAME ## _table[n]();                                                      \
+#define FGEN32(func, NAME)                       \
+static GenOpFunc *NAME ## _table [32] = {        \
+NAME ## 0,  NAME ## 1,  NAME ## 2,  NAME ## 3,   \
+NAME ## 4,  NAME ## 5,  NAME ## 6,  NAME ## 7,   \
+NAME ## 8,  NAME ## 9,  NAME ## 10, NAME ## 11,  \
+NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,  \
+NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,  \
+NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,  \
+NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,  \
+NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,  \
+};                                               \
+static inline void func(int n)                   \
+{                                                \
+    NAME ## _table[n]();                         \
 }
 
-# define DFGEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [32] = {                                     \
-NAME ## 0,  0, NAME ## 2,  0,                                                 \
-NAME ## 4,  0, NAME ## 6,  0,                                                 \
-NAME ## 8,  0, NAME ## 10, 0,                                                 \
-NAME ## 12, 0, NAME ## 14, 0,                                                 \
-NAME ## 16, 0, NAME ## 18, 0,                                                 \
-NAME ## 20, 0, NAME ## 22, 0,                                                 \
-NAME ## 24, 0, NAME ## 26, 0,                                                 \
-NAME ## 28, 0, NAME ## 30, 0,                                                 \
-};                                                                            \
-static inline void func(int n)                                                \
-{                                                                             \
-    NAME ## _table[n]();                                                      \
-}
+FGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
+FGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
 
-SFGEN32(gen_op_load_fpr_WT0,  gen_op_load_fpr_WT0_fpr);
-SFGEN32(gen_op_store_fpr_WT0, gen_op_store_fpr_WT0_fpr);
+FGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
+FGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
 
-SFGEN32(gen_op_load_fpr_WT1,  gen_op_load_fpr_WT1_fpr);
-SFGEN32(gen_op_store_fpr_WT1, gen_op_store_fpr_WT1_fpr);
+FGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
+FGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
 
-SFGEN32(gen_op_load_fpr_WT2,  gen_op_load_fpr_WT2_fpr);
-SFGEN32(gen_op_store_fpr_WT2, gen_op_store_fpr_WT2_fpr);
+FGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
+FGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
 
-DFGEN32(gen_op_load_fpr_DT0,  gen_op_load_fpr_DT0_fpr);
-DFGEN32(gen_op_store_fpr_DT0, gen_op_store_fpr_DT0_fpr);
+FGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
+FGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
 
-DFGEN32(gen_op_load_fpr_DT1,  gen_op_load_fpr_DT1_fpr);
-DFGEN32(gen_op_store_fpr_DT1, gen_op_store_fpr_DT1_fpr);
+FGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
+FGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
 
-DFGEN32(gen_op_load_fpr_DT2,  gen_op_load_fpr_DT2_fpr);
-DFGEN32(gen_op_store_fpr_DT2, gen_op_store_fpr_DT2_fpr);
+FGEN32(gen_op_load_fpr_WTH0,  gen_op_load_fpr_WTH0_fpr);
+FGEN32(gen_op_store_fpr_WTH0, gen_op_store_fpr_WTH0_fpr);
 
+FGEN32(gen_op_load_fpr_WTH1,  gen_op_load_fpr_WTH1_fpr);
+FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr);
+
+FGEN32(gen_op_load_fpr_WTH2,  gen_op_load_fpr_WTH2_fpr);
+FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr);
+
 #define FOP_CONDS(fmt) \
-static GenOpFunc * cond_ ## fmt ## _table[16] = {                       \
+static GenOpFunc1 * cond_ ## fmt ## _table[16] = {                      \
     gen_op_cmp_ ## fmt ## _f,                                           \
     gen_op_cmp_ ## fmt ## _un,                                          \
     gen_op_cmp_ ## fmt ## _eq,                                          \
@@ -468,20 +509,20 @@
     gen_op_cmp_ ## fmt ## _le,                                          \
     gen_op_cmp_ ## fmt ## _ngt,                                         \
 };                                                                      \
-static inline void gen_cmp_ ## fmt(int n)                               \
+static inline void gen_cmp_ ## fmt(int n, long cc)                      \
 {                                                                       \
-    cond_ ## fmt ## _table[n]();                                        \
+    cond_ ## fmt ## _table[n](cc);                                      \
 }
 
 FOP_CONDS(d)
 FOP_CONDS(s)
+FOP_CONDS(ps)
 
-#endif /* MIPS_USES_FPU */
-
 typedef struct DisasContext {
     struct TranslationBlock *tb;
     target_ulong pc, saved_pc;
     uint32_t opcode;
+    uint32_t fp_status, saved_fp_status;
     /* Routine used to access memory */
     int mem_idx;
     uint32_t hflags, saved_hflags;
@@ -503,7 +544,7 @@
 #define MIPS_DEBUG(fmt, args...)                                              \
 do {                                                                          \
     if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \
-        fprintf(logfile, TLSZ ": %08x " fmt "\n",                             \
+        fprintf(logfile, TARGET_FMT_lx ": %08x " fmt "\n",                    \
                 ctx->pc, ctx->opcode , ##args);                               \
     }                                                                         \
 } while (0)
@@ -567,17 +608,31 @@
     if (ctx->hflags != ctx->saved_hflags) {
         gen_op_save_state(ctx->hflags);
         ctx->saved_hflags = ctx->hflags;
-        if (ctx->hflags & MIPS_HFLAG_BR) {
+        switch (ctx->hflags & MIPS_HFLAG_BMASK) {
+        case MIPS_HFLAG_BR:
             gen_op_save_breg_target();
-        } else if (ctx->hflags & MIPS_HFLAG_B) {
-            gen_op_save_btarget(ctx->btarget);
-        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {
+            break;
+        case MIPS_HFLAG_BC:
             gen_op_save_bcond();
+            /* fall through */
+        case MIPS_HFLAG_BL:
+            /* bcond was already saved by the BL insn */
+            /* fall through */
+        case MIPS_HFLAG_B:
             gen_op_save_btarget(ctx->btarget);
+            break;
         }
     }
 }
 
+static inline void save_fpu_state (DisasContext *ctx)
+{
+    if (ctx->fp_status != ctx->saved_fp_status) {
+        gen_op_save_fp_status(ctx->fp_status);
+        ctx->saved_fp_status = ctx->fp_status;
+    }
+}
+
 static inline void generate_exception_err (DisasContext *ctx, int excp, int err)
 {
 #if defined MIPS_DEBUG_DISAS
@@ -615,7 +670,7 @@
 }
 #endif
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
 OP_LD_TABLE(d);
 OP_LD_TABLE(dl);
 OP_LD_TABLE(dr);
@@ -640,12 +695,16 @@
 OP_ST_TABLE(b);
 OP_LD_TABLE(l);
 OP_ST_TABLE(c);
-#ifdef MIPS_USES_FPU
 OP_LD_TABLE(wc1);
 OP_ST_TABLE(wc1);
 OP_LD_TABLE(dc1);
 OP_ST_TABLE(dc1);
-#endif
+OP_LD_TABLE(wxc1);
+OP_ST_TABLE(wxc1);
+OP_LD_TABLE(dxc1);
+OP_ST_TABLE(dxc1);
+OP_LD_TABLE(uxc1);
+OP_ST_TABLE(uxc1);
 
 /* Load and store */
 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
@@ -660,13 +719,13 @@
     } else {
         gen_op_load_gpr_T0(base);
         gen_op_set_T1(offset);
-        gen_op_add();
+        gen_op_addr_add();
     }
     /* Don't do NOP if destination is zero: we must perform the actual
      * memory access
      */
     switch (opc) {
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_LD:
         op_ldst(ld);
         GEN_STORE_TN_REG(rt, T0);
@@ -683,6 +742,7 @@
         opn = "sd";
         break;
     case OPC_SCD:
+        save_cpu_state(ctx, 1);
         GEN_LOAD_REG_TN(T1, rt);
         op_ldst(scd);
         opn = "scd";
@@ -781,6 +841,7 @@
         opn = "ll";
         break;
     case OPC_SC:
+        save_cpu_state(ctx, 1);
         GEN_LOAD_REG_TN(T1, rt);
         op_ldst(sc);
         GEN_STORE_TN_REG(rt, T0);
@@ -794,8 +855,6 @@
     MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
 }
 
-#ifdef MIPS_USES_FPU
-
 /* Load and store */
 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
                       int base, int16_t offset)
@@ -809,7 +868,7 @@
     } else {
         gen_op_load_gpr_T0(base);
         gen_op_set_T1(offset);
-        gen_op_add();
+        gen_op_addr_add();
     }
     /* Don't do NOP if destination is zero: we must perform the actual
      * memory access
@@ -837,14 +896,12 @@
         break;
     default:
         MIPS_INVAL("float load/store");
-        generate_exception_err(ctx, EXCP_CpU, 1);
+        generate_exception(ctx, EXCP_RI);
         return;
     }
     MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
 }
 
-#endif /* MIPS_USES_FPU */
-
 /* Arithmetic with immediate operand */
 static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
                            int rs, int16_t imm)
@@ -859,18 +916,42 @@
         MIPS_DEBUG("NOP");
         return;
     }
-    if (opc == OPC_ADDI || opc == OPC_ADDIU ||
-        opc == OPC_DADDI || opc == OPC_DADDIU ||
-        opc == OPC_SLTI || opc == OPC_SLTIU)
+    uimm = (uint16_t)imm;
+    switch (opc) {
+    case OPC_ADDI:
+    case OPC_ADDIU:
+#ifdef TARGET_MIPS64
+    case OPC_DADDI:
+    case OPC_DADDIU:
+#endif
+    case OPC_SLTI:
+    case OPC_SLTIU:
         uimm = (int32_t)imm; /* Sign extend to 32 bits */
-    else
-        uimm = (uint16_t)imm;
-    if (opc != OPC_LUI) {
+        /* Fall through. */
+    case OPC_ANDI:
+    case OPC_ORI:
+    case OPC_XORI:
         GEN_LOAD_REG_TN(T0, rs);
         GEN_LOAD_IMM_TN(T1, uimm);
-    } else {
-        uimm = uimm << 16;
-        GEN_LOAD_IMM_TN(T0, uimm);
+        break;
+    case OPC_LUI:
+        GEN_LOAD_IMM_TN(T0, uimm << 16);
+        break;
+    case OPC_SLL:
+    case OPC_SRA:
+    case OPC_SRL:
+#ifdef TARGET_MIPS64
+    case OPC_DSLL:
+    case OPC_DSRA:
+    case OPC_DSRL:
+    case OPC_DSLL32:
+    case OPC_DSRA32:
+    case OPC_DSRL32:
+#endif
+        uimm &= 0x1f;
+        GEN_LOAD_REG_TN(T0, rs);
+        GEN_LOAD_IMM_TN(T1, uimm);
+        break;
     }
     switch (opc) {
     case OPC_ADDI:
@@ -882,7 +963,7 @@
         gen_op_add();
         opn = "addiu";
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DADDI:
         save_cpu_state(ctx, 1);
         gen_op_daddo();
@@ -925,15 +1006,22 @@
         opn = "sra";
         break;
     case OPC_SRL:
-       if ((ctx->opcode >> 21) & 1) {
+        switch ((ctx->opcode >> 21) & 0x1f) {
+        case 0:
+            gen_op_srl();
+            opn = "srl";
+            break;
+        case 1:
             gen_op_rotr();
             opn = "rotr";
-       } else {
-            gen_op_srl();
-            opn = "srl";
-       }
+            break;
+        default:
+            MIPS_INVAL("invalid srl flag");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DSLL:
         gen_op_dsll();
         opn = "dsll";
@@ -943,13 +1031,20 @@
         opn = "dsra";
         break;
     case OPC_DSRL:
-       if ((ctx->opcode >> 21) & 1) {
+        switch ((ctx->opcode >> 21) & 0x1f) {
+        case 0:
+            gen_op_dsrl();
+            opn = "dsrl";
+            break;
+        case 1:
             gen_op_drotr();
             opn = "drotr";
-       } else {
-            gen_op_dsrl();
-            opn = "dsrl";
-       }
+            break;
+        default:
+            MIPS_INVAL("invalid dsrl flag");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
         break;
     case OPC_DSLL32:
         gen_op_dsll32();
@@ -960,13 +1055,20 @@
         opn = "dsra32";
         break;
     case OPC_DSRL32:
-       if ((ctx->opcode >> 21) & 1) {
+        switch ((ctx->opcode >> 21) & 0x1f) {
+        case 0:
+            gen_op_dsrl32();
+            opn = "dsrl32";
+            break;
+        case 1:
             gen_op_drotr32();
             opn = "drotr32";
-       } else {
-            gen_op_dsrl32();
-            opn = "dsrl32";
-       }
+            break;
+        default:
+            MIPS_INVAL("invalid dsrl32 flag");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
         break;
 #endif
     default:
@@ -1013,7 +1115,7 @@
         gen_op_sub();
         opn = "subu";
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DADD:
         save_cpu_state(ctx, 1);
         gen_op_daddo();
@@ -1078,15 +1180,22 @@
         opn = "srav";
         break;
     case OPC_SRLV:
-       if ((ctx->opcode >> 6) & 1) {
+        switch ((ctx->opcode >> 6) & 0x1f) {
+        case 0:
+            gen_op_srlv();
+            opn = "srlv";
+            break;
+        case 1:
             gen_op_rotrv();
             opn = "rotrv";
-       } else {
-            gen_op_srlv();
-            opn = "srlv";
-       }
+            break;
+        default:
+            MIPS_INVAL("invalid srlv flag");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DSLLV:
         gen_op_dsllv();
         opn = "dsllv";
@@ -1096,13 +1205,20 @@
         opn = "dsrav";
         break;
     case OPC_DSRLV:
-       if ((ctx->opcode >> 6) & 1) {
+        switch ((ctx->opcode >> 6) & 0x1f) {
+        case 0:
+            gen_op_dsrlv();
+            opn = "dsrlv";
+            break;
+        case 1:
             gen_op_drotrv();
             opn = "drotrv";
-       } else {
-            gen_op_dsrlv();
-            opn = "dsrlv";
-       }
+            break;
+        default:
+            MIPS_INVAL("invalid dsrlv flag");
+            generate_exception(ctx, EXCP_RI);
+            break;
+        }
         break;
 #endif
     default:
@@ -1178,7 +1294,7 @@
         gen_op_multu();
         opn = "multu";
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DDIV:
         gen_op_ddiv();
         opn = "ddiv";
@@ -1239,7 +1355,7 @@
         gen_op_clz();
         opn = "clz";
         break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     case OPC_DCLO:
         gen_op_dclo();
         opn = "dclo";
@@ -1366,24 +1482,32 @@
             gen_op_goto_tb1(TBPARAM(tb));
         gen_op_save_pc(dest);
         gen_op_set_T0((long)tb + n);
-        gen_op_exit_tb();
     } else {
         gen_op_save_pc(dest);
-        gen_op_set_T0(0);
-        gen_op_exit_tb();
+        gen_op_reset_T0();
     }
+    gen_op_exit_tb();
 }
 
 /* Branches (before delay slot) */
 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
                                 int rs, int rt, int32_t offset)
 {
-    target_ulong btarget;
-    int blink, bcond;
+    target_ulong btarget = -1;
+    int blink = 0;
+    int bcond = 0;
 
-    btarget = -1;
-    blink = 0;
-    bcond = 0;
+    if (ctx->hflags & MIPS_HFLAG_BMASK) {
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
+            fprintf(logfile,
+                    "Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
+                    ctx->pc);
+	}
+        MIPS_INVAL("branch/jump in bdelay slot");
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+
     /* Load needed operands */
     switch (opc) {
     case OPC_BEQ:
@@ -1427,7 +1551,7 @@
         /* Jump to register */
         if (offset != 0 && offset != 16) {
             /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
-              others are reserved. */
+               others are reserved. */
             generate_exception(ctx, EXCP_RI);
             return;
         }
@@ -1467,18 +1591,21 @@
         case OPC_BLTZAL:  /* 0 < 0           */
             gen_op_set_T0(ctx->pc + 8);
             gen_op_store_T0_gpr(31);
+            MIPS_DEBUG("bnever and link");
             return;
         case OPC_BLTZALL: /* 0 < 0 likely */
             gen_op_set_T0(ctx->pc + 8);
             gen_op_store_T0_gpr(31);
-            gen_goto_tb(ctx, 0, ctx->pc + 4);
+            /* Skip the instruction in the delay slot */
+            MIPS_DEBUG("bnever, link and skip");
+            ctx->pc += 4;
             return;
         case OPC_BNEL:    /* rx != rx likely */
         case OPC_BGTZL:   /* 0 > 0 likely */
         case OPC_BLTZL:   /* 0 < 0 likely */
             /* Skip the instruction in the delay slot */
             MIPS_DEBUG("bnever and skip");
-            gen_goto_tb(ctx, 0, ctx->pc + 4);
+            ctx->pc += 4;
             return;
         case OPC_J:
             ctx->hflags |= MIPS_HFLAG_B;
@@ -1573,6 +1700,7 @@
             MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);
         not_likely:
             ctx->hflags |= MIPS_HFLAG_BC;
+            gen_op_set_bcond();
             break;
         case OPC_BLTZALL:
             gen_op_ltz();
@@ -1580,9 +1708,14 @@
             MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);
         likely:
             ctx->hflags |= MIPS_HFLAG_BL;
+            gen_op_set_bcond();
+            gen_op_save_bcond();
             break;
+        default:
+            MIPS_INVAL("conditional branch/jump");
+            generate_exception(ctx, EXCP_RI);
+            return;
         }
-        gen_op_set_bcond();
     }
     MIPS_DEBUG("enter ds: link %d cond %02x target %08x",
                blink, ctx->hflags, btarget);
@@ -1591,7 +1724,6 @@
         gen_op_set_T0(ctx->pc + 8);
         gen_op_store_T0_gpr(blink);
     }
-    return;
 }
 
 /* special3 bitfield operations */
@@ -1621,25 +1753,25 @@
     case OPC_INS:
         if (lsb > msb)
             goto fail;
-        GEN_LOAD_REG_TN(T2, rt);
+        GEN_LOAD_REG_TN(T0, rt);
         gen_op_ins(lsb, msb - lsb + 1);
         break;
     case OPC_DINSM:
         if (lsb > msb)
             goto fail;
-        GEN_LOAD_REG_TN(T2, rt);
+        GEN_LOAD_REG_TN(T0, rt);
         gen_op_ins(lsb, msb - lsb + 1 + 32);
         break;
     case OPC_DINSU:
         if (lsb > msb)
             goto fail;
-        GEN_LOAD_REG_TN(T2, rt);
+        GEN_LOAD_REG_TN(T0, rt);
         gen_op_ins(lsb + 32, msb - lsb + 1);
         break;
     case OPC_DINS:
         if (lsb > msb)
             goto fail;
-        GEN_LOAD_REG_TN(T2, rt);
+        GEN_LOAD_REG_TN(T0, rt);
         gen_op_ins(lsb, msb - lsb + 1);
         break;
     default:
@@ -1660,21 +1792,21 @@
     case 0:
         switch (sel) {
         case 0:
-           gen_op_mfc0_index();
+            gen_op_mfc0_index();
             rn = "Index";
             break;
         case 1:
-//         gen_op_mfc0_mvpcontrol(); /* MT ASE */
+//            gen_op_mfc0_mvpcontrol(); /* MT ASE */
             rn = "MVPControl";
-//         break;
+//            break;
         case 2:
-//         gen_op_mfc0_mvpconf0(); /* MT ASE */
+//            gen_op_mfc0_mvpconf0(); /* MT ASE */
             rn = "MVPConf0";
-//         break;
+//            break;
         case 3:
-//         gen_op_mfc0_mvpconf1(); /* MT ASE */
+//            gen_op_mfc0_mvpconf1(); /* MT ASE */
             rn = "MVPConf1";
-//         break;
+//            break;
         default:
             goto die;
         }
@@ -1684,35 +1816,35 @@
         case 0:
             gen_op_mfc0_random();
             rn = "Random";
-           break;
+            break;
         case 1:
-//         gen_op_mfc0_vpecontrol(); /* MT ASE */
+//            gen_op_mfc0_vpecontrol(); /* MT ASE */
             rn = "VPEControl";
-//         break;
+//            break;
         case 2:
-//         gen_op_mfc0_vpeconf0(); /* MT ASE */
+//            gen_op_mfc0_vpeconf0(); /* MT ASE */
             rn = "VPEConf0";
-//         break;
+//            break;
         case 3:
-//         gen_op_mfc0_vpeconf1(); /* MT ASE */
+//            gen_op_mfc0_vpeconf1(); /* MT ASE */
             rn = "VPEConf1";
-//         break;
+//            break;
         case 4:
-//         gen_op_mfc0_YQMask(); /* MT ASE */
+//            gen_op_mfc0_YQMask(); /* MT ASE */
             rn = "YQMask";
-//         break;
+//            break;
         case 5:
-//         gen_op_mfc0_vpeschedule(); /* MT ASE */
+//            gen_op_mfc0_vpeschedule(); /* MT ASE */
             rn = "VPESchedule";
-//         break;
+//            break;
         case 6:
-//         gen_op_mfc0_vpeschefback(); /* MT ASE */
+//            gen_op_mfc0_vpeschefback(); /* MT ASE */
             rn = "VPEScheFBack";
-//         break;
+//            break;
         case 7:
-//         gen_op_mfc0_vpeopt(); /* MT ASE */
+//            gen_op_mfc0_vpeopt(); /* MT ASE */
             rn = "VPEOpt";
-//         break;
+//            break;
         default:
             goto die;
         }
@@ -1720,37 +1852,37 @@
     case 2:
         switch (sel) {
         case 0:
-           gen_op_mfc0_entrylo0();
-           rn = "EntryLo0";
-           break;
+            gen_op_mfc0_entrylo0();
+            rn = "EntryLo0";
+            break;
         case 1:
-//         gen_op_mfc0_tcstatus(); /* MT ASE */
-           rn = "TCStatus";
-//         break;
+//            gen_op_mfc0_tcstatus(); /* MT ASE */
+            rn = "TCStatus";
+//            break;
         case 2:
-//         gen_op_mfc0_tcbind(); /* MT ASE */
-           rn = "TCBind";
-//         break;
+//            gen_op_mfc0_tcbind(); /* MT ASE */
+            rn = "TCBind";
+//            break;
         case 3:
-//         gen_op_mfc0_tcrestart(); /* MT ASE */
-           rn = "TCRestart";
-//         break;
+//            gen_op_mfc0_tcrestart(); /* MT ASE */
+            rn = "TCRestart";
+//            break;
         case 4:
-//         gen_op_mfc0_tchalt(); /* MT ASE */
-           rn = "TCHalt";
-//         break;
+//            gen_op_mfc0_tchalt(); /* MT ASE */
+            rn = "TCHalt";
+//            break;
         case 5:
-//         gen_op_mfc0_tccontext(); /* MT ASE */
-           rn = "TCContext";
-//         break;
+//            gen_op_mfc0_tccontext(); /* MT ASE */
+            rn = "TCContext";
+//            break;
         case 6:
-//         gen_op_mfc0_tcschedule(); /* MT ASE */
-           rn = "TCSchedule";
-//         break;
+//            gen_op_mfc0_tcschedule(); /* MT ASE */
+            rn = "TCSchedule";
+//            break;
         case 7:
-//         gen_op_mfc0_tcschefback(); /* MT ASE */
-           rn = "TCScheFBack";
-//         break;
+//            gen_op_mfc0_tcschefback(); /* MT ASE */
+            rn = "TCScheFBack";
+//            break;
         default:
             goto die;
         }
@@ -1758,87 +1890,87 @@
     case 3:
         switch (sel) {
         case 0:
-           gen_op_mfc0_entrylo1();
-           rn = "EntryLo1";
-           break;
+            gen_op_mfc0_entrylo1();
+            rn = "EntryLo1";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 4:
         switch (sel) {
         case 0:
-           gen_op_mfc0_context();
-           rn = "Context";
-           break;
+            gen_op_mfc0_context();
+            rn = "Context";
+            break;
         case 1:
-//         gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
-           rn = "ContextConfig";
-//         break;
+//            gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */
+            rn = "ContextConfig";
+//            break;
         default:
             goto die;
-       }
+        }
         break;
     case 5:
         switch (sel) {
         case 0:
-           gen_op_mfc0_pagemask();
-           rn = "PageMask";
-           break;
+            gen_op_mfc0_pagemask();
+            rn = "PageMask";
+            break;
         case 1:
-           gen_op_mfc0_pagegrain();
-           rn = "PageGrain";
-           break;
+            gen_op_mfc0_pagegrain();
+            rn = "PageGrain";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 6:
         switch (sel) {
         case 0:
-           gen_op_mfc0_wired();
-           rn = "Wired";
-           break;
+            gen_op_mfc0_wired();
+            rn = "Wired";
+            break;
         case 1:
-//         gen_op_mfc0_srsconf0(); /* shadow registers */
-           rn = "SRSConf0";
-//         break;
+//            gen_op_mfc0_srsconf0(); /* shadow registers */
+            rn = "SRSConf0";
+//            break;
         case 2:
-//         gen_op_mfc0_srsconf1(); /* shadow registers */
-           rn = "SRSConf1";
-//         break;
+//            gen_op_mfc0_srsconf1(); /* shadow registers */
+            rn = "SRSConf1";
+//            break;
         case 3:
-//         gen_op_mfc0_srsconf2(); /* shadow registers */
-           rn = "SRSConf2";
-//         break;
+//            gen_op_mfc0_srsconf2(); /* shadow registers */
+            rn = "SRSConf2";
+//            break;
         case 4:
-//         gen_op_mfc0_srsconf3(); /* shadow registers */
-           rn = "SRSConf3";
-//         break;
+//            gen_op_mfc0_srsconf3(); /* shadow registers */
+            rn = "SRSConf3";
+//            break;
         case 5:
-//         gen_op_mfc0_srsconf4(); /* shadow registers */
-           rn = "SRSConf4";
-//         break;
+//            gen_op_mfc0_srsconf4(); /* shadow registers */
+            rn = "SRSConf4";
+//            break;
         default:
             goto die;
-       }
+        }
         break;
     case 7:
         switch (sel) {
         case 0:
-           gen_op_mfc0_hwrena();
-           rn = "HWREna";
-           break;
+            gen_op_mfc0_hwrena();
+            rn = "HWREna";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 8:
         switch (sel) {
         case 0:
-           gen_op_mfc0_badvaddr();
-           rn = "BadVaddr";
-           break;
+            gen_op_mfc0_badvaddr();
+            rn = "BadVaddr";
+            break;
         default:
             goto die;
        }
@@ -1846,53 +1978,53 @@
     case 9:
         switch (sel) {
         case 0:
-           gen_op_mfc0_count();
-           rn = "Count";
-           break;
-       /* 6,7 are implementation dependent */
+            gen_op_mfc0_count();
+            rn = "Count";
+            break;
+        /* 6,7 are implementation dependent */
         default:
             goto die;
-       }
+        }
         break;
     case 10:
         switch (sel) {
         case 0:
-           gen_op_mfc0_entryhi();
-           rn = "EntryHi";
-           break;
+            gen_op_mfc0_entryhi();
+            rn = "EntryHi";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 11:
         switch (sel) {
         case 0:
-           gen_op_mfc0_compare();
-           rn = "Compare";
-           break;
-       /* 6,7 are implementation dependent */
+            gen_op_mfc0_compare();
+            rn = "Compare";
+            break;
+        /* 6,7 are implementation dependent */
         default:
             goto die;
-       }
+        }
         break;
     case 12:
         switch (sel) {
         case 0:
-           gen_op_mfc0_status();
-           rn = "Status";
-           break;
+            gen_op_mfc0_status();
+            rn = "Status";
+            break;
         case 1:
-           gen_op_mfc0_intctl();
-           rn = "IntCtl";
-           break;
+            gen_op_mfc0_intctl();
+            rn = "IntCtl";
+            break;
         case 2:
-           gen_op_mfc0_srsctl();
-           rn = "SRSCtl";
-           break;
+            gen_op_mfc0_srsctl();
+            rn = "SRSCtl";
+            break;
         case 3:
-//         gen_op_mfc0_srsmap(); /* shadow registers */
-           rn = "SRSMap";
-//         break;
+//            gen_op_mfc0_srsmap(); /* shadow registers */
+            rn = "SRSMap";
+//            break;
         default:
             goto die;
        }
@@ -1900,9 +2032,9 @@
     case 13:
         switch (sel) {
         case 0:
-           gen_op_mfc0_cause();
-           rn = "Cause";
-           break;
+            gen_op_mfc0_cause();
+            rn = "Cause";
+            break;
         default:
             goto die;
        }
@@ -1910,23 +2042,23 @@
     case 14:
         switch (sel) {
         case 0:
-           gen_op_mfc0_epc();
-           rn = "EPC";
-           break;
+            gen_op_mfc0_epc();
+            rn = "EPC";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 15:
         switch (sel) {
         case 0:
-           gen_op_mfc0_prid();
-           rn = "PRid";
-           break;
+            gen_op_mfc0_prid();
+            rn = "PRid";
+            break;
         case 1:
-           gen_op_mfc0_ebase();
-           rn = "EBase";
-           break;
+            gen_op_mfc0_ebase();
+            rn = "EBase";
+            break;
         default:
             goto die;
        }
@@ -1934,22 +2066,31 @@
     case 16:
         switch (sel) {
         case 0:
-           gen_op_mfc0_config0();
+            gen_op_mfc0_config0();
             rn = "Config";
             break;
         case 1:
-           gen_op_mfc0_config1();
+            gen_op_mfc0_config1();
             rn = "Config1";
             break;
         case 2:
-           gen_op_mfc0_config2();
+            gen_op_mfc0_config2();
             rn = "Config2";
             break;
         case 3:
-           gen_op_mfc0_config3();
+            gen_op_mfc0_config3();
             rn = "Config3";
             break;
-       /* 6,7 are implementation dependent */
+        /* 4,5 are reserved */
+        /* 6,7 are implementation dependent */
+        case 6:
+            gen_op_mfc0_config6();
+            rn = "Config6";
+            break;
+        case 7:
+            gen_op_mfc0_config7();
+            rn = "Config7";
+            break;
         default:
             goto die;
         }
@@ -1957,9 +2098,9 @@
     case 17:
         switch (sel) {
         case 0:
-           gen_op_mfc0_lladdr();
-           rn = "LLAddr";
-           break;
+            gen_op_mfc0_lladdr();
+            rn = "LLAddr";
+            break;
         default:
             goto die;
         }
@@ -1967,37 +2108,37 @@
     case 18:
         switch (sel) {
         case 0:
-           gen_op_mfc0_watchlo0();
-           rn = "WatchLo";
-           break;
+            gen_op_mfc0_watchlo0();
+            rn = "WatchLo";
+            break;
         case 1:
-//         gen_op_mfc0_watchlo1();
-           rn = "WatchLo1";
-//         break;
+//            gen_op_mfc0_watchlo1();
+            rn = "WatchLo1";
+//            break;
         case 2:
-//         gen_op_mfc0_watchlo2();
-           rn = "WatchLo2";
-//         break;
+//            gen_op_mfc0_watchlo2();
+            rn = "WatchLo2";
+//            break;
         case 3:
-//         gen_op_mfc0_watchlo3();
-           rn = "WatchLo3";
-//         break;
+//            gen_op_mfc0_watchlo3();
+            rn = "WatchLo3";
+//            break;
         case 4:
-//         gen_op_mfc0_watchlo4();
-           rn = "WatchLo4";
-//         break;
+//            gen_op_mfc0_watchlo4();
+            rn = "WatchLo4";
+//            break;
         case 5:
-//         gen_op_mfc0_watchlo5();
-           rn = "WatchLo5";
-//         break;
+//            gen_op_mfc0_watchlo5();
+            rn = "WatchLo5";
+//            break;
         case 6:
-//         gen_op_mfc0_watchlo6();
-           rn = "WatchLo6";
-//         break;
+//            gen_op_mfc0_watchlo6();
+            rn = "WatchLo6";
+//            break;
         case 7:
-//         gen_op_mfc0_watchlo7();
-           rn = "WatchLo7";
-//         break;
+//            gen_op_mfc0_watchlo7();
+            rn = "WatchLo7";
+//            break;
         default:
             goto die;
         }
@@ -2005,37 +2146,37 @@
     case 19:
         switch (sel) {
         case 0:
-           gen_op_mfc0_watchhi0();
-           rn = "WatchHi";
-           break;
+            gen_op_mfc0_watchhi0();
+            rn = "WatchHi";
+            break;
         case 1:
-//         gen_op_mfc0_watchhi1();
-           rn = "WatchHi1";
-//         break;
+//            gen_op_mfc0_watchhi1();
+            rn = "WatchHi1";
+//            break;
         case 2:
-//         gen_op_mfc0_watchhi2();
-           rn = "WatchHi2";
-//         break;
+//            gen_op_mfc0_watchhi2();
+            rn = "WatchHi2";
+//            break;
         case 3:
-//         gen_op_mfc0_watchhi3();
-           rn = "WatchHi3";
-//         break;
+//            gen_op_mfc0_watchhi3();
+            rn = "WatchHi3";
+//            break;
         case 4:
-//         gen_op_mfc0_watchhi4();
-           rn = "WatchHi4";
-//         break;
+//            gen_op_mfc0_watchhi4();
+            rn = "WatchHi4";
+//            break;
         case 5:
-//         gen_op_mfc0_watchhi5();
-           rn = "WatchHi5";
-//         break;
+//            gen_op_mfc0_watchhi5();
+            rn = "WatchHi5";
+//            break;
         case 6:
-//         gen_op_mfc0_watchhi6();
-           rn = "WatchHi6";
-//         break;
+//            gen_op_mfc0_watchhi6();
+            rn = "WatchHi6";
+//            break;
         case 7:
-//         gen_op_mfc0_watchhi7();
-           rn = "WatchHi7";
-//         break;
+//            gen_op_mfc0_watchhi7();
+            rn = "WatchHi7";
+//            break;
         default:
             goto die;
         }
@@ -2043,10 +2184,10 @@
     case 20:
         switch (sel) {
         case 0:
-           /* 64 bit MMU only */
-           gen_op_mfc0_xcontext();
-           rn = "XContext";
-           break;
+            /* 64 bit MMU only */
+            gen_op_mfc0_xcontext();
+            rn = "XContext";
+            break;
         default:
             goto die;
         }
@@ -2055,39 +2196,39 @@
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-           gen_op_mfc0_framemask();
-           rn = "Framemask";
-           break;
+            gen_op_mfc0_framemask();
+            rn = "Framemask";
+            break;
         default:
             goto die;
         }
         break;
     case 22:
-       /* ignored */
-       rn = "'Diagnostic"; /* implementation dependent */
-       break;
+        /* ignored */
+        rn = "'Diagnostic"; /* implementation dependent */
+        break;
     case 23:
         switch (sel) {
         case 0:
-           gen_op_mfc0_debug(); /* EJTAG support */
-           rn = "Debug";
-           break;
+            gen_op_mfc0_debug(); /* EJTAG support */
+            rn = "Debug";
+            break;
         case 1:
-//         gen_op_mfc0_tracecontrol(); /* PDtrace support */
-           rn = "TraceControl";
-//         break;
+//            gen_op_mfc0_tracecontrol(); /* PDtrace support */
+            rn = "TraceControl";
+//            break;
         case 2:
-//         gen_op_mfc0_tracecontrol2(); /* PDtrace support */
-           rn = "TraceControl2";
-//         break;
+//            gen_op_mfc0_tracecontrol2(); /* PDtrace support */
+            rn = "TraceControl2";
+//            break;
         case 3:
-//         gen_op_mfc0_usertracedata(); /* PDtrace support */
-           rn = "UserTraceData";
-//         break;
+//            gen_op_mfc0_usertracedata(); /* PDtrace support */
+            rn = "UserTraceData";
+//            break;
         case 4:
-//         gen_op_mfc0_debug(); /* PDtrace support */
-           rn = "TraceBPC";
-//         break;
+//            gen_op_mfc0_debug(); /* PDtrace support */
+            rn = "TraceBPC";
+//            break;
         default:
             goto die;
         }
@@ -2095,9 +2236,9 @@
     case 24:
         switch (sel) {
         case 0:
-           gen_op_mfc0_depc(); /* EJTAG support */
-           rn = "DEPC";
-           break;
+            gen_op_mfc0_depc(); /* EJTAG support */
+            rn = "DEPC";
+            break;
         default:
             goto die;
         }
@@ -2105,37 +2246,37 @@
     case 25:
         switch (sel) {
         case 0:
-           gen_op_mfc0_performance0();
-           rn = "Performance0";
+            gen_op_mfc0_performance0();
+            rn = "Performance0";
             break;
         case 1:
-//         gen_op_mfc0_performance1();
-           rn = "Performance1";
-//         break;
+//            gen_op_mfc0_performance1();
+            rn = "Performance1";
+//            break;
         case 2:
-//         gen_op_mfc0_performance2();
-           rn = "Performance2";
-//         break;
+//            gen_op_mfc0_performance2();
+            rn = "Performance2";
+//            break;
         case 3:
-//         gen_op_mfc0_performance3();
-           rn = "Performance3";
-//         break;
+//            gen_op_mfc0_performance3();
+            rn = "Performance3";
+//            break;
         case 4:
-//         gen_op_mfc0_performance4();
-           rn = "Performance4";
-//         break;
+//            gen_op_mfc0_performance4();
+            rn = "Performance4";
+//            break;
         case 5:
-//         gen_op_mfc0_performance5();
-           rn = "Performance5";
-//         break;
+//            gen_op_mfc0_performance5();
+            rn = "Performance5";
+//            break;
         case 6:
-//         gen_op_mfc0_performance6();
-           rn = "Performance6";
-//         break;
+//            gen_op_mfc0_performance6();
+            rn = "Performance6";
+//            break;
         case 7:
-//         gen_op_mfc0_performance7();
-           rn = "Performance7";
-//         break;
+//            gen_op_mfc0_performance7();
+            rn = "Performance7";
+//            break;
         default:
             goto die;
         }
@@ -2147,8 +2288,8 @@
         switch (sel) {
         /* ignored */
         case 0 ... 3:
-           rn = "CacheErr";
-           break;
+            rn = "CacheErr";
+            break;
         default:
             goto die;
         }
@@ -2196,9 +2337,9 @@
     case 30:
         switch (sel) {
         case 0:
-           gen_op_mfc0_errorepc();
-           rn = "ErrorEPC";
-           break;
+            gen_op_mfc0_errorepc();
+            rn = "ErrorEPC";
+            break;
         default:
             goto die;
         }
@@ -2206,9 +2347,9 @@
     case 31:
         switch (sel) {
         case 0:
-           gen_op_mfc0_desave(); /* EJTAG support */
-           rn = "DESAVE";
-           break;
+            gen_op_mfc0_desave(); /* EJTAG support */
+            rn = "DESAVE";
+            break;
         default:
             goto die;
         }
@@ -2246,17 +2387,17 @@
             rn = "Index";
             break;
         case 1:
-//         gen_op_mtc0_mvpcontrol(); /* MT ASE */
+//            gen_op_mtc0_mvpcontrol(); /* MT ASE */
             rn = "MVPControl";
-//         break;
+//            break;
         case 2:
-//         gen_op_mtc0_mvpconf0(); /* MT ASE */
+//            gen_op_mtc0_mvpconf0(); /* MT ASE */
             rn = "MVPConf0";
-//         break;
+//            break;
         case 3:
-//         gen_op_mtc0_mvpconf1(); /* MT ASE */
+//            gen_op_mtc0_mvpconf1(); /* MT ASE */
             rn = "MVPConf1";
-//         break;
+//            break;
         default:
             goto die;
         }
@@ -2264,37 +2405,37 @@
     case 1:
         switch (sel) {
         case 0:
-           /* ignored */
+            /* ignored */
             rn = "Random";
-           break;
+            break;
         case 1:
-//         gen_op_mtc0_vpecontrol(); /* MT ASE */
+//            gen_op_mtc0_vpecontrol(); /* MT ASE */
             rn = "VPEControl";
-//         break;
+//            break;
         case 2:
-//         gen_op_mtc0_vpeconf0(); /* MT ASE */
+//            gen_op_mtc0_vpeconf0(); /* MT ASE */
             rn = "VPEConf0";
-//         break;
+//            break;
         case 3:
-//         gen_op_mtc0_vpeconf1(); /* MT ASE */
+//            gen_op_mtc0_vpeconf1(); /* MT ASE */
             rn = "VPEConf1";
-//         break;
+//            break;
         case 4:
-//         gen_op_mtc0_YQMask(); /* MT ASE */
+//            gen_op_mtc0_YQMask(); /* MT ASE */
             rn = "YQMask";
-//         break;
+//            break;
         case 5:
-//         gen_op_mtc0_vpeschedule(); /* MT ASE */
+//            gen_op_mtc0_vpeschedule(); /* MT ASE */
             rn = "VPESchedule";
-//         break;
+//            break;
         case 6:
-//         gen_op_mtc0_vpeschefback(); /* MT ASE */
+//            gen_op_mtc0_vpeschefback(); /* MT ASE */
             rn = "VPEScheFBack";
-//         break;
+//            break;
         case 7:
-//         gen_op_mtc0_vpeopt(); /* MT ASE */
+//            gen_op_mtc0_vpeopt(); /* MT ASE */
             rn = "VPEOpt";
-//         break;
+//            break;
         default:
             goto die;
         }
@@ -2302,37 +2443,37 @@
     case 2:
         switch (sel) {
         case 0:
-           gen_op_mtc0_entrylo0();
-           rn = "EntryLo0";
-           break;
+            gen_op_mtc0_entrylo0();
+            rn = "EntryLo0";
+            break;
         case 1:
-//         gen_op_mtc0_tcstatus(); /* MT ASE */
-           rn = "TCStatus";
-//         break;
+//            gen_op_mtc0_tcstatus(); /* MT ASE */
+            rn = "TCStatus";
+//            break;
         case 2:
-//         gen_op_mtc0_tcbind(); /* MT ASE */
-           rn = "TCBind";
-//         break;
+//            gen_op_mtc0_tcbind(); /* MT ASE */
+            rn = "TCBind";
+//            break;
         case 3:
-//         gen_op_mtc0_tcrestart(); /* MT ASE */
-           rn = "TCRestart";
-//         break;
+//            gen_op_mtc0_tcrestart(); /* MT ASE */
+            rn = "TCRestart";
+//            break;
         case 4:
-//         gen_op_mtc0_tchalt(); /* MT ASE */
-           rn = "TCHalt";
-//         break;
+//            gen_op_mtc0_tchalt(); /* MT ASE */
+            rn = "TCHalt";
+//            break;
         case 5:
-//         gen_op_mtc0_tccontext(); /* MT ASE */
-           rn = "TCContext";
-//         break;
+//            gen_op_mtc0_tccontext(); /* MT ASE */
+            rn = "TCContext";
+//            break;
         case 6:
-//         gen_op_mtc0_tcschedule(); /* MT ASE */
-           rn = "TCSchedule";
-//         break;
+//            gen_op_mtc0_tcschedule(); /* MT ASE */
+            rn = "TCSchedule";
+//            break;
         case 7:
-//         gen_op_mtc0_tcschefback(); /* MT ASE */
-           rn = "TCScheFBack";
-//         break;
+//            gen_op_mtc0_tcschefback(); /* MT ASE */
+            rn = "TCScheFBack";
+//            break;
         default:
             goto die;
         }
@@ -2340,80 +2481,80 @@
     case 3:
         switch (sel) {
         case 0:
-           gen_op_mtc0_entrylo1();
-           rn = "EntryLo1";
-           break;
+            gen_op_mtc0_entrylo1();
+            rn = "EntryLo1";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 4:
         switch (sel) {
         case 0:
-           gen_op_mtc0_context();
-           rn = "Context";
-           break;
+            gen_op_mtc0_context();
+            rn = "Context";
+            break;
         case 1:
-//         gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
-           rn = "ContextConfig";
-//         break;
+//            gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */
+            rn = "ContextConfig";
+//            break;
         default:
             goto die;
-       }
+        }
         break;
     case 5:
         switch (sel) {
         case 0:
-           gen_op_mtc0_pagemask();
-           rn = "PageMask";
-           break;
+            gen_op_mtc0_pagemask();
+            rn = "PageMask";
+            break;
         case 1:
-           gen_op_mtc0_pagegrain();
-           rn = "PageGrain";
-           break;
+            gen_op_mtc0_pagegrain();
+            rn = "PageGrain";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 6:
         switch (sel) {
         case 0:
-           gen_op_mtc0_wired();
-           rn = "Wired";
-           break;
+            gen_op_mtc0_wired();
+            rn = "Wired";
+            break;
         case 1:
-//         gen_op_mtc0_srsconf0(); /* shadow registers */
-           rn = "SRSConf0";
-//         break;
+//            gen_op_mtc0_srsconf0(); /* shadow registers */
+            rn = "SRSConf0";
+//            break;
         case 2:
-//         gen_op_mtc0_srsconf1(); /* shadow registers */
-           rn = "SRSConf1";
-//         break;
+//            gen_op_mtc0_srsconf1(); /* shadow registers */
+            rn = "SRSConf1";
+//            break;
         case 3:
-//         gen_op_mtc0_srsconf2(); /* shadow registers */
-           rn = "SRSConf2";
-//         break;
+//            gen_op_mtc0_srsconf2(); /* shadow registers */
+            rn = "SRSConf2";
+//            break;
         case 4:
-//         gen_op_mtc0_srsconf3(); /* shadow registers */
-           rn = "SRSConf3";
-//         break;
+//            gen_op_mtc0_srsconf3(); /* shadow registers */
+            rn = "SRSConf3";
+//            break;
         case 5:
-//         gen_op_mtc0_srsconf4(); /* shadow registers */
-           rn = "SRSConf4";
-//         break;
+//            gen_op_mtc0_srsconf4(); /* shadow registers */
+            rn = "SRSConf4";
+//            break;
         default:
             goto die;
-       }
+        }
         break;
     case 7:
         switch (sel) {
         case 0:
-           gen_op_mtc0_hwrena();
-           rn = "HWREna";
-           break;
+            gen_op_mtc0_hwrena();
+            rn = "HWREna";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 8:
         /* ignored */
@@ -2422,131 +2563,142 @@
     case 9:
         switch (sel) {
         case 0:
-           gen_op_mtc0_count();
-           rn = "Count";
-           break;
-       /* 6,7 are implementation dependent */
+            gen_op_mtc0_count();
+            rn = "Count";
+            break;
+        /* 6,7 are implementation dependent */
         default:
             goto die;
-       }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     case 10:
         switch (sel) {
         case 0:
-           gen_op_mtc0_entryhi();
-           rn = "EntryHi";
-           break;
+            gen_op_mtc0_entryhi();
+            rn = "EntryHi";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 11:
         switch (sel) {
         case 0:
-           gen_op_mtc0_compare();
-           rn = "Compare";
-           break;
-       /* 6,7 are implementation dependent */
+            gen_op_mtc0_compare();
+            rn = "Compare";
+            break;
+        /* 6,7 are implementation dependent */
         default:
             goto die;
-       }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     case 12:
         switch (sel) {
         case 0:
-           gen_op_mtc0_status();
-           rn = "Status";
-           break;
+            gen_op_mtc0_status();
+            rn = "Status";
+            break;
         case 1:
-           gen_op_mtc0_intctl();
-           rn = "IntCtl";
-           break;
+            gen_op_mtc0_intctl();
+            rn = "IntCtl";
+            break;
         case 2:
-           gen_op_mtc0_srsctl();
-           rn = "SRSCtl";
-           break;
+            gen_op_mtc0_srsctl();
+            rn = "SRSCtl";
+            break;
         case 3:
-//         gen_op_mtc0_srsmap(); /* shadow registers */
-           rn = "SRSMap";
-//         break;
+//            gen_op_mtc0_srsmap(); /* shadow registers */
+            rn = "SRSMap";
+//            break;
         default:
             goto die;
-       }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     case 13:
         switch (sel) {
         case 0:
-           gen_op_mtc0_cause();
-           rn = "Cause";
-           break;
+            gen_op_mtc0_cause();
+            rn = "Cause";
+            break;
         default:
             goto die;
-       }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     case 14:
         switch (sel) {
         case 0:
-           gen_op_mtc0_epc();
-           rn = "EPC";
-           break;
+            gen_op_mtc0_epc();
+            rn = "EPC";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 15:
         switch (sel) {
         case 0:
-           /* ignored */
-           rn = "PRid";
-           break;
+            /* ignored */
+            rn = "PRid";
+            break;
         case 1:
-           gen_op_mtc0_ebase();
-           rn = "EBase";
-           break;
+            gen_op_mtc0_ebase();
+            rn = "EBase";
+            break;
         default:
             goto die;
-       }
+        }
         break;
     case 16:
         switch (sel) {
         case 0:
-           gen_op_mtc0_config0();
+            gen_op_mtc0_config0();
             rn = "Config";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
             break;
         case 1:
-           /* ignored */
+            /* ignored, read only */
             rn = "Config1";
             break;
         case 2:
-           gen_op_mtc0_config2();
+            gen_op_mtc0_config2();
             rn = "Config2";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
             break;
         case 3:
-           /* ignored */
+            /* ignored, read only */
             rn = "Config3";
             break;
-       /* 6,7 are implementation dependent */
+        /* 4,5 are reserved */
+        /* 6,7 are implementation dependent */
+        case 6:
+            /* ignored */
+            rn = "Config6";
+            break;
+        case 7:
+            /* ignored */
+            rn = "Config7";
+            break;
         default:
             rn = "Invalid config selector";
             goto die;
         }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
         break;
     case 17:
         switch (sel) {
         case 0:
-           /* ignored */
-           rn = "LLAddr";
-           break;
+            /* ignored */
+            rn = "LLAddr";
+            break;
         default:
             goto die;
         }
@@ -2554,37 +2706,37 @@
     case 18:
         switch (sel) {
         case 0:
-           gen_op_mtc0_watchlo0();
-           rn = "WatchLo";
-           break;
+            gen_op_mtc0_watchlo0();
+            rn = "WatchLo";
+            break;
         case 1:
-//         gen_op_mtc0_watchlo1();
-           rn = "WatchLo1";
-//         break;
+//            gen_op_mtc0_watchlo1();
+            rn = "WatchLo1";
+//            break;
         case 2:
-//         gen_op_mtc0_watchlo2();
-           rn = "WatchLo2";
-//         break;
+//            gen_op_mtc0_watchlo2();
+            rn = "WatchLo2";
+//            break;
         case 3:
-//         gen_op_mtc0_watchlo3();
-           rn = "WatchLo3";
-//         break;
+//            gen_op_mtc0_watchlo3();
+            rn = "WatchLo3";
+//            break;
         case 4:
-//         gen_op_mtc0_watchlo4();
-           rn = "WatchLo4";
-//         break;
+//            gen_op_mtc0_watchlo4();
+            rn = "WatchLo4";
+//            break;
         case 5:
-//         gen_op_mtc0_watchlo5();
-           rn = "WatchLo5";
-//         break;
+//            gen_op_mtc0_watchlo5();
+            rn = "WatchLo5";
+//            break;
         case 6:
-//         gen_op_mtc0_watchlo6();
-           rn = "WatchLo6";
-//         break;
+//            gen_op_mtc0_watchlo6();
+            rn = "WatchLo6";
+//            break;
         case 7:
-//         gen_op_mtc0_watchlo7();
-           rn = "WatchLo7";
-//         break;
+//            gen_op_mtc0_watchlo7();
+            rn = "WatchLo7";
+//            break;
         default:
             goto die;
         }
@@ -2592,37 +2744,37 @@
     case 19:
         switch (sel) {
         case 0:
-           gen_op_mtc0_watchhi0();
-           rn = "WatchHi";
-           break;
+            gen_op_mtc0_watchhi0();
+            rn = "WatchHi";
+            break;
         case 1:
-//         gen_op_mtc0_watchhi1();
-           rn = "WatchHi1";
-//         break;
+//            gen_op_mtc0_watchhi1();
+            rn = "WatchHi1";
+//            break;
         case 2:
-//         gen_op_mtc0_watchhi2();
-           rn = "WatchHi2";
-//         break;
+//            gen_op_mtc0_watchhi2();
+            rn = "WatchHi2";
+//            break;
         case 3:
-//         gen_op_mtc0_watchhi3();
-           rn = "WatchHi3";
-//         break;
+//            gen_op_mtc0_watchhi3();
+            rn = "WatchHi3";
+//            break;
         case 4:
-//         gen_op_mtc0_watchhi4();
-           rn = "WatchHi4";
-//         break;
+//            gen_op_mtc0_watchhi4();
+            rn = "WatchHi4";
+//            break;
         case 5:
-//         gen_op_mtc0_watchhi5();
-           rn = "WatchHi5";
-//         break;
+//            gen_op_mtc0_watchhi5();
+            rn = "WatchHi5";
+//            break;
         case 6:
-//         gen_op_mtc0_watchhi6();
-           rn = "WatchHi6";
-//         break;
+//            gen_op_mtc0_watchhi6();
+            rn = "WatchHi6";
+//            break;
         case 7:
-//         gen_op_mtc0_watchhi7();
-           rn = "WatchHi7";
-//         break;
+//            gen_op_mtc0_watchhi7();
+            rn = "WatchHi7";
+//            break;
         default:
             goto die;
         }
@@ -2630,10 +2782,10 @@
     case 20:
         switch (sel) {
         case 0:
-           /* 64 bit MMU only */
-           gen_op_mtc0_xcontext();
-           rn = "XContext";
-           break;
+            /* 64 bit MMU only */
+            /* Nothing writable in lower 32 bits */
+            rn = "XContext";
+            break;
         default:
             goto die;
         }
@@ -2642,9 +2794,9 @@
        /* Officially reserved, but sel 0 is used for R1x000 framemask */
         switch (sel) {
         case 0:
-           gen_op_mtc0_framemask();
-           rn = "Framemask";
-           break;
+            gen_op_mtc0_framemask();
+            rn = "Framemask";
+            break;
         default:
             goto die;
         }
@@ -2652,41 +2804,41 @@
     case 22:
         /* ignored */
         rn = "Diagnostic"; /* implementation dependent */
-       break;
+        break;
     case 23:
         switch (sel) {
         case 0:
-           gen_op_mtc0_debug(); /* EJTAG support */
-           rn = "Debug";
-           break;
+            gen_op_mtc0_debug(); /* EJTAG support */
+            rn = "Debug";
+            break;
         case 1:
-//         gen_op_mtc0_tracecontrol(); /* PDtrace support */
-           rn = "TraceControl";
-//         break;
+//            gen_op_mtc0_tracecontrol(); /* PDtrace support */
+            rn = "TraceControl";
+//            break;
         case 2:
-//         gen_op_mtc0_tracecontrol2(); /* PDtrace support */
-           rn = "TraceControl2";
-//         break;
+//            gen_op_mtc0_tracecontrol2(); /* PDtrace support */
+            rn = "TraceControl2";
+//            break;
         case 3:
-//         gen_op_mtc0_usertracedata(); /* PDtrace support */
-           rn = "UserTraceData";
-//         break;
+//            gen_op_mtc0_usertracedata(); /* PDtrace support */
+            rn = "UserTraceData";
+//            break;
         case 4:
-//         gen_op_mtc0_debug(); /* PDtrace support */
-           rn = "TraceBPC";
-//         break;
+//            gen_op_mtc0_debug(); /* PDtrace support */
+            rn = "TraceBPC";
+//            break;
         default:
             goto die;
         }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     case 24:
         switch (sel) {
         case 0:
-           gen_op_mtc0_depc(); /* EJTAG support */
-           rn = "DEPC";
-           break;
+            gen_op_mtc0_depc(); /* EJTAG support */
+            rn = "DEPC";
+            break;
         default:
             goto die;
         }
@@ -2694,51 +2846,51 @@
     case 25:
         switch (sel) {
         case 0:
-           gen_op_mtc0_performance0();
-           rn = "Performance0";
-           break;
+            gen_op_mtc0_performance0();
+            rn = "Performance0";
+            break;
         case 1:
-//         gen_op_mtc0_performance1();
-           rn = "Performance1";
-//         break;
+//            gen_op_mtc0_performance1();
+            rn = "Performance1";
+//            break;
         case 2:
-//         gen_op_mtc0_performance2();
-           rn = "Performance2";
-//         break;
+//            gen_op_mtc0_performance2();
+            rn = "Performance2";
+//            break;
         case 3:
-//         gen_op_mtc0_performance3();
-           rn = "Performance3";
-//         break;
+//            gen_op_mtc0_performance3();
+            rn = "Performance3";
+//            break;
         case 4:
-//         gen_op_mtc0_performance4();
-           rn = "Performance4";
-//         break;
+//            gen_op_mtc0_performance4();
+            rn = "Performance4";
+//            break;
         case 5:
-//         gen_op_mtc0_performance5();
-           rn = "Performance5";
-//         break;
+//            gen_op_mtc0_performance5();
+            rn = "Performance5";
+//            break;
         case 6:
-//         gen_op_mtc0_performance6();
-           rn = "Performance6";
-//         break;
+//            gen_op_mtc0_performance6();
+            rn = "Performance6";
+//            break;
         case 7:
-//         gen_op_mtc0_performance7();
-           rn = "Performance7";
-//         break;
+//            gen_op_mtc0_performance7();
+            rn = "Performance7";
+//            break;
         default:
             goto die;
         }
        break;
     case 26:
-       /* ignored */
+        /* ignored */
         rn = "ECC";
-       break;
+        break;
     case 27:
         switch (sel) {
         case 0 ... 3:
-           /* ignored */
-           rn = "CacheErr";
-           break;
+            /* ignored */
+            rn = "CacheErr";
+            break;
         default:
             goto die;
         }
@@ -2756,7 +2908,7 @@
         case 3:
         case 5:
         case 7:
-           gen_op_mtc0_datalo();
+            gen_op_mtc0_datalo();
             rn = "DataLo";
             break;
         default:
@@ -2776,7 +2928,7 @@
         case 3:
         case 5:
         case 7:
-           gen_op_mtc0_datahi();
+            gen_op_mtc0_datahi();
             rn = "DataHi";
             break;
         default:
@@ -2787,9 +2939,9 @@
     case 30:
         switch (sel) {
         case 0:
-           gen_op_mtc0_errorepc();
-           rn = "ErrorEPC";
-           break;
+            gen_op_mtc0_errorepc();
+            rn = "ErrorEPC";
+            break;
         default:
             goto die;
         }
@@ -2797,14 +2949,14 @@
     case 31:
         switch (sel) {
         case 0:
-           gen_op_mtc0_desave(); /* EJTAG support */
-           rn = "DESAVE";
-           break;
+            gen_op_mtc0_desave(); /* EJTAG support */
+            rn = "DESAVE";
+            break;
         default:
             goto die;
         }
-       /* Stop translation as we may have switched the execution mode */
-       ctx->bstate = BS_STOP;
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
         break;
     default:
        goto die;
@@ -2827,21 +2979,1189 @@
     generate_exception(ctx, EXCP_RI);
 }
 
-static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
+#ifdef TARGET_MIPS64
+static void gen_dmfc0 (DisasContext *ctx, int reg, int sel)
 {
-    const char *opn = "unk";
+    const char *rn = "invalid";
 
-    if ((!ctx->CP0_Status & (1 << CP0St_CU0) &&
-          (ctx->hflags & MIPS_HFLAG_UM)) &&
-        !(ctx->hflags & MIPS_HFLAG_ERL) &&
-        !(ctx->hflags & MIPS_HFLAG_EXL)) {
-        if (loglevel & CPU_LOG_TB_IN_ASM) {
-            fprintf(logfile, "CP0 is not usable\n");
+    switch (reg) {
+    case 0:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_index();
+            rn = "Index";
+            break;
+        case 1:
+//            gen_op_dmfc0_mvpcontrol(); /* MT ASE */
+            rn = "MVPControl";
+//            break;
+        case 2:
+//            gen_op_dmfc0_mvpconf0(); /* MT ASE */
+            rn = "MVPConf0";
+//            break;
+        case 3:
+//            gen_op_dmfc0_mvpconf1(); /* MT ASE */
+            rn = "MVPConf1";
+//            break;
+        default:
+            goto die;
         }
-        generate_exception (ctx, EXCP_CpU);
-        return;
+        break;
+    case 1:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_random();
+            rn = "Random";
+            break;
+        case 1:
+//            gen_op_dmfc0_vpecontrol(); /* MT ASE */
+            rn = "VPEControl";
+//            break;
+        case 2:
+//            gen_op_dmfc0_vpeconf0(); /* MT ASE */
+            rn = "VPEConf0";
+//            break;
+        case 3:
+//            gen_op_dmfc0_vpeconf1(); /* MT ASE */
+            rn = "VPEConf1";
+//            break;
+        case 4:
+//            gen_op_dmfc0_YQMask(); /* MT ASE */
+            rn = "YQMask";
+//            break;
+        case 5:
+//            gen_op_dmfc0_vpeschedule(); /* MT ASE */
+            rn = "VPESchedule";
+//            break;
+        case 6:
+//            gen_op_dmfc0_vpeschefback(); /* MT ASE */
+            rn = "VPEScheFBack";
+//            break;
+        case 7:
+//            gen_op_dmfc0_vpeopt(); /* MT ASE */
+            rn = "VPEOpt";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 2:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_entrylo0();
+            rn = "EntryLo0";
+            break;
+        case 1:
+//            gen_op_dmfc0_tcstatus(); /* MT ASE */
+            rn = "TCStatus";
+//            break;
+        case 2:
+//            gen_op_dmfc0_tcbind(); /* MT ASE */
+            rn = "TCBind";
+//            break;
+        case 3:
+//            gen_op_dmfc0_tcrestart(); /* MT ASE */
+            rn = "TCRestart";
+//            break;
+        case 4:
+//            gen_op_dmfc0_tchalt(); /* MT ASE */
+            rn = "TCHalt";
+//            break;
+        case 5:
+//            gen_op_dmfc0_tccontext(); /* MT ASE */
+            rn = "TCContext";
+//            break;
+        case 6:
+//            gen_op_dmfc0_tcschedule(); /* MT ASE */
+            rn = "TCSchedule";
+//            break;
+        case 7:
+//            gen_op_dmfc0_tcschefback(); /* MT ASE */
+            rn = "TCScheFBack";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_entrylo1();
+            rn = "EntryLo1";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 4:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_context();
+            rn = "Context";
+            break;
+        case 1:
+//            gen_op_dmfc0_contextconfig(); /* SmartMIPS ASE */
+            rn = "ContextConfig";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 5:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_pagemask();
+            rn = "PageMask";
+            break;
+        case 1:
+            gen_op_mfc0_pagegrain();
+            rn = "PageGrain";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 6:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_wired();
+            rn = "Wired";
+            break;
+        case 1:
+//            gen_op_dmfc0_srsconf0(); /* shadow registers */
+            rn = "SRSConf0";
+//            break;
+        case 2:
+//            gen_op_dmfc0_srsconf1(); /* shadow registers */
+            rn = "SRSConf1";
+//            break;
+        case 3:
+//            gen_op_dmfc0_srsconf2(); /* shadow registers */
+            rn = "SRSConf2";
+//            break;
+        case 4:
+//            gen_op_dmfc0_srsconf3(); /* shadow registers */
+            rn = "SRSConf3";
+//            break;
+        case 5:
+//            gen_op_dmfc0_srsconf4(); /* shadow registers */
+            rn = "SRSConf4";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 7:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_hwrena();
+            rn = "HWREna";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 8:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_badvaddr();
+            rn = "BadVaddr";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 9:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_count();
+            rn = "Count";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        break;
+    case 10:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_entryhi();
+            rn = "EntryHi";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 11:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_compare();
+            rn = "Compare";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        break;
+    case 12:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_status();
+            rn = "Status";
+            break;
+        case 1:
+            gen_op_mfc0_intctl();
+            rn = "IntCtl";
+            break;
+        case 2:
+            gen_op_mfc0_srsctl();
+            rn = "SRSCtl";
+            break;
+        case 3:
+            gen_op_mfc0_srsmap(); /* shadow registers */
+            rn = "SRSMap";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 13:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_cause();
+            rn = "Cause";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 14:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_epc();
+            rn = "EPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 15:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_prid();
+            rn = "PRid";
+            break;
+        case 1:
+            gen_op_mfc0_ebase();
+            rn = "EBase";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_config0();
+            rn = "Config";
+            break;
+        case 1:
+            gen_op_mfc0_config1();
+            rn = "Config1";
+            break;
+        case 2:
+            gen_op_mfc0_config2();
+            rn = "Config2";
+            break;
+        case 3:
+            gen_op_mfc0_config3();
+            rn = "Config3";
+            break;
+       /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_lladdr();
+            rn = "LLAddr";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 18:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_watchlo0();
+            rn = "WatchLo";
+            break;
+        case 1:
+//            gen_op_dmfc0_watchlo1();
+            rn = "WatchLo1";
+//            break;
+        case 2:
+//            gen_op_dmfc0_watchlo2();
+            rn = "WatchLo2";
+//            break;
+        case 3:
+//            gen_op_dmfc0_watchlo3();
+            rn = "WatchLo3";
+//            break;
+        case 4:
+//            gen_op_dmfc0_watchlo4();
+            rn = "WatchLo4";
+//            break;
+        case 5:
+//            gen_op_dmfc0_watchlo5();
+            rn = "WatchLo5";
+//            break;
+        case 6:
+//            gen_op_dmfc0_watchlo6();
+            rn = "WatchLo6";
+//            break;
+        case 7:
+//            gen_op_dmfc0_watchlo7();
+            rn = "WatchLo7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 19:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_watchhi0();
+            rn = "WatchHi";
+            break;
+        case 1:
+//            gen_op_mfc0_watchhi1();
+            rn = "WatchHi1";
+//            break;
+        case 2:
+//            gen_op_mfc0_watchhi2();
+            rn = "WatchHi2";
+//            break;
+        case 3:
+//            gen_op_mfc0_watchhi3();
+            rn = "WatchHi3";
+//            break;
+        case 4:
+//            gen_op_mfc0_watchhi4();
+            rn = "WatchHi4";
+//            break;
+        case 5:
+//            gen_op_mfc0_watchhi5();
+            rn = "WatchHi5";
+//            break;
+        case 6:
+//            gen_op_mfc0_watchhi6();
+            rn = "WatchHi6";
+//            break;
+        case 7:
+//            gen_op_mfc0_watchhi7();
+            rn = "WatchHi7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 20:
+        switch (sel) {
+        case 0:
+            /* 64 bit MMU only */
+            gen_op_dmfc0_xcontext();
+            rn = "XContext";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 21:
+       /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_framemask();
+            rn = "Framemask";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 22:
+        /* ignored */
+        rn = "'Diagnostic"; /* implementation dependent */
+        break;
+    case 23:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_debug(); /* EJTAG support */
+            rn = "Debug";
+            break;
+        case 1:
+//            gen_op_dmfc0_tracecontrol(); /* PDtrace support */
+            rn = "TraceControl";
+//            break;
+        case 2:
+//            gen_op_dmfc0_tracecontrol2(); /* PDtrace support */
+            rn = "TraceControl2";
+//            break;
+        case 3:
+//            gen_op_dmfc0_usertracedata(); /* PDtrace support */
+            rn = "UserTraceData";
+//            break;
+        case 4:
+//            gen_op_dmfc0_debug(); /* PDtrace support */
+            rn = "TraceBPC";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 24:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_depc(); /* EJTAG support */
+            rn = "DEPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 25:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_performance0();
+            rn = "Performance0";
+            break;
+        case 1:
+//            gen_op_dmfc0_performance1();
+            rn = "Performance1";
+//            break;
+        case 2:
+//            gen_op_dmfc0_performance2();
+            rn = "Performance2";
+//            break;
+        case 3:
+//            gen_op_dmfc0_performance3();
+            rn = "Performance3";
+//            break;
+        case 4:
+//            gen_op_dmfc0_performance4();
+            rn = "Performance4";
+//            break;
+        case 5:
+//            gen_op_dmfc0_performance5();
+            rn = "Performance5";
+//            break;
+        case 6:
+//            gen_op_dmfc0_performance6();
+            rn = "Performance6";
+//            break;
+        case 7:
+//            gen_op_dmfc0_performance7();
+            rn = "Performance7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 26:
+       rn = "ECC";
+       break;
+    case 27:
+        switch (sel) {
+        /* ignored */
+        case 0 ... 3:
+            rn = "CacheErr";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mfc0_taglo();
+            rn = "TagLo";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mfc0_datalo();
+            rn = "DataLo";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 29:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mfc0_taghi();
+            rn = "TagHi";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mfc0_datahi();
+            rn = "DataHi";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 30:
+        switch (sel) {
+        case 0:
+            gen_op_dmfc0_errorepc();
+            rn = "ErrorEPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 31:
+        switch (sel) {
+        case 0:
+            gen_op_mfc0_desave(); /* EJTAG support */
+            rn = "DESAVE";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    default:
+        goto die;
     }
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    return;
 
+die:
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmfc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    generate_exception(ctx, EXCP_RI);
+}
+
+static void gen_dmtc0 (DisasContext *ctx, int reg, int sel)
+{
+    const char *rn = "invalid";
+
+    switch (reg) {
+    case 0:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_index();
+            rn = "Index";
+            break;
+        case 1:
+//            gen_op_dmtc0_mvpcontrol(); /* MT ASE */
+            rn = "MVPControl";
+//            break;
+        case 2:
+//            gen_op_dmtc0_mvpconf0(); /* MT ASE */
+            rn = "MVPConf0";
+//            break;
+        case 3:
+//            gen_op_dmtc0_mvpconf1(); /* MT ASE */
+            rn = "MVPConf1";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 1:
+        switch (sel) {
+        case 0:
+            /* ignored */
+            rn = "Random";
+            break;
+        case 1:
+//            gen_op_dmtc0_vpecontrol(); /* MT ASE */
+            rn = "VPEControl";
+//            break;
+        case 2:
+//            gen_op_dmtc0_vpeconf0(); /* MT ASE */
+            rn = "VPEConf0";
+//            break;
+        case 3:
+//            gen_op_dmtc0_vpeconf1(); /* MT ASE */
+            rn = "VPEConf1";
+//            break;
+        case 4:
+//            gen_op_dmtc0_YQMask(); /* MT ASE */
+            rn = "YQMask";
+//            break;
+        case 5:
+//            gen_op_dmtc0_vpeschedule(); /* MT ASE */
+            rn = "VPESchedule";
+//            break;
+        case 6:
+//            gen_op_dmtc0_vpeschefback(); /* MT ASE */
+            rn = "VPEScheFBack";
+//            break;
+        case 7:
+//            gen_op_dmtc0_vpeopt(); /* MT ASE */
+            rn = "VPEOpt";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 2:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_entrylo0();
+            rn = "EntryLo0";
+            break;
+        case 1:
+//            gen_op_dmtc0_tcstatus(); /* MT ASE */
+            rn = "TCStatus";
+//            break;
+        case 2:
+//            gen_op_dmtc0_tcbind(); /* MT ASE */
+            rn = "TCBind";
+//            break;
+        case 3:
+//            gen_op_dmtc0_tcrestart(); /* MT ASE */
+            rn = "TCRestart";
+//            break;
+        case 4:
+//            gen_op_dmtc0_tchalt(); /* MT ASE */
+            rn = "TCHalt";
+//            break;
+        case 5:
+//            gen_op_dmtc0_tccontext(); /* MT ASE */
+            rn = "TCContext";
+//            break;
+        case 6:
+//            gen_op_dmtc0_tcschedule(); /* MT ASE */
+            rn = "TCSchedule";
+//            break;
+        case 7:
+//            gen_op_dmtc0_tcschefback(); /* MT ASE */
+            rn = "TCScheFBack";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 3:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_entrylo1();
+            rn = "EntryLo1";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 4:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_context();
+            rn = "Context";
+            break;
+        case 1:
+//           gen_op_dmtc0_contextconfig(); /* SmartMIPS ASE */
+            rn = "ContextConfig";
+//           break;
+        default:
+            goto die;
+        }
+        break;
+    case 5:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_pagemask();
+            rn = "PageMask";
+            break;
+        case 1:
+            gen_op_mtc0_pagegrain();
+            rn = "PageGrain";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 6:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_wired();
+            rn = "Wired";
+            break;
+        case 1:
+//            gen_op_dmtc0_srsconf0(); /* shadow registers */
+            rn = "SRSConf0";
+//            break;
+        case 2:
+//            gen_op_dmtc0_srsconf1(); /* shadow registers */
+            rn = "SRSConf1";
+//            break;
+        case 3:
+//            gen_op_dmtc0_srsconf2(); /* shadow registers */
+            rn = "SRSConf2";
+//            break;
+        case 4:
+//            gen_op_dmtc0_srsconf3(); /* shadow registers */
+            rn = "SRSConf3";
+//            break;
+        case 5:
+//            gen_op_dmtc0_srsconf4(); /* shadow registers */
+            rn = "SRSConf4";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 7:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_hwrena();
+            rn = "HWREna";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 8:
+        /* ignored */
+        rn = "BadVaddr";
+        break;
+    case 9:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_count();
+            rn = "Count";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 10:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_entryhi();
+            rn = "EntryHi";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 11:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_compare();
+            rn = "Compare";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 12:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_status();
+            rn = "Status";
+            break;
+        case 1:
+            gen_op_mtc0_intctl();
+            rn = "IntCtl";
+            break;
+        case 2:
+            gen_op_mtc0_srsctl();
+            rn = "SRSCtl";
+            break;
+        case 3:
+            gen_op_mtc0_srsmap(); /* shadow registers */
+            rn = "SRSMap";
+            break;
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 13:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_cause();
+            rn = "Cause";
+            break;
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 14:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_epc();
+            rn = "EPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 15:
+        switch (sel) {
+        case 0:
+            /* ignored */
+            rn = "PRid";
+            break;
+        case 1:
+            gen_op_mtc0_ebase();
+            rn = "EBase";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 16:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_config0();
+            rn = "Config";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
+            break;
+        case 1:
+            /* ignored */
+            rn = "Config1";
+            break;
+        case 2:
+            gen_op_mtc0_config2();
+            rn = "Config2";
+            /* Stop translation as we may have switched the execution mode */
+            ctx->bstate = BS_STOP;
+            break;
+        case 3:
+            /* ignored */
+            rn = "Config3";
+            break;
+        /* 6,7 are implementation dependent */
+        default:
+            rn = "Invalid config selector";
+            goto die;
+        }
+        break;
+    case 17:
+        switch (sel) {
+        case 0:
+            /* ignored */
+            rn = "LLAddr";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 18:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_watchlo0();
+            rn = "WatchLo";
+            break;
+        case 1:
+//            gen_op_dmtc0_watchlo1();
+            rn = "WatchLo1";
+//            break;
+        case 2:
+//            gen_op_dmtc0_watchlo2();
+            rn = "WatchLo2";
+//            break;
+        case 3:
+//            gen_op_dmtc0_watchlo3();
+            rn = "WatchLo3";
+//            break;
+        case 4:
+//            gen_op_dmtc0_watchlo4();
+            rn = "WatchLo4";
+//            break;
+        case 5:
+//            gen_op_dmtc0_watchlo5();
+            rn = "WatchLo5";
+//            break;
+        case 6:
+//            gen_op_dmtc0_watchlo6();
+            rn = "WatchLo6";
+//            break;
+        case 7:
+//            gen_op_dmtc0_watchlo7();
+            rn = "WatchLo7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 19:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_watchhi0();
+            rn = "WatchHi";
+            break;
+        case 1:
+//            gen_op_dmtc0_watchhi1();
+            rn = "WatchHi1";
+//            break;
+        case 2:
+//            gen_op_dmtc0_watchhi2();
+            rn = "WatchHi2";
+//            break;
+        case 3:
+//            gen_op_dmtc0_watchhi3();
+            rn = "WatchHi3";
+//            break;
+        case 4:
+//            gen_op_dmtc0_watchhi4();
+            rn = "WatchHi4";
+//            break;
+        case 5:
+//            gen_op_dmtc0_watchhi5();
+            rn = "WatchHi5";
+//            break;
+        case 6:
+//            gen_op_dmtc0_watchhi6();
+            rn = "WatchHi6";
+//            break;
+        case 7:
+//            gen_op_dmtc0_watchhi7();
+            rn = "WatchHi7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 20:
+        switch (sel) {
+        case 0:
+            /* 64 bit MMU only */
+            gen_op_dmtc0_xcontext();
+            rn = "XContext";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 21:
+       /* Officially reserved, but sel 0 is used for R1x000 framemask */
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_framemask();
+            rn = "Framemask";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 22:
+        /* ignored */
+        rn = "Diagnostic"; /* implementation dependent */
+        break;
+    case 23:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_debug(); /* EJTAG support */
+            rn = "Debug";
+            break;
+        case 1:
+//            gen_op_dmtc0_tracecontrol(); /* PDtrace support */
+            rn = "TraceControl";
+//            break;
+        case 2:
+//            gen_op_dmtc0_tracecontrol2(); /* PDtrace support */
+            rn = "TraceControl2";
+//            break;
+        case 3:
+//            gen_op_dmtc0_usertracedata(); /* PDtrace support */
+            rn = "UserTraceData";
+//            break;
+        case 4:
+//            gen_op_dmtc0_debug(); /* PDtrace support */
+            rn = "TraceBPC";
+//            break;
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    case 24:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_depc(); /* EJTAG support */
+            rn = "DEPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 25:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_performance0();
+            rn = "Performance0";
+            break;
+        case 1:
+//            gen_op_dmtc0_performance1();
+            rn = "Performance1";
+//            break;
+        case 2:
+//            gen_op_dmtc0_performance2();
+            rn = "Performance2";
+//            break;
+        case 3:
+//            gen_op_dmtc0_performance3();
+            rn = "Performance3";
+//            break;
+        case 4:
+//            gen_op_dmtc0_performance4();
+            rn = "Performance4";
+//            break;
+        case 5:
+//            gen_op_dmtc0_performance5();
+            rn = "Performance5";
+//            break;
+        case 6:
+//            gen_op_dmtc0_performance6();
+            rn = "Performance6";
+//            break;
+        case 7:
+//            gen_op_dmtc0_performance7();
+            rn = "Performance7";
+//            break;
+        default:
+            goto die;
+        }
+        break;
+    case 26:
+        /* ignored */
+        rn = "ECC";
+        break;
+    case 27:
+        switch (sel) {
+        case 0 ... 3:
+            /* ignored */
+            rn = "CacheErr";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 28:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mtc0_taglo();
+            rn = "TagLo";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mtc0_datalo();
+            rn = "DataLo";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 29:
+        switch (sel) {
+        case 0:
+        case 2:
+        case 4:
+        case 6:
+            gen_op_mtc0_taghi();
+            rn = "TagHi";
+            break;
+        case 1:
+        case 3:
+        case 5:
+        case 7:
+            gen_op_mtc0_datahi();
+            rn = "DataHi";
+            break;
+        default:
+            rn = "invalid sel";
+            goto die;
+        }
+        break;
+    case 30:
+        switch (sel) {
+        case 0:
+            gen_op_dmtc0_errorepc();
+            rn = "ErrorEPC";
+            break;
+        default:
+            goto die;
+        }
+        break;
+    case 31:
+        switch (sel) {
+        case 0:
+            gen_op_mtc0_desave(); /* EJTAG support */
+            rn = "DESAVE";
+            break;
+        default:
+            goto die;
+        }
+        /* Stop translation as we may have switched the execution mode */
+        ctx->bstate = BS_STOP;
+        break;
+    default:
+        goto die;
+    }
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
+        fprintf(logfile, "dmtc0 %s (reg %d sel %d)\n",
+                rn, reg, sel);
+    }
+#endif
+    generate_exception(ctx, EXCP_RI);
+}
+#endif /* TARGET_MIPS64 */
+
+static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd)
+{
+    const char *opn = "unk";
+
     switch (opc) {
     case OPC_MFC0:
         if (rt == 0) {
@@ -2853,15 +4173,26 @@
         opn = "mfc0";
         break;
     case OPC_MTC0:
-        /* If we get an exception, we want to restart at next instruction */
-       /* XXX: breaks for mtc in delay slot */
-        ctx->pc += 4;
-        save_cpu_state(ctx, 1);
-        ctx->pc -= 4;
         GEN_LOAD_REG_TN(T0, rt);
         gen_mtc0(ctx, rd, ctx->opcode & 0x7);
         opn = "mtc0";
         break;
+#ifdef TARGET_MIPS64
+    case OPC_DMFC0:
+        if (rt == 0) {
+            /* Treat as NOP */
+            return;
+        }
+        gen_dmfc0(ctx, rd, ctx->opcode & 0x7);
+        gen_op_store_T0_gpr(rt);
+        opn = "dmfc0";
+        break;
+    case OPC_DMTC0:
+        GEN_LOAD_REG_TN(T0, rt);
+        gen_dmtc0(ctx, rd, ctx->opcode & 0x7);
+        opn = "dmtc0";
+        break;
+#endif
 #if defined(MIPS_USES_R4K_TLB)
     case OPC_TLBWI:
         gen_op_tlbwi();
@@ -2917,11 +4248,9 @@
     MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
 }
 
-#ifdef MIPS_USES_FPU
-
 /* CP1 Branches (before delay slot) */
 static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
-                                 int32_t offset)
+                                 int32_t cc, int32_t offset)
 {
     target_ulong btarget;
 
@@ -2929,33 +4258,51 @@
 
     switch (op) {
     case OPC_BC1F:
-        gen_op_bc1f();
-        MIPS_DEBUG("bc1f " TLSZ, btarget);
+        gen_op_bc1f(cc);
+        MIPS_DEBUG("bc1f " TARGET_FMT_lx, btarget);
         goto not_likely;
     case OPC_BC1FL:
-        gen_op_bc1f();
-        MIPS_DEBUG("bc1fl " TLSZ, btarget);
+        gen_op_bc1f(cc);
+        MIPS_DEBUG("bc1fl " TARGET_FMT_lx, btarget);
         goto likely;
     case OPC_BC1T:
-        gen_op_bc1t();
-        MIPS_DEBUG("bc1t " TLSZ, btarget);
-    not_likely:
-        ctx->hflags |= MIPS_HFLAG_BC;
-        break;
+        gen_op_bc1t(cc);
+        MIPS_DEBUG("bc1t " TARGET_FMT_lx, btarget);
+        goto not_likely;
     case OPC_BC1TL:
-        gen_op_bc1t();
-        MIPS_DEBUG("bc1tl " TLSZ, btarget);
+        gen_op_bc1t(cc);
+        MIPS_DEBUG("bc1tl " TARGET_FMT_lx, btarget);
     likely:
         ctx->hflags |= MIPS_HFLAG_BL;
+        gen_op_set_bcond();
+        gen_op_save_bcond();
         break;
-    default:    
-        MIPS_INVAL("cp1 branch/jump");
-        generate_exception_err (ctx, EXCP_RI, 1);
+    case OPC_BC1FANY2:
+        gen_op_bc1fany2(cc);
+        MIPS_DEBUG("bc1fany2 " TARGET_FMT_lx, btarget);
+        goto not_likely;
+    case OPC_BC1TANY2:
+        gen_op_bc1tany2(cc);
+        MIPS_DEBUG("bc1tany2 " TARGET_FMT_lx, btarget);
+        goto not_likely;
+    case OPC_BC1FANY4:
+        gen_op_bc1fany4(cc);
+        MIPS_DEBUG("bc1fany4 " TARGET_FMT_lx, btarget);
+        goto not_likely;
+    case OPC_BC1TANY4:
+        gen_op_bc1tany4(cc);
+        MIPS_DEBUG("bc1tany4 " TARGET_FMT_lx, btarget);
+    not_likely:
+        ctx->hflags |= MIPS_HFLAG_BC;
+        gen_op_set_bcond();
+        break;
+    default:
+        MIPS_INVAL("cp1 branch");
+        generate_exception (ctx, EXCP_RI);
         return;
     }
-    gen_op_set_bcond();
 
-    MIPS_DEBUG("enter ds: cond %02x target " TLSZ,
+    MIPS_DEBUG("enter ds: cond %02x target " TARGET_FMT_lx,
                ctx->hflags, btarget);
     ctx->btarget = btarget;
 
@@ -2963,6 +4310,29 @@
 }
 
 /* Coprocessor 1 (FPU) */
+
+/* verify if floating point register is valid; an operation is not defined
+ * if bit 0 of any register specification is set and the FR bit in the
+ * Status register equals zero, since the register numbers specify an
+ * even-odd pair of adjacent coprocessor general registers. When the FR bit
+ * in the Status register equals one, both even and odd register numbers
+ * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
+ * 
+ * Multiple 64 bit wide registers can be checked by calling
+ * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
+ * 
+ * FIXME: This is broken for R2, it needs to be checked at runtime, not
+ * at translation time.
+ */
+#define CHECK_FR(ctx, freg) do { \
+        if (!((ctx)->CP0_Status & (1 << CP0St_FR)) && ((freg) & 1)) { \
+            generate_exception (ctx, EXCP_RI); \
+            return; \
+        } \
+    } while(0)
+
+#define FOP(func, fmt) (((fmt) << 21) | (func))
+
 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
 {
     const char *opn = "unk";
@@ -2981,59 +4351,93 @@
         opn = "mtc1";
         break;
     case OPC_CFC1:
-        if (fs != 0 && fs != 31) {
-            MIPS_INVAL("cfc1 freg");
-            generate_exception_err (ctx, EXCP_RI, 1);
-            return;
-        }
         GEN_LOAD_IMM_TN(T1, fs);
         gen_op_cfc1();
         GEN_STORE_TN_REG(rt, T0);
         opn = "cfc1";
         break;
     case OPC_CTC1:
-         if (fs != 0 && fs != 31) {
-            MIPS_INVAL("ctc1 freg");
-            generate_exception_err (ctx, EXCP_RI, 1);
-            return;
-        }
         GEN_LOAD_IMM_TN(T1, fs);
         GEN_LOAD_REG_TN(T0, rt);
         gen_op_ctc1();
         opn = "ctc1";
         break;
+    case OPC_DMFC1:
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_dmfc1();
+        GEN_STORE_TN_REG(rt, T0);
+        opn = "dmfc1";
+        break;
+    case OPC_DMTC1:
+        GEN_LOAD_REG_TN(T0, rt);
+        gen_op_dmtc1();
+        GEN_STORE_FTN_FREG(fs, DT0);
+        opn = "dmtc1";
+        break;
+    case OPC_MFHC1:
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_mfhc1();
+        GEN_STORE_TN_REG(rt, T0);
+        opn = "mfhc1";
+        break;
+    case OPC_MTHC1:
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_REG_TN(T0, rt);
+        gen_op_mthc1();
+        GEN_STORE_FTN_FREG(fs, WTH0);
+        opn = "mthc1";
+        break;
     default:
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "Invalid CP1 opcode: %08x %03x %03x %03x\n",
                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
                     ((ctx->opcode >> 16) & 0x1F));
         }
-        generate_exception_err (ctx, EXCP_RI, 1);
+        generate_exception (ctx, EXCP_RI);
         return;
     }
     MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
 }
 
-/* verify if floating point register is valid; an operation is not defined
- * if bit 0 of any register specification is set and the FR bit in the
- * Status register equals zero, since the register numbers specify an
- * even-odd pair of adjacent coprocessor general registers. When the FR bit
- * in the Status register equals one, both even and odd register numbers
- * are valid.
- * 
- * Multiple float registers can be checked by calling
- * CHECK_FR(ctx, freg1 | freg2 | ... | fregN);
- */
-#define CHECK_FR(ctx, freg) do { \
-        if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \
-            generate_exception_err (ctx, EXCP_RI, 1); \
-            return; \
-        } \
-    } while(0)
+static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
+{
+    uint32_t ccbit;
 
-#define FOP(func, fmt) (((fmt) << 21) | (func))
+    GEN_LOAD_REG_TN(T0, rd);
+    GEN_LOAD_REG_TN(T1, rs);
+    if (cc)
+        ccbit = 1 << (24 + cc);
+    else
+        ccbit = 1 << 23;
+    if (!tf)
+        gen_op_movf(ccbit);
+    else
+        gen_op_movt(ccbit);
+    GEN_STORE_TN_REG(rd, T0);
+}
 
-static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd)
+#define GEN_MOVCF(fmt)                                                \
+static void glue(gen_movcf_, fmt) (DisasContext *ctx, int cc, int tf) \
+{                                                                     \
+    uint32_t ccbit;                                                   \
+                                                                      \
+    if (cc)                                                           \
+        ccbit = 1 << (24 + cc);                                       \
+    else                                                              \
+        ccbit = 1 << 23;                                              \
+    if (!tf)                                                          \
+        glue(gen_op_float_movf_, fmt)(ccbit);                         \
+    else                                                              \
+        glue(gen_op_float_movt_, fmt)(ccbit);                         \
+}
+GEN_MOVCF(d);
+GEN_MOVCF(s);
+GEN_MOVCF(ps);
+#undef GEN_MOVCF
+
+static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,
+                        int fs, int fd, int cc)
 {
     const char *opn = "unk";
     const char *condnames[] = {
@@ -3058,6 +4462,187 @@
     uint32_t func = ctx->opcode & 0x3f;
 
     switch (ctx->opcode & FOP(0x3f, 0x1f)) {
+    case FOP(0, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_add_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "add.s";
+        binary = 1;
+        break;
+    case FOP(1, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_sub_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "sub.s";
+        binary = 1;
+        break;
+    case FOP(2, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_mul_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "mul.s";
+        binary = 1;
+        break;
+    case FOP(3, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_div_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "div.s";
+        binary = 1;
+        break;
+    case FOP(4, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_sqrt_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "sqrt.s";
+        break;
+    case FOP(5, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_abs_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "abs.s";
+        break;
+    case FOP(6, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_mov_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "mov.s";
+        break;
+    case FOP(7, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_chs_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "neg.s";
+        break;
+    case FOP(8, 16):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_roundl_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "round.l.s";
+        break;
+    case FOP(9, 16):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_truncl_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "trunc.l.s";
+        break;
+    case FOP(10, 16):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_ceill_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "ceil.l.s";
+        break;
+    case FOP(11, 16):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_floorl_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "floor.l.s";
+        break;
+    case FOP(12, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_roundw_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "round.w.s";
+        break;
+    case FOP(13, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_truncw_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "trunc.w.s";
+        break;
+    case FOP(14, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_ceilw_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "ceil.w.s";
+        break;
+    case FOP(15, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_floorw_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "floor.w.s";
+        break;
+    case FOP(17, 16):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "movcf.s";
+        break;
+    case FOP(18, 16):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        gen_op_float_movz_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "movz.s";
+        break;
+    case FOP(19, 16):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        gen_op_float_movn_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "movn.s";
+        break;
+    case FOP(33, 16):
+        CHECK_FR(ctx, fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_cvtd_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.d.s";
+        break;
+    case FOP(36, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_cvtw_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "cvt.w.s";
+        break;
+    case FOP(37, 16):
+        CHECK_FR(ctx, fs | fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_cvtl_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.l.s";
+        break;
+    case FOP(38, 16):
+        CHECK_FR(ctx, fs | ft | fd);
+        GEN_LOAD_FREG_FTN(WT1, fs);
+        GEN_LOAD_FREG_FTN(WT0, ft);
+        gen_op_float_cvtps_s();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.ps.s";
+        break;
+    case FOP(48, 16):
+    case FOP(49, 16):
+    case FOP(50, 16):
+    case FOP(51, 16):
+    case FOP(52, 16):
+    case FOP(53, 16):
+    case FOP(54, 16):
+    case FOP(55, 16):
+    case FOP(56, 16):
+    case FOP(57, 16):
+    case FOP(58, 16):
+    case FOP(59, 16):
+    case FOP(60, 16):
+    case FOP(61, 16):
+    case FOP(62, 16):
+    case FOP(63, 16):
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_cmp_s(func-48, cc);
+        opn = condnames[func-48];
+        break;
     case FOP(0, 17):
         CHECK_FR(ctx, fs | ft | fd);
         GEN_LOAD_FREG_FTN(DT0, fs);
@@ -3122,52 +4707,86 @@
         GEN_STORE_FTN_FREG(fd, DT2);
         opn = "neg.d";
         break;
-    /*  8 - round.l */
-    /*  9 - trunc.l */
-    /* 10 - ceil.l  */
-    /* 11 - floor.l */
+    case FOP(8, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_roundl_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "round.l.d";
+        break;
+    case FOP(9, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_truncl_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "trunc.l.d";
+        break;
+    case FOP(10, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_ceill_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "ceil.l.d";
+        break;
+    case FOP(11, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_floorl_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "floor.l.d";
+        break;
     case FOP(12, 17):
-        CHECK_FR(ctx, fs | fd);
+        CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_roundw_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "round.w.d";
         break;
     case FOP(13, 17):
-        CHECK_FR(ctx, fs | fd);
+        CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_truncw_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "trunc.w.d";
         break;
     case FOP(14, 17):
-        CHECK_FR(ctx, fs | fd);
+        CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_ceilw_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "ceil.w.d";
         break;
     case FOP(15, 17):
-        CHECK_FR(ctx, fs | fd);
+        CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(DT0, fs);
         gen_op_float_floorw_d();
         GEN_STORE_FTN_FREG(fd, WT2);
         opn = "floor.w.d";
         break;
-    case FOP(33, 16): /* cvt.d.s */
-        CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_cvtd_s();
+    case FOP(17, 17):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT2, fd);
+        gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);
         GEN_STORE_FTN_FREG(fd, DT2);
-        opn = "cvt.d.s";
+        opn = "movcf.d";
         break;
-    case FOP(33, 20): /* cvt.d.w */
-        CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_cvtd_w();
+    case FOP(18, 17):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT2, fd);
+        gen_op_float_movz_d();
         GEN_STORE_FTN_FREG(fd, DT2);
-        opn = "cvt.d.w";
+        opn = "movz.d";
         break;
+    case FOP(19, 17):
+        GEN_LOAD_REG_TN(T0, ft);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT2, fd);
+        gen_op_float_movn_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "movn.d";
+        break;
     case FOP(48, 17):
     case FOP(49, 17):
     case FOP(50, 17):
@@ -3187,144 +4806,246 @@
         CHECK_FR(ctx, fs | ft);
         GEN_LOAD_FREG_FTN(DT0, fs);
         GEN_LOAD_FREG_FTN(DT1, ft);
-        gen_cmp_d(func-48);
+        gen_cmp_d(func-48, cc);
         opn = condnames[func-48];
         break;
-    case FOP(0, 16):
-        CHECK_FR(ctx, fs | ft | fd);
+    case FOP(32, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_cvts_d();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "cvt.s.d";
+        break;
+    case FOP(36, 17):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_cvtw_d();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "cvt.w.d";
+        break;
+    case FOP(37, 17):
+        CHECK_FR(ctx, fs | fd);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_cvtl_d();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.l.d";
+        break;
+    case FOP(32, 20):
         GEN_LOAD_FREG_FTN(WT0, fs);
-        GEN_LOAD_FREG_FTN(WT1, ft);
-        gen_op_float_add_s();
+        gen_op_float_cvts_w();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "add.s";
-        binary = 1;
+        opn = "cvt.s.w";
         break;
-    case FOP(1, 16):
+    case FOP(33, 20):
+        CHECK_FR(ctx, fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        gen_op_float_cvtd_w();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.d.w";
+        break;
+    case FOP(32, 21):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_cvts_l();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "cvt.s.l";
+        break;
+    case FOP(33, 21):
+        CHECK_FR(ctx, fs | fd);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        gen_op_float_cvtd_l();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "cvt.d.l";
+        break;
+    case FOP(38, 20):
+    case FOP(38, 21):
+        CHECK_FR(ctx, fs | fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_cvtps_pw();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "cvt.ps.pw";
+        break;
+    case FOP(0, 22):
         CHECK_FR(ctx, fs | ft | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
         GEN_LOAD_FREG_FTN(WT1, ft);
-        gen_op_float_sub_s();
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_add_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "sub.s";
-        binary = 1;
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "add.ps";
         break;
-    case FOP(2, 16):
+    case FOP(1, 22):
         CHECK_FR(ctx, fs | ft | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
         GEN_LOAD_FREG_FTN(WT1, ft);
-        gen_op_float_mul_s();
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_sub_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "mul.s";
-        binary = 1;
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "sub.ps";
         break;
-    case FOP(3, 16):
+    case FOP(2, 22):
         CHECK_FR(ctx, fs | ft | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
         GEN_LOAD_FREG_FTN(WT1, ft);
-        gen_op_float_div_s();
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_mul_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "div.s";
-        binary = 1;
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "mul.ps";
         break;
-    case FOP(4, 16):
+    case FOP(5, 22):
         CHECK_FR(ctx, fs | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_sqrt_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_abs_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "sqrt.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "abs.ps";
         break;
-    case FOP(5, 16):
+    case FOP(6, 22):
         CHECK_FR(ctx, fs | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_abs_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_mov_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "abs.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "mov.ps";
         break;
-    case FOP(6, 16):
+    case FOP(7, 22):
         CHECK_FR(ctx, fs | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_mov_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_chs_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "mov.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "neg.ps";
         break;
-    case FOP(7, 16):
-        CHECK_FR(ctx, fs | fd);
+    case FOP(17, 22):
+        GEN_LOAD_REG_TN(T0, ft);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_chs_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        GEN_LOAD_FREG_FTN(WTH2, fd);
+        gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "neg.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "movcf.ps";
         break;
-    case FOP(12, 16):
-        CHECK_FR(ctx, fs | fd);
+    case FOP(18, 22):
+        GEN_LOAD_REG_TN(T0, ft);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_roundw_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        GEN_LOAD_FREG_FTN(WTH2, fd);
+        gen_op_float_movz_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "round.w.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "movz.ps";
         break;
-    case FOP(13, 16):
-        CHECK_FR(ctx, fs | fd);
+    case FOP(19, 22):
+        GEN_LOAD_REG_TN(T0, ft);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_truncw_s();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT2, fd);
+        GEN_LOAD_FREG_FTN(WTH2, fd);
+        gen_op_float_movn_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "trunc.w.s";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "movn.ps";
         break;
-    case FOP(32, 17): /* cvt.s.d */
-        CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(DT0, fs);
-        gen_op_float_cvts_d();
+    case FOP(32, 22):
+        CHECK_FR(ctx, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_cvts_pu();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "cvt.s.d";
+        opn = "cvt.s.pu";
         break;
-    case FOP(32, 20): /* cvt.s.w */
+    case FOP(36, 22):
         CHECK_FR(ctx, fs | fd);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_cvts_w();
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        gen_op_float_cvtpw_ps();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "cvt.s.w";
+        GEN_STORE_FTN_FREG(fd, WTH2);
+        opn = "cvt.pw.ps";
         break;
-    case FOP(36, 16): /* cvt.w.s */
-        CHECK_FR(ctx, fs | fd);
+    case FOP(40, 22):
+        CHECK_FR(ctx, fs);
         GEN_LOAD_FREG_FTN(WT0, fs);
-        gen_op_float_cvtw_s();
+        gen_op_float_cvts_pl();
         GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "cvt.w.s";
+        opn = "cvt.s.pl";
         break;
-    case FOP(36, 17): /* cvt.w.d */
-        CHECK_FR(ctx, fs | fd);
-        GEN_LOAD_FREG_FTN(DT0, fs);
-        gen_op_float_cvtw_d();
-        GEN_STORE_FTN_FREG(fd, WT2);
-        opn = "cvt.w.d";
+    case FOP(44, 22):
+        CHECK_FR(ctx, fs | ft | fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_pll_ps();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "pll.ps";
         break;
-    case FOP(48, 16):
-    case FOP(49, 16):
-    case FOP(50, 16):
-    case FOP(51, 16):
-    case FOP(52, 16):
-    case FOP(53, 16):
-    case FOP(54, 16):
-    case FOP(55, 16):
-    case FOP(56, 16):
-    case FOP(57, 16):
-    case FOP(58, 16):
-    case FOP(59, 16):
-    case FOP(60, 16):
-    case FOP(61, 16):
-    case FOP(62, 16):
-    case FOP(63, 16):
+    case FOP(45, 22):
+        CHECK_FR(ctx, fs | ft | fd);
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_plu_ps();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "plu.ps";
+        break;
+    case FOP(46, 22):
+        CHECK_FR(ctx, fs | ft | fd);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        gen_op_float_pul_ps();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "pul.ps";
+        break;
+    case FOP(47, 22):
+        CHECK_FR(ctx, fs | ft | fd);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_op_float_puu_ps();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "puu.ps";
+        break;
+    case FOP(48, 22):
+    case FOP(49, 22):
+    case FOP(50, 22):
+    case FOP(51, 22):
+    case FOP(52, 22):
+    case FOP(53, 22):
+    case FOP(54, 22):
+    case FOP(55, 22):
+    case FOP(56, 22):
+    case FOP(57, 22):
+    case FOP(58, 22):
+    case FOP(59, 22):
+    case FOP(60, 22):
+    case FOP(61, 22):
+    case FOP(62, 22):
+    case FOP(63, 22):
         CHECK_FR(ctx, fs | ft);
         GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WTH0, fs);
         GEN_LOAD_FREG_FTN(WT1, ft);
-        gen_cmp_s(func-48);
+        GEN_LOAD_FREG_FTN(WTH1, ft);
+        gen_cmp_ps(func-48, cc);
         opn = condnames[func-48];
         break;
-    default:    
+    default:
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n",
                     ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,
                     ((ctx->opcode >> 16) & 0x1F));
         }
-        generate_exception_err (ctx, EXCP_RI, 1);
+        generate_exception (ctx, EXCP_RI);
         return;
     }
     if (binary)
@@ -3333,46 +5054,149 @@
         MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
 }
 
-static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
+/* Coprocessor 3 (FPU) */
+static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, int fd,
+                           int base, int index)
 {
-    uint32_t ccbit;
+    const char *opn = "unk";
 
-    if (cc)
-        ccbit = 1 << (24 + cc);
-    else
-        ccbit = 1 << 23;
-    if (!tf)
-        gen_op_movf(ccbit, rd, rs);
-    else
-       gen_op_movt(ccbit, rd, rs);
+    GEN_LOAD_REG_TN(T0, base);
+    GEN_LOAD_REG_TN(T1, index);
+    /* Don't do NOP if destination is zero: we must perform the actual
+     * memory access
+     */
+    switch (opc) {
+    case OPC_LWXC1:
+        op_ldst(lwxc1);
+        GEN_STORE_FTN_FREG(fd, WT0);
+        opn = "lwxc1";
+        break;
+    case OPC_LDXC1:
+        op_ldst(ldxc1);
+        GEN_STORE_FTN_FREG(fd, DT0);
+        opn = "ldxc1";
+        break;
+    case OPC_LUXC1:
+        op_ldst(luxc1);
+        GEN_STORE_FTN_FREG(fd, DT0);
+        opn = "luxc1";
+        break;
+    case OPC_SWXC1:
+        GEN_LOAD_FREG_FTN(WT0, fd);
+        op_ldst(swxc1);
+        opn = "swxc1";
+        break;
+    case OPC_SDXC1:
+        GEN_LOAD_FREG_FTN(DT0, fd);
+        op_ldst(sdxc1);
+        opn = "sdxc1";
+        break;
+    case OPC_SUXC1:
+        GEN_LOAD_FREG_FTN(DT0, fd);
+        op_ldst(suxc1);
+        opn = "suxc1";
+        break;
+    default:
+        MIPS_INVAL("extended float load/store");
+        generate_exception(ctx, EXCP_RI);
+        return;
+    }
+    MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[fd],regnames[index], regnames[base]);
 }
 
-#endif /* MIPS_USES_FPU */
+static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,
+                            int fr, int fs, int ft)
+{
+    const char *opn = "unk";
 
+    /* All of those work only on 64bit FPUs. */
+    CHECK_FR(ctx, fd | fr | fs | ft);
+    switch (opc) {
+    case OPC_ALNV_PS:
+        GEN_LOAD_REG_TN(T0, fr);
+        GEN_LOAD_FREG_FTN(DT0, fs);
+        GEN_LOAD_FREG_FTN(DT1, ft);
+        gen_op_float_alnv_ps();
+        GEN_STORE_FTN_FREG(fd, DT2);
+        opn = "alnv.ps";
+        break;
+    case OPC_MADD_S:
+        GEN_LOAD_FREG_FTN(WT0, fs);
+        GEN_LOAD_FREG_FTN(WT1, ft);
+        GEN_LOAD_FREG_FTN(WT2, fr);
+        gen_op_float_muladd_s();
+        GEN_STORE_FTN_FREG(fd, WT2);
+        opn = "madd.s";
+        break;
+    case OPC_MADD_D:
+        generate_exception (ctx, EXCP_RI);
+        opn = "madd.d";
+        break;
+    case OPC_MADD_PS:
+        generate_exception (ctx, EXCP_RI);
+        opn = "madd.ps";
+        break;
+    case OPC_MSUB_S:
+        generate_exception (ctx, EXCP_RI);
+        opn = "msub.s";
+        break;
+    case OPC_MSUB_D:
+        generate_exception (ctx, EXCP_RI);
+        opn = "msub.d";
+        break;
+    case OPC_MSUB_PS:
+        generate_exception (ctx, EXCP_RI);
+        opn = "msub.ps";
+        break;
+    case OPC_NMADD_S:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmadd.s";
+        break;
+    case OPC_NMADD_D:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmadd.d";
+        break;
+    case OPC_NMADD_PS:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmadd.ps";
+        break;
+    case OPC_NMSUB_S:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmsub.s";
+        break;
+    case OPC_NMSUB_D:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmsub.d";
+        break;
+    case OPC_NMSUB_PS:
+        generate_exception (ctx, EXCP_RI);
+        opn = "nmsub.ps";
+        break;
+    default:    
+        if (loglevel & CPU_LOG_TB_IN_ASM) {
+            fprintf(logfile, "Invalid extended FP arith function: %08x %03x %03x\n",
+                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F);
+        }
+        generate_exception (ctx, EXCP_RI);
+        return;
+    }
+    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
+               fregnames[fs], fregnames[ft]);
+}
+
 /* ISA extensions (ASEs) */
 /* MIPS16 extension to MIPS32 */
 /* SmartMIPS extension to MIPS32 */
 
-#ifdef MIPS_HAS_MIPS64
-/* Coprocessor 3 (FPU) */
+#ifdef TARGET_MIPS64
 
 /* MDMX extension to MIPS64 */
 /* MIPS-3D extension to MIPS64 */
 
 #endif
 
-static void gen_blikely(DisasContext *ctx)
+static void decode_opc (CPUState *env, DisasContext *ctx)
 {
-    int l1;
-    l1 = gen_new_label();
-    gen_op_jnz_T2(l1);
-    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
-    gen_goto_tb(ctx, 1, ctx->pc + 4);
-    gen_set_label(l1);
-}
-
-static void decode_opc (DisasContext *ctx)
-{
     int32_t offset;
     int rs, rt, rd, sa;
     uint32_t op, op1, op2;
@@ -3380,14 +5204,20 @@
 
     /* make sure instructions are on a word boundary */
     if (ctx->pc & 0x3) {
+        env->CP0_BadVAddr = ctx->pc;
         generate_exception(ctx, EXCP_AdEL);
         return;
     }
 
     if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {
+        int l1;
         /* Handle blikely not taken case */
-        MIPS_DEBUG("blikely condition (" TLSZ ")", ctx->pc + 4);
-        gen_blikely(ctx);
+        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
+        l1 = gen_new_label();
+        gen_op_jnz_T2(l1);
+        gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);
+        gen_goto_tb(ctx, 1, ctx->pc + 4);
+        gen_set_label(l1);
     }
     op = MASK_OP_MAJOR(ctx->opcode);
     rs = (ctx->opcode >> 21) & 0x1f;
@@ -3428,34 +5258,46 @@
         case OPC_MTLO:          /* Move to HI/LO */
             gen_HILO(ctx, op1, rs);
             break;
-        case OPC_PMON:          /* Pmon entry point */
+        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */
+#ifdef MIPS_STRICT_STANDARD
+            MIPS_INVAL("PMON / selsl");
+            generate_exception(ctx, EXCP_RI);
+#else
             gen_op_pmon(sa);
+#endif
             break;
         case OPC_SYSCALL:
             generate_exception(ctx, EXCP_SYSCALL);
-            ctx->bstate = BS_EXCP;
             break;
         case OPC_BREAK:
             generate_exception(ctx, EXCP_BREAK);
             break;
-        case OPC_SPIM:        /* SPIM ? */
+        case OPC_SPIM:
+#ifdef MIPS_STRICT_STANDARD
+            MIPS_INVAL("SPIM");
+            generate_exception(ctx, EXCP_RI);
+#else
            /* Implemented as RI exception for now. */
             MIPS_INVAL("spim (unofficial)");
             generate_exception(ctx, EXCP_RI);
+#endif
             break;
         case OPC_SYNC:
             /* Treat as a noop. */
             break;
 
-#ifdef MIPS_USES_FPU
         case OPC_MOVCI:
-            gen_op_cp1_enabled();
-            gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
-                      (ctx->opcode >> 16) & 1);
+            if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+                save_cpu_state(ctx, 1);
+                gen_op_cp1_enabled();
+                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
+                          (ctx->opcode >> 16) & 1);
+            } else {
+                generate_exception_err(ctx, EXCP_CpU, 1);
+            }
             break;
-#endif
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
        /* MIPS64 specific opcodes */
         case OPC_DSLL:
         case OPC_DSRL ... OPC_DSRA:
@@ -3502,7 +5344,7 @@
             }
             /* Treat as a noop */
             break;
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
         case OPC_DCLZ ... OPC_DCLO:
             gen_cl(ctx, op1, rd, rs);
             break;
@@ -3514,77 +5356,86 @@
         }
         break;
     case OPC_SPECIAL3:
-        op1 = MASK_SPECIAL3(ctx->opcode);
-        switch (op1) {
-        case OPC_EXT:
-        case OPC_INS:
+         op1 = MASK_SPECIAL3(ctx->opcode);
+         switch (op1) {
+         case OPC_EXT:
+         case OPC_INS:
+             gen_bitops(ctx, op1, rt, rs, sa, rd);
+             break;
+         case OPC_BSHFL:
+             op2 = MASK_BSHFL(ctx->opcode);
+             switch (op2) {
+             case OPC_WSBH:
+                 GEN_LOAD_REG_TN(T1, rt);
+                 gen_op_wsbh();
+                 break;
+             case OPC_SEB:
+                 GEN_LOAD_REG_TN(T1, rt);
+                 gen_op_seb();
+                 break;
+             case OPC_SEH:
+                 GEN_LOAD_REG_TN(T1, rt);
+                 gen_op_seh();
+                 break;
+             default:            /* Invalid */
+                 MIPS_INVAL("bshfl");
+                 generate_exception(ctx, EXCP_RI);
+                 break;
+            }
+            GEN_STORE_TN_REG(rd, T0);
+            break;
+        case OPC_RDHWR:
+            switch (rd) {
+            case 0:
+                save_cpu_state(ctx, 1);
+                gen_op_rdhwr_cpunum();
+                break;
+            case 1:
+                save_cpu_state(ctx, 1);
+                gen_op_rdhwr_synci_step();
+                break;
+            case 2:
+                save_cpu_state(ctx, 1);
+                gen_op_rdhwr_cc();
+                break;
+            case 3:
+                save_cpu_state(ctx, 1);
+                gen_op_rdhwr_ccres();
+                break;
+            case 29:
+#if defined (CONFIG_USER_ONLY)
+                gen_op_tls_value ();
+                break;
+#endif
+            default:            /* Invalid */
+                MIPS_INVAL("rdhwr");
+                generate_exception(ctx, EXCP_RI);
+                break;
+            }
+            GEN_STORE_TN_REG(rt, T0);
+            break;
+#ifdef TARGET_MIPS64
+        case OPC_DEXTM ... OPC_DEXT:
+        case OPC_DINSM ... OPC_DINS:
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
-        case OPC_BSHFL:
-            op2 = MASK_BSHFL(ctx->opcode);
+        case OPC_DBSHFL:
+            op2 = MASK_DBSHFL(ctx->opcode);
             switch (op2) {
-            case OPC_WSBH:
+            case OPC_DSBH:
                 GEN_LOAD_REG_TN(T1, rt);
-                gen_op_wsbh();
+                gen_op_dsbh();
                 break;
-            case OPC_SEB:
+            case OPC_DSHD:
                 GEN_LOAD_REG_TN(T1, rt);
-                gen_op_seb();
+                gen_op_dshd();
                 break;
-            case OPC_SEH:
-                GEN_LOAD_REG_TN(T1, rt);
-                gen_op_seh();
-                break;
-             default:            /* Invalid */
-                MIPS_INVAL("bshfl");
-                generate_exception(ctx, EXCP_RI);
-                break;
-           }
-           GEN_STORE_TN_REG(rd, T0);
-           break;
-       case OPC_RDHWR:
-           switch (rd) {
-           case 0:
-               gen_op_rdhwr_cpunum();
-               break;
-           case 1:
-               gen_op_rdhwr_synci_step();
-               break;
-           case 2:
-               gen_op_rdhwr_cc();
-               break;
-           case 3:
-               gen_op_rdhwr_ccres();
-               break;
-           default:            /* Invalid */
-               MIPS_INVAL("rdhwr");
-               generate_exception(ctx, EXCP_RI);
-               break;
-           }
-           GEN_STORE_TN_REG(rt, T0);
-           break;
-#ifdef MIPS_HAS_MIPS64
-       case OPC_DEXTM ... OPC_DEXT:
-       case OPC_DINSM ... OPC_DINS:
-           gen_bitops(ctx, op1, rt, rs, sa, rd);
-            break;
-       case OPC_DBSHFL:
-           op2 = MASK_DBSHFL(ctx->opcode);
-           switch (op2) {
-           case OPC_DSBH:
-               GEN_LOAD_REG_TN(T1, rt);
-               gen_op_dsbh();
-               break;
-           case OPC_DSHD:
-               GEN_LOAD_REG_TN(T1, rt);
-               gen_op_dshd();
-               break;
             default:            /* Invalid */
                 MIPS_INVAL("dbshfl");
                 generate_exception(ctx, EXCP_RI);
                 break;
-           }
-           GEN_STORE_TN_REG(rd, T0);
+            }
+            GEN_STORE_TN_REG(rd, T0);
 #endif
         default:            /* Invalid */
             MIPS_INVAL("special3");
@@ -3604,7 +5455,7 @@
             gen_trap(ctx, op1, rs, -1, imm);
             break;
         case OPC_SYNCI:
-           /* treat as noop */
+            /* treat as noop */
             break;
         default:            /* Invalid */
             MIPS_INVAL("REGIMM");
@@ -3613,11 +5464,13 @@
         }
         break;
     case OPC_CP0:
+        save_cpu_state(ctx, 1);
+        gen_op_cp0_enabled();
         op1 = MASK_CP0(ctx->opcode);
         switch (op1) {
         case OPC_MFC0:
         case OPC_MTC0:
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
         case OPC_DMFC0:
         case OPC_DMTC0:
 #endif
@@ -3646,9 +5499,15 @@
             }
             GEN_STORE_TN_REG(rt, T0);
             break;
-        /* Shadow registers (not implemented). */
         case OPC_RDPGPR:
         case OPC_WRPGPR:
+            if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) {
+                /* Shadow registers not implemented. */
+                GEN_LOAD_REG_TN(T0, rt);
+                GEN_STORE_TN_REG(rd, T0);
+            } else
+                generate_exception(ctx, EXCP_RI);
+            break;
         default:
             generate_exception(ctx, EXCP_RI);
             break;
@@ -3684,43 +5543,52 @@
     case OPC_LDC1:
     case OPC_SWC1:
     case OPC_SDC1:
-#if defined(MIPS_USES_FPU)
-        save_cpu_state(ctx, 1);
-        gen_op_cp1_enabled();
-        gen_flt_ldst(ctx, op, rt, rs, imm);
-#else
-        generate_exception_err(ctx, EXCP_CpU, 1);
-#endif
+        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+            save_cpu_state(ctx, 1);
+            gen_op_cp1_enabled();
+            gen_flt_ldst(ctx, op, rt, rs, imm);
+        } else {
+            generate_exception_err(ctx, EXCP_CpU, 1);
+        }
         break;
 
     case OPC_CP1:
-#if defined(MIPS_USES_FPU)
-        save_cpu_state(ctx, 1);
-        gen_op_cp1_enabled();
-        op1 = MASK_CP1(ctx->opcode);
-        switch (op1) {
-        case OPC_MFC1:
-        case OPC_CFC1:
-        case OPC_MTC1:
-        case OPC_CTC1:
-            gen_cp1(ctx, op1, rt, rd);
-            break;
-        case OPC_BC1:
-            gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2);
-            return;
-        case OPC_S_FMT:
-        case OPC_D_FMT:
-        case OPC_W_FMT:
-        case OPC_L_FMT:
-            gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa);
-            break;
-        default:
-            generate_exception_err(ctx, EXCP_RI, 1);
-            break;
+        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+            save_cpu_state(ctx, 1);
+            gen_op_cp1_enabled();
+            op1 = MASK_CP1(ctx->opcode);
+            switch (op1) {
+            case OPC_MFC1:
+            case OPC_CFC1:
+            case OPC_MTC1:
+            case OPC_CTC1:
+#ifdef TARGET_MIPS64
+            case OPC_DMFC1:
+            case OPC_DMTC1:
+#endif
+            case OPC_MFHC1:
+            case OPC_MTHC1:
+                gen_cp1(ctx, op1, rt, rd);
+                break;
+            case OPC_BC1:
+                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
+                                    (rt >> 2) & 0x7, imm << 2);
+                return;
+            case OPC_S_FMT:
+            case OPC_D_FMT:
+            case OPC_W_FMT:
+            case OPC_L_FMT:
+            case OPC_PS_FMT:
+                gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
+                           (imm >> 8) & 0x7);
+                break;
+            default:
+                generate_exception (ctx, EXCP_RI);
+                break;
+            }
+        } else {
+            generate_exception_err(ctx, EXCP_CpU, 1);
         }
-#else
-        generate_exception_err(ctx, EXCP_CpU, 1);
-#endif
         break;
 
     /* COP2.  */
@@ -3733,20 +5601,48 @@
         generate_exception_err(ctx, EXCP_CpU, 2);
         break;
 
-#ifdef MIPS_USES_FPU
     case OPC_CP3:
-        gen_op_cp1_enabled();
-        op1 = MASK_CP3(ctx->opcode);
-        switch (op1) {
-        /* Not implemented */
-        default:
-            generate_exception_err(ctx, EXCP_RI, 1);
-            break;
+        if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+            save_cpu_state(ctx, 1);
+            gen_op_cp1_enabled();
+            op1 = MASK_CP3(ctx->opcode);
+            switch (op1) {
+            case OPC_LWXC1:
+            case OPC_LDXC1:
+            case OPC_LUXC1:
+            case OPC_SWXC1:
+            case OPC_SDXC1:
+            case OPC_SUXC1:
+                gen_flt3_ldst(ctx, op1, sa, rs, rt);
+                break;
+            case OPC_PREFX:
+                /* treat as noop */
+                break;
+            case OPC_ALNV_PS:
+            case OPC_MADD_S:
+            case OPC_MADD_D:
+            case OPC_MADD_PS:
+            case OPC_MSUB_S:
+            case OPC_MSUB_D:
+            case OPC_MSUB_PS:
+            case OPC_NMADD_S:
+            case OPC_NMADD_D:
+            case OPC_NMADD_PS:
+            case OPC_NMSUB_S:
+            case OPC_NMSUB_D:
+            case OPC_NMSUB_PS:
+                gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
+                break;
+            default:
+                generate_exception (ctx, EXCP_RI);
+                break;
+            }
+        } else {
+            generate_exception_err(ctx, EXCP_CpU, 1);
         }
         break;
-#endif
 
-#ifdef MIPS_HAS_MIPS64
+#ifdef TARGET_MIPS64
     /* MIPS64 opcodes */
     case OPC_LWU:
     case OPC_LDL ... OPC_LDR:
@@ -3775,12 +5671,12 @@
         break;
     }
     if (ctx->hflags & MIPS_HFLAG_BMASK) {
-        int hflags = ctx->hflags;
+        int hflags = ctx->hflags & MIPS_HFLAG_BMASK;
         /* Branches completion */
         ctx->hflags &= ~MIPS_HFLAG_BMASK;
         ctx->bstate = BS_BRANCH;
         save_cpu_state(ctx, 0);
-        switch (hflags & MIPS_HFLAG_BMASK) {
+        switch (hflags) {
         case MIPS_HFLAG_B:
             /* unconditional branch */
             MIPS_DEBUG("unconditional branch");
@@ -3807,6 +5703,8 @@
             /* unconditional branch to register */
             MIPS_DEBUG("branch to register");
             gen_op_breg();
+            gen_op_reset_T0();
+            gen_op_exit_tb();
             break;
         default:
             MIPS_DEBUG("unknown branch");
@@ -3815,8 +5713,9 @@
     }
 }
 
-int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
-                                    int search_pc)
+static inline int
+gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
+                                int search_pc)
 {
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
@@ -3838,16 +5737,18 @@
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = tb->flags;
     ctx.saved_hflags = ctx.hflags;
-    if (ctx.hflags & MIPS_HFLAG_BR) {
+    switch (ctx.hflags & MIPS_HFLAG_BMASK) {
+    case MIPS_HFLAG_BR:
         gen_op_restore_breg_target();
-    } else if (ctx.hflags & MIPS_HFLAG_B) {
+        break;
+    case MIPS_HFLAG_B:
         ctx.btarget = env->btarget;
-    } else if (ctx.hflags & MIPS_HFLAG_BMASK) {
-        /* If we are in the delay slot of a conditional branch,
-         * restore the branch condition from env->bcond to T2
-         */
+        break;
+    case MIPS_HFLAG_BC:
+    case MIPS_HFLAG_BL:
         ctx.btarget = env->btarget;
         gen_op_restore_bcond();
+        break;
     }
 #if defined(CONFIG_USER_ONLY)
     ctx.mem_idx = 0;
@@ -3891,7 +5792,7 @@
             gen_opc_instr_start[lj] = 1;
         }
         ctx.opcode = ldl_code(ctx.pc);
-        decode_opc(&ctx);
+        decode_opc(env, &ctx);
         ctx.pc += 4;
 
         if (env->singlestep_enabled)
@@ -3907,15 +5808,25 @@
     if (env->singlestep_enabled) {
         save_cpu_state(ctxp, ctx.bstate == BS_NONE);
         gen_op_debug();
-        goto done_generating;
+    } else {
+	switch (ctx.bstate) {
+        case BS_STOP:
+            gen_op_interrupt_restart();
+            /* Fall through. */
+        case BS_NONE:
+            save_cpu_state(ctxp, 0);
+            gen_goto_tb(&ctx, 0, ctx.pc);
+            break;
+        case BS_EXCP:
+            gen_op_interrupt_restart();
+            gen_op_reset_T0();
+            gen_op_exit_tb();
+            break;
+        case BS_BRANCH:
+        default:
+            break;
+	}
     }
-    else if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) {
-        save_cpu_state(ctxp, 0);
-        gen_goto_tb(&ctx, 0, ctx.pc);
-    }
-    gen_op_reset_T0();
-    /* Generate the return instruction */
-    gen_op_exit_tb();
 done_generating:
     *gen_opc_ptr = INDEX_op_end;
     if (search_pc) {
@@ -3934,7 +5845,7 @@
 #endif
     if (loglevel & CPU_LOG_TB_IN_ASM) {
         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
-    target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
+        target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
         fprintf(logfile, "\n");
     }
     if (loglevel & CPU_LOG_TB_OP) {
@@ -3960,28 +5871,38 @@
     return gen_intermediate_code_internal(env, tb, 1);
 }
 
-#ifdef MIPS_USES_FPU
-
 void fpu_dump_state(CPUState *env, FILE *f, 
                     int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
 {
     int i;
+    int is_fpu64 = !!(env->CP0_Status & (1 << CP0St_FR));
 
-#   define printfpr(fp) do { \
-        fpu_fprintf(f, "w:%08x d:%08lx%08lx fd:%g fs:%g\n", \
-                (fp)->w[FP_ENDIAN_IDX], (fp)->w[0], (fp)->w[1], (fp)->fd, (fp)->fs[FP_ENDIAN_IDX]); \
+#define printfpr(fp)                                                        \
+    do {                                                                    \
+        if (is_fpu64)                                                       \
+            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu: %13g\n",   \
+                        (fp)->w[FP_ENDIAN_IDX], (fp)->d, (fp)->fd,          \
+                        (fp)->fs[FP_ENDIAN_IDX], (fp)->fs[!FP_ENDIAN_IDX]); \
+        else {                                                              \
+            fpr_t tmp;                                                      \
+            tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX];                  \
+            tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX];           \
+            fpu_fprintf(f, "w:%08x d:%016lx fd:%13g fs:%13g psu:%13g\n",    \
+                        tmp.w[FP_ENDIAN_IDX], tmp.d, tmp.fd,                \
+                        tmp.fs[FP_ENDIAN_IDX], tmp.fs[!FP_ENDIAN_IDX]);     \
+        }                                                                   \
     } while(0)
 
-    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d\n",
-                env->fcr0, env->fcr31,
-                (env->CP0_Status & (1 << CP0St_FR)) != 0);
+
+    fpu_fprintf(f, "CP1 FCR0 0x%08x  FCR31 0x%08x  SR.FR %d  fp_status 0x%08x(0x%02x)\n",
+                env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
     fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
     fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
     fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
-    for(i = 0; i < 32; i += 2) {
-        fpu_fprintf(f, "%s: ", fregnames[i]);
-        printfpr(FPR(env, i));
+    for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
+        fpu_fprintf(f, "%3s: ", fregnames[i]);
+        printfpr(&env->fpr[i]);
     }
 
 #undef printfpr
@@ -3990,15 +5911,13 @@
 void dump_fpu (CPUState *env)
 {
     if (loglevel) { 
-       fprintf(logfile, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
+       fprintf(logfile, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
                env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
        fpu_dump_state(env, logfile, fprintf, 0);
     }
 }
 
-#endif /* MIPS_USES_FPU */
-
-#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
 /* Debug help: The architecture requires 32bit code to maintain proper
    sign-extened values on 64bit machines.  */
 
@@ -4011,23 +5930,23 @@
     int i;
 
     if (!SIGN_EXT_P(env->PC))
-        cpu_fprintf(f, "BROKEN: pc=0x" TLSZ "\n", env->PC);
+        cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
     if (!SIGN_EXT_P(env->HI))
-        cpu_fprintf(f, "BROKEN: HI=0x" TLSZ "\n", env->HI);
+        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
     if (!SIGN_EXT_P(env->LO))
-        cpu_fprintf(f, "BROKEN: LO=0x" TLSZ "\n", env->LO);
+        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
     if (!SIGN_EXT_P(env->btarget))
-        cpu_fprintf(f, "BROKEN: btarget=0x" TLSZ "\n", env->btarget);
+        cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
 
     for (i = 0; i < 32; i++) {
         if (!SIGN_EXT_P(env->gpr[i]))
-            cpu_fprintf(f, "BROKEN: %s=0x" TLSZ "\n", regnames[i], env->gpr[i]);
+            cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
     }
 
     if (!SIGN_EXT_P(env->CP0_EPC))
-        cpu_fprintf(f, "BROKEN: EPC=0x" TLSZ "\n", env->CP0_EPC);
+        cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
     if (!SIGN_EXT_P(env->CP0_LLAddr))
-        cpu_fprintf(f, "BROKEN: LLAddr=0x" TLSZ "\n", env->CP0_LLAddr);
+        cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
 }
 #endif
 
@@ -4038,33 +5957,25 @@
     uint32_t c0_status;
     int i;
     
-    cpu_fprintf(f, "pc=0x" TLSZ " HI=0x" TLSZ " LO=0x" TLSZ " ds %04x " TLSZ " %d\n",
+    cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n",
                 env->PC, env->HI, env->LO, env->hflags, env->btarget, env->bcond);
     for (i = 0; i < 32; i++) {
         if ((i & 3) == 0)
             cpu_fprintf(f, "GPR%02d:", i);
-        cpu_fprintf(f, " %s " TLSZ, regnames[i], env->gpr[i]);
+        cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i]);
         if ((i & 3) == 3)
             cpu_fprintf(f, "\n");
     }
 
     c0_status = env->CP0_Status;
-    if (env->hflags & MIPS_HFLAG_UM)
-        c0_status |= (1 << CP0St_UM);
-    if (env->hflags & MIPS_HFLAG_ERL)
-        c0_status |= (1 << CP0St_ERL);
-    if (env->hflags & MIPS_HFLAG_EXL)
-        c0_status |= (1 << CP0St_EXL);
 
-    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TLSZ "\n",
+    cpu_fprintf(f, "CP0 Status  0x%08x Cause   0x%08x EPC    0x" TARGET_FMT_lx "\n",
                 c0_status, env->CP0_Cause, env->CP0_EPC);
-    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TLSZ "\n",
+    cpu_fprintf(f, "    Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
                 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
-#ifdef MIPS_USES_FPU
     if (c0_status & (1 << CP0St_CU1))
         fpu_dump_state(env, f, cpu_fprintf, flags);
-#endif
-#if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
+#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
     cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
 #endif
 }
@@ -4097,34 +6008,25 @@
     } else {
         env->CP0_ErrorEPC = env->PC;
     }
+    env->hflags = 0;
     env->PC = (int32_t)0xBFC00000;
-#if defined (MIPS_USES_R4K_TLB)
-    env->CP0_random = MIPS_TLB_NB - 1;
-    env->tlb_in_use = MIPS_TLB_NB;
-#endif
     env->CP0_Wired = 0;
     /* SMP not implemented */
-    env->CP0_EBase = (int32_t)0x80000000;
-    env->CP0_Config0 = MIPS_CONFIG0;
-    env->CP0_Config1 = MIPS_CONFIG1;
-    env->CP0_Config2 = MIPS_CONFIG2;
-    env->CP0_Config3 = MIPS_CONFIG3;
+    env->CP0_EBase = 0x80000000;
     env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
+    /* vectored interrupts not implemented, timer on int 7,
+       no performance counters. */
+    env->CP0_IntCtl = 0xe0000000;
     env->CP0_WatchLo = 0;
-    env->hflags = MIPS_HFLAG_ERL;
+    env->CP0_WatchHi = 0;
     /* Count register increments in debug mode, EJTAG version 1 */
     env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
-    env->CP0_PRid = MIPS_CPU;
 #endif
     env->exception_index = EXCP_NONE;
 #if defined(CONFIG_USER_ONLY)
     env->hflags |= MIPS_HFLAG_UM;
     env->user_mode_only = 1;
 #endif
-#ifdef MIPS_USES_FPU
-    env->fcr0 = MIPS_FCR0;	
-#endif
-    /* XXX some guesswork here, values are CPU specific */
-    env->SYNCI_Step = 16;
-    env->CCRes = 2;
 }
+
+#include "translate_init.c"

Added: trunk/src/host/qemu-neo1973/target-mips/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,207 @@
+/*
+ *  MIPS emulation for qemu: CPU initialisation routines.
+ *
+ *  Copyright (c) 2004-2005 Jocelyn Mayer
+ *  Copyright (c) 2007 Herve Poussineau
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* CPU / CPU family specific config register values. */
+
+/* Have config1, is MIPS32R1, uses TLB, no virtual icache,
+   uncached coherency */
+#define MIPS_CONFIG0                                              \
+  ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) |      \
+   (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) |    \
+   (0x2 << CP0C0_K0))
+
+/* Have config2, 64 sets Icache, 16 bytes Icache line,
+   2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache,
+   no coprocessor2 attached, no MDMX support attached,
+   no performance counters, watch registers present,
+   no code compression, EJTAG present, no FPU */
+#define MIPS_CONFIG1                                              \
+((1 << CP0C1_M) |                                                 \
+ (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) |      \
+ (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) |      \
+ (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |            \
+ (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) |            \
+ (0 << CP0C1_FP))
+
+/* Have config3, no tertiary/secondary caches implemented */
+#define MIPS_CONFIG2                                              \
+((1 << CP0C2_M))
+
+/* No config4, no DSP ASE, no large physaddr,
+   no external interrupt controller, no vectored interupts,
+   no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */
+#define MIPS_CONFIG3                                              \
+((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |          \
+ (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |        \
+ (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL))
+
+/* Define a implementation number of 1.
+   Define a major version 1, minor version 0. */
+#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
+
+
+struct mips_def_t {
+    const unsigned char *name;
+    int32_t CP0_PRid;
+    int32_t CP0_Config0;
+    int32_t CP0_Config1;
+    int32_t CP0_Config2;
+    int32_t CP0_Config3;
+    int32_t CP0_Config6;
+    int32_t CP0_Config7;
+    int32_t SYNCI_Step;
+    int32_t CCRes;
+    int32_t Status_rw_bitmask;
+    int32_t CP1_fcr0;
+};
+
+/*****************************************************************************/
+/* MIPS CPU definitions */
+static mips_def_t mips_defs[] =
+{
+#ifndef TARGET_MIPS64
+    {
+        .name = "4Kc",
+        .CP0_PRid = 0x00018000,
+        .CP0_Config0 = MIPS_CONFIG0,
+        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .Status_rw_bitmask = 0x3278FF17,
+    },
+    {
+        .name = "4KEcR1",
+        .CP0_PRid = 0x00018400,
+        .CP0_Config0 = MIPS_CONFIG0,
+        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+    },
+    {
+        .name = "4KEc",
+        .CP0_PRid = 0x00019000,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .Status_rw_bitmask = 0x3278FF17,
+    },
+    {
+        .name = "24Kc",
+        .CP0_PRid = 0x00019300,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .Status_rw_bitmask = 0x3278FF17,
+    },
+    {
+        .name = "24Kf",
+        .CP0_PRid = 0x00019300,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 32,
+        .CCRes = 2,
+        .Status_rw_bitmask = 0x3678FF17,
+        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
+                    (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+    },
+#else
+    {
+        .name = "R4000",
+        .CP0_PRid = 0x00000400,
+        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3,
+        .SYNCI_Step = 16,
+        .CCRes = 2,
+        .Status_rw_bitmask = 0x3678FFFF,
+        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
+                    (1 << FCR0_D) | (1 << FCR0_S) |
+                    (0x4 << FCR0_PRID) | (0x0 << FCR0_REV),
+    },
+#endif
+};
+
+int mips_find_by_name (const unsigned char *name, mips_def_t **def)
+{
+    int i, ret;
+
+    ret = -1;
+    *def = NULL;
+    for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) {
+        if (strcasecmp(name, mips_defs[i].name) == 0) {
+            *def = &mips_defs[i];
+            ret = 0;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+    int i;
+
+    for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) {
+        (*cpu_fprintf)(f, "MIPS '%s'\n",
+                       mips_defs[i].name);
+    }
+}
+
+int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
+{
+    if (!def)
+        cpu_abort(env, "Unable to find MIPS CPU definition\n");
+    env->CP0_PRid = def->CP0_PRid;
+#ifdef TARGET_WORDS_BIGENDIAN
+    env->CP0_Config0 = def->CP0_Config0 | (1 << CP0C0_BE);
+#else
+    env->CP0_Config0 = def->CP0_Config0;
+#endif
+    env->CP0_Config1 = def->CP0_Config1;
+    env->CP0_Config2 = def->CP0_Config2;
+    env->CP0_Config3 = def->CP0_Config3;
+    env->CP0_Config6 = def->CP0_Config6;
+    env->CP0_Config7 = def->CP0_Config7;
+    env->SYNCI_Step = def->SYNCI_Step;
+    env->CCRes = def->CCRes;
+    env->Status_rw_bitmask = def->Status_rw_bitmask;
+    env->fcr0 = def->CP1_fcr0;
+#if defined (MIPS_USES_R4K_TLB)
+    env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
+    env->CP0_Random = env->nb_tlb - 1;
+    env->tlb_in_use = env->nb_tlb;
+#endif
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/target-ppc/STATUS
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/STATUS	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/STATUS	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,105 @@
+PowerPC emulation status.
+The goal of this file is to provide a reference status to avoid regressions.
+
+===============================================================================
+PowerPC core emulation status
+
+PowerPC CPU known to work (ie booting at least Linux 2.4):
+* main stream PowerPC cores
+- PowerPC 603 & derivatives
+- PowerPC 604 & derivatives
+- PowerPC 740 & derivatives
+- PowerPC 750 & derivatives
+- PowerPC 405
+
+PowerPC that should work but are not supported by standard Linux kernel
+(then remain mostly untested)
+- PowerPC 745
+- PowerPC 755
+
+Work in progress:
+* embedded PowerPC cores
+- BookE PowerPC
+- e500 core (Freescale PowerQUICC)
+* main stream PowerPC cores
+- PowerPC 601
+- PowerPC 602
+
+TODO:
+* embedded PowerPC cores
+- PowerPC 401
+- PowerPC 403
+- PowerPC 440
+- PowerPC 460
+* main stream PowerPC cores
+- PowerPC 7400 (aka G4)
+- PowerPC 7410
+- PowerPC 7450
+- PowerPC 7455
+- PowerPC 7457
+- PowerPC 7457A
+* original POWER
+- POWER
+- POWER2
+* 64 bits PowerPC cores
+- PowerPC 620
+- PowerPC 630 (aka POWER3)
+- PowerPC 631 (aka POWER3+)
+- POWER4
+- POWER4+
+- POWER5
+- POWER5+
+- PowerPC 970
+* RS64 series
+- RS64
+- RS64-II
+- RS64-III
+- RS64-IV
+
+===============================================================================
+PowerPC microcontrollers emulation status
+
+Implemementation should be sufficient to boot Linux:
+- PowerPC 405CR
+- PowerPC 405EP
+
+TODO:
+- More PowerPC 40x microcontrollers emulation
+- PowerQUICC microcontrollers emulation
+
+===============================================================================
+PowerPC based platforms emulation status
+
+* PREP platform (RS/6000 7043...) - TO BE CHECKED (broken)
+- Gentoo Linux live CDROM 1.4
+- Debian Linux 3.0
+- Mandrake Linux 9
+
+* heathrow PowerMac platform (beige PowerMac) - TO BE CHECKED (broken)
+- Gentoo Linux live CDROM 1.4
+- Debian Linux 3.0
+- Mandrake Linux 9
+
+* mac99 platform (white and blue PowerMac, ...)
+- Gentoo Linux live CDROM 1.4 - boots, compiles linux kernel
+- Debian Linux woody - boots from CDROM and HDD
+- Mandrake Linux 9 - boots from CDROM, freezes during install
+- Knoppix 2003-07-13_4 boots from CDROM, pb with X configuration
+  distribution bug: X runs with a properly hand-coded configuration.
+- rock Linux 2.0 runs from CDROM
+
+* Linux 2.6 support seems deadly broken (used to boot...).
+
+* PowerPC 405EP reference boards:
+- can boot Linux 2.4 & 2.6.
+  Need to provide a flash image ready to boot for reproductible tests.
+
+TODO:
+- MCA based RS/6000 emulation
+- CHRP emulation (not PowerMac)
+- PPAR emulation
+- ePPAR emulation
+- misc PowerPC reference boards emulation
+
+===============================================================================
+(to be completed)

Modified: trunk/src/host/qemu-neo1973/target-ppc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation cpu definitions for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -21,18 +21,57 @@
 #define __CPU_PPC_H__
 
 #include "config.h"
+#include <inttypes.h>
 
+#if !defined(TARGET_PPCEMB)
+#if defined(TARGET_PPC64) || (HOST_LONG_BITS >= 64)
+/* When using 64 bits temporary registers,
+ * we can use 64 bits GPR with no extra cost
+ */
+#define TARGET_PPCEMB
+#endif
+#endif
+
+#if defined (TARGET_PPC64)
+typedef uint64_t ppc_gpr_t;
+#define TARGET_LONG_BITS 64
+#define TARGET_GPR_BITS  64
+#define REGX "%016" PRIx64
+#define TARGET_PAGE_BITS 12
+#elif defined(TARGET_PPCEMB)
+/* e500v2 have 36 bits physical address space */
+#define TARGET_PHYS_ADDR_BITS 64
+/* GPR are 64 bits: used by vector extension */
+typedef uint64_t ppc_gpr_t;
 #define TARGET_LONG_BITS 32
+#define TARGET_GPR_BITS  64
+#define REGX "%016" PRIx64
+/* Pages can be 1 kB small */
+#define TARGET_PAGE_BITS 10
+#else
+typedef uint32_t ppc_gpr_t;
+#define TARGET_LONG_BITS 32
+#define TARGET_GPR_BITS  32
+#define REGX "%08" PRIx32
+#define TARGET_PAGE_BITS 12
+#endif
 
 #include "cpu-defs.h"
 
+#define ADDRX TARGET_FMT_lx
+#define PADDRX TARGET_FMT_plx
+
 #include <setjmp.h>
 
 #include "softfloat.h"
 
 #define TARGET_HAS_ICE 1
 
-#define ELF_MACHINE	EM_PPC
+#if defined (TARGET_PPC64)
+#define ELF_MACHINE     EM_PPC64
+#else
+#define ELF_MACHINE     EM_PPC
+#endif
 
 /* XXX: this should be tunable: PowerPC 601 & 64 bits PowerPC
  *                              have different cache line sizes
@@ -42,6 +81,7 @@
 
 /* XXX: put this in a common place */
 #define likely(x)   __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
 
 /*****************************************************************************/
 /* PVR definitions for most known PowerPC */
@@ -54,72 +94,155 @@
     CPU_PPC_401E2     = 0x00250000,
     CPU_PPC_401F2     = 0x00260000,
     CPU_PPC_401G2     = 0x00270000,
-    CPU_PPC_IOP480    = 0x40100000,
+#define CPU_PPC_401 CPU_PPC_401G2
+    CPU_PPC_IOP480    = 0x40100000, /* 401B2 ? */
+    CPU_PPC_COBRA     = 0x10100000, /* IBM Processor for Network Resources */
     /* PowerPC 403 cores */
-    CPU_PPC_403GA     = 0x00200000,
+    CPU_PPC_403GA     = 0x00200011,
     CPU_PPC_403GB     = 0x00200100,
     CPU_PPC_403GC     = 0x00200200,
     CPU_PPC_403GCX    = 0x00201400,
+#define CPU_PPC_403 CPU_PPC_403GCX
     /* PowerPC 405 cores */
-    CPU_PPC_405       = 0x40110000,
-    CPU_PPC_405EP     = 0x51210000,
-    CPU_PPC_405GPR    = 0x50910000,
+    CPU_PPC_405CR     = 0x40110145,
+#define CPU_PPC_405GP CPU_PPC_405CR
+    CPU_PPC_405EP     = 0x51210950,
+    CPU_PPC_405GPR    = 0x50910951,
     CPU_PPC_405D2     = 0x20010000,
     CPU_PPC_405D4     = 0x41810000,
-    CPU_PPC_NPE405H   = 0x41410000,
-    CPU_PPC_NPE405L   = 0x41610000,
+#define CPU_PPC_405 CPU_PPC_405D4
+    CPU_PPC_NPE405H   = 0x414100C0,
+    CPU_PPC_NPE405H2  = 0x41410140,
+    CPU_PPC_NPE405L   = 0x416100C0,
+    /* XXX: missing 405LP, LC77700 */
+    /* IBM STBxxx (PowerPC 401/403/405 core based microcontrollers) */
 #if 0
-    CPU_PPC_STB02     = xxx,
+    CPU_PPC_STB01000  = xxx,
 #endif
+#if 0
+    CPU_PPC_STB01010  = xxx,
+#endif
+#if 0
+    CPU_PPC_STB0210   = xxx,
+#endif
     CPU_PPC_STB03     = 0x40310000,
 #if 0
-    CPU_PPC_STB04     = xxx,
+    CPU_PPC_STB043    = xxx,
 #endif
-    CPU_PPC_STB25     = 0x51510000,
 #if 0
+    CPU_PPC_STB045    = xxx,
+#endif
+    CPU_PPC_STB25     = 0x51510950,
+#if 0
     CPU_PPC_STB130    = xxx,
 #endif
+    /* Xilinx cores */
+    CPU_PPC_X2VP4     = 0x20010820,
+#define CPU_PPC_X2VP7 CPU_PPC_X2VP4
+    CPU_PPC_X2VP20    = 0x20010860,
+#define CPU_PPC_X2VP50 CPU_PPC_X2VP20
     /* PowerPC 440 cores */
-    CPU_PPC_440EP     = 0x42220000,
-    CPU_PPC_440GP     = 0x40120400,
-    CPU_PPC_440GX     = 0x51B20000,
-    /* PowerPC MPC 8xx cores */
-    CPU_PPC_8540      = 0x80200000,
+    CPU_PPC_440EP     = 0x422218D3,
+#define CPU_PPC_440GR CPU_PPC_440EP
+    CPU_PPC_440GP     = 0x40120481,
+    CPU_PPC_440GX     = 0x51B21850,
+    CPU_PPC_440GXc    = 0x51B21892,
+    CPU_PPC_440GXf    = 0x51B21894,
+    CPU_PPC_440SP     = 0x53221850,
+    CPU_PPC_440SP2    = 0x53221891,
+    CPU_PPC_440SPE    = 0x53421890,
+    /* XXX: missing 440GRX */
+    /* PowerPC 460 cores - TODO */
+    /* PowerPC MPC 5xx cores */
+    CPU_PPC_5xx       = 0x00020020,
+    /* PowerPC MPC 8xx cores (aka PowerQUICC) */
     CPU_PPC_8xx       = 0x00500000,
-    CPU_PPC_8240      = 0x00810100,
-    CPU_PPC_8245      = 0x00811014,
+    /* PowerPC MPC 8xxx cores (aka PowerQUICC-II) */
+    CPU_PPC_82xx_HIP3 = 0x00810101,
+    CPU_PPC_82xx_HIP4 = 0x80811014,
+    CPU_PPC_827x      = 0x80822013,
+    /* eCores */
+    CPU_PPC_e200      = 0x81120000,
+    CPU_PPC_e500v110  = 0x80200010,
+    CPU_PPC_e500v120  = 0x80200020,
+    CPU_PPC_e500v210  = 0x80210010,
+    CPU_PPC_e500v220  = 0x80210020,
+#define CPU_PPC_e500 CPU_PPC_e500v220
+    CPU_PPC_e600      = 0x80040010,
     /* PowerPC 6xx cores */
-    CPU_PPC_601       = 0x00010000,
-    CPU_PPC_602       = 0x00050000,
-    CPU_PPC_603       = 0x00030000,
-    CPU_PPC_603E      = 0x00060000,
-    CPU_PPC_603EV     = 0x00070000,
-    CPU_PPC_603R      = 0x00071000,
-    CPU_PPC_G2        = 0x80810000,
-    CPU_PPC_G2LE      = 0x80820000,
+    CPU_PPC_601       = 0x00010001,
+    CPU_PPC_602       = 0x00050100,
+    CPU_PPC_603       = 0x00030100,
+    CPU_PPC_603E      = 0x00060101,
+    CPU_PPC_603P      = 0x00070000,
+    CPU_PPC_603E7v    = 0x00070100,
+    CPU_PPC_603E7v2   = 0x00070201,
+    CPU_PPC_603E7     = 0x00070200,
+    CPU_PPC_603R      = 0x00071201,
+    CPU_PPC_G2        = 0x00810011,
+    CPU_PPC_G2H4      = 0x80811010,
+    CPU_PPC_G2gp      = 0x80821010,
+    CPU_PPC_G2ls      = 0x90810010,
+    CPU_PPC_G2LE      = 0x80820010,
+    CPU_PPC_G2LEgp    = 0x80822010,
+    CPU_PPC_G2LEls    = 0xA0822010,
     CPU_PPC_604       = 0x00040000,
-    CPU_PPC_604E      = 0x00090000,
-    CPU_PPC_604R      = 0x000a0000,
+    CPU_PPC_604E      = 0x00090100, /* Also 2110 & 2120 */
+    CPU_PPC_604R      = 0x000a0101,
     /* PowerPC 74x/75x cores (aka G3) */
     CPU_PPC_74x       = 0x00080000,
-    CPU_PPC_755       = 0x00083000,
+    CPU_PPC_740E      = 0x00080100,
+    CPU_PPC_750E      = 0x00080200,
+    CPU_PPC_755_10    = 0x00083100,
+    CPU_PPC_755_11    = 0x00083101,
+    CPU_PPC_755_20    = 0x00083200,
+    CPU_PPC_755D      = 0x00083202,
+    CPU_PPC_755E      = 0x00083203,
+#define CPU_PPC_755 CPU_PPC_755E
     CPU_PPC_74xP      = 0x10080000,
-    CPU_PPC_750CXE22  = 0x00082202,
+    CPU_PPC_750CXE21  = 0x00082201,
+    CPU_PPC_750CXE22  = 0x00082212,
+    CPU_PPC_750CXE23  = 0x00082203,
     CPU_PPC_750CXE24  = 0x00082214,
     CPU_PPC_750CXE24b = 0x00083214,
     CPU_PPC_750CXE31  = 0x00083211,
     CPU_PPC_750CXE31b = 0x00083311,
 #define CPU_PPC_750CXE CPU_PPC_750CXE31b
-    CPU_PPC_750FX     = 0x70000000,
-    CPU_PPC_750GX     = 0x70020000,
+    CPU_PPC_750CXR    = 0x00083410,
+    CPU_PPC_750FX10   = 0x70000100,
+    CPU_PPC_750FX20   = 0x70000200,
+    CPU_PPC_750FX21   = 0x70000201,
+    CPU_PPC_750FX22   = 0x70000202,
+    CPU_PPC_750FX23   = 0x70000203,
+#define CPU_PPC_750FX CPU_PPC_750FX23
+    CPU_PPC_750FL     = 0x700A0203,
+    CPU_PPC_750GX10   = 0x70020100,
+    CPU_PPC_750GX11   = 0x70020101,
+    CPU_PPC_750GX12   = 0x70020102,
+#define CPU_PPC_750GX CPU_PPC_750GX12
+    CPU_PPC_750GL     = 0x70020102,
+    CPU_PPC_750L30    = 0x00088300,
+    CPU_PPC_750L32    = 0x00088302,
+    CPU_PPC_750CL     = 0x00087200,
     /* PowerPC 74xx cores (aka G4) */
-    CPU_PPC_7400      = 0x000C0000,
-    CPU_PPC_7410      = 0x800C0000,
-    CPU_PPC_7441      = 0x80000200,
-    CPU_PPC_7450      = 0x80000000,
+    CPU_PPC_7400      = 0x000C0100,
+    CPU_PPC_7410C     = 0x800C1102,
+    CPU_PPC_7410D     = 0x800C1103,
+    CPU_PPC_7410E     = 0x800C1104,
+    CPU_PPC_7441      = 0x80000210,
+    CPU_PPC_7445      = 0x80010100,
+    CPU_PPC_7447      = 0x80020100,
+    CPU_PPC_7447A     = 0x80030101,
+    CPU_PPC_7448      = 0x80040100,
+    CPU_PPC_7450      = 0x80000200,
+    CPU_PPC_7450b     = 0x80000201,
     CPU_PPC_7451      = 0x80000203,
-    CPU_PPC_7455      = 0x80010000,
-    CPU_PPC_7457      = 0x80020000,
+    CPU_PPC_7451G     = 0x80000210,
+    CPU_PPC_7455      = 0x80010201,
+    CPU_PPC_7455F     = 0x80010303,
+    CPU_PPC_7455G     = 0x80010304,
+    CPU_PPC_7457      = 0x80020101,
+    CPU_PPC_7457C     = 0x80020102,
     CPU_PPC_7457A     = 0x80030000,
     /* 64 bits PowerPC */
     CPU_PPC_620       = 0x00140000,
@@ -130,7 +253,21 @@
     CPU_PPC_POWER5    = 0x003A0000,
     CPU_PPC_POWER5P   = 0x003B0000,
     CPU_PPC_970       = 0x00390000,
-    CPU_PPC_970FX     = 0x003C0000,
+    CPU_PPC_970FX10   = 0x00391100,
+    CPU_PPC_970FX20   = 0x003C0200,
+    CPU_PPC_970FX21   = 0x003C0201,
+    CPU_PPC_970FX30   = 0x003C0300,
+    CPU_PPC_970FX31   = 0x003C0301,
+#define CPU_PPC_970FX CPU_PPC_970FX31
+    CPU_PPC_970MP10   = 0x00440100,
+    CPU_PPC_970MP11   = 0x00440101,
+#define CPU_PPC_970MP CPU_PPC_970MP11
+    CPU_PPC_CELL10    = 0x00700100,
+    CPU_PPC_CELL20    = 0x00700400,
+    CPU_PPC_CELL30    = 0x00700500,
+    CPU_PPC_CELL31    = 0x00700501,
+#define CPU_PPC_CELL32 CPU_PPC_CELL31
+#define CPU_PPC_CELL CPU_PPC_CELL32
     CPU_PPC_RS64      = 0x00330000,
     CPU_PPC_RS64II    = 0x00340000,
     CPU_PPC_RS64III   = 0x00360000,
@@ -147,12 +284,28 @@
 #endif
 };
 
-/* System version register (used on MPC 8xx) */
+/* System version register (used on MPC 8xxx) */
 enum {
     PPC_SVR_8540      = 0x80300000,
-    PPC_SVR_8541E     = 0x807A0000,
-    PPC_SVR_8555E     = 0x80790000,
-    PPC_SVR_8560      = 0x80700000,
+    PPC_SVR_8541E     = 0x807A0010,
+    PPC_SVR_8543v10   = 0x80320010,
+    PPC_SVR_8543v11   = 0x80320011,
+    PPC_SVR_8543v20   = 0x80320020,
+    PPC_SVR_8543Ev10  = 0x803A0010,
+    PPC_SVR_8543Ev11  = 0x803A0011,
+    PPC_SVR_8543Ev20  = 0x803A0020,
+    PPC_SVR_8545      = 0x80310220,
+    PPC_SVR_8545E     = 0x80390220,
+    PPC_SVR_8547E     = 0x80390120,
+    PPC_SCR_8548v10   = 0x80310010,
+    PPC_SCR_8548v11   = 0x80310011,
+    PPC_SCR_8548v20   = 0x80310020,
+    PPC_SVR_8548Ev10  = 0x80390010,
+    PPC_SVR_8548Ev11  = 0x80390011,
+    PPC_SVR_8548Ev20  = 0x80390020,
+    PPC_SVR_8555E     = 0x80790010,
+    PPC_SVR_8560v10   = 0x80700010,
+    PPC_SVR_8560v20   = 0x80700020,
 };
 
 /*****************************************************************************/
@@ -165,7 +318,7 @@
     /* ld/st with reservation instructions         */
     /* cache control instructions                  */
     /* spr/msr access instructions                 */
-    PPC_INSNS_BASE  = 0x00000001,
+    PPC_INSNS_BASE  = 0x0000000000000001ULL,
 #define PPC_INTEGER PPC_INSNS_BASE
 #define PPC_FLOW    PPC_INSNS_BASE
 #define PPC_MEM     PPC_INSNS_BASE
@@ -173,102 +326,133 @@
 #define PPC_CACHE   PPC_INSNS_BASE
 #define PPC_MISC    PPC_INSNS_BASE
     /* floating point operations instructions      */
-    PPC_FLOAT       = 0x00000002,
+    PPC_FLOAT       = 0x0000000000000002ULL,
     /* more floating point operations instructions */
-    PPC_FLOAT_EXT   = 0x00000004,
+    PPC_FLOAT_EXT   = 0x0000000000000004ULL,
     /* external control instructions               */
-    PPC_EXTERN      = 0x00000008,
+    PPC_EXTERN      = 0x0000000000000008ULL,
     /* segment register access instructions        */
-    PPC_SEGMENT     = 0x00000010,
+    PPC_SEGMENT     = 0x0000000000000010ULL,
     /* Optional cache control instructions         */
-    PPC_CACHE_OPT   = 0x00000020,
+    PPC_CACHE_OPT   = 0x0000000000000020ULL,
     /* Optional floating point op instructions     */
-    PPC_FLOAT_OPT   = 0x00000040,
+    PPC_FLOAT_OPT   = 0x0000000000000040ULL,
     /* Optional memory control instructions        */
-    PPC_MEM_TLBIA   = 0x00000080,
-    PPC_MEM_TLBIE   = 0x00000100,
-    PPC_MEM_TLBSYNC = 0x00000200,
+    PPC_MEM_TLBIA   = 0x0000000000000080ULL,
+    PPC_MEM_TLBIE   = 0x0000000000000100ULL,
+    PPC_MEM_TLBSYNC = 0x0000000000000200ULL,
     /* eieio & sync                                */
-    PPC_MEM_SYNC    = 0x00000400,
+    PPC_MEM_SYNC    = 0x0000000000000400ULL,
     /* PowerPC 6xx TLB management instructions     */
-    PPC_6xx_TLB     = 0x00000800,
+    PPC_6xx_TLB     = 0x0000000000000800ULL,
     /* Altivec support                             */
-    PPC_ALTIVEC     = 0x00001000,
+    PPC_ALTIVEC     = 0x0000000000001000ULL,
     /* Time base support                           */
-    PPC_TB          = 0x00002000,
+    PPC_TB          = 0x0000000000002000ULL,
     /* Embedded PowerPC dedicated instructions     */
-    PPC_4xx_COMMON  = 0x00004000,
+    PPC_EMB_COMMON  = 0x0000000000004000ULL,
     /* PowerPC 40x exception model                 */
-    PPC_40x_EXCP    = 0x00008000,
+    PPC_40x_EXCP    = 0x0000000000008000ULL,
     /* PowerPC 40x specific instructions           */
-    PPC_40x_SPEC    = 0x00010000,
+    PPC_40x_SPEC    = 0x0000000000010000ULL,
     /* PowerPC 405 Mac instructions                */
-    PPC_405_MAC     = 0x00020000,
+    PPC_405_MAC     = 0x0000000000020000ULL,
     /* PowerPC 440 specific instructions           */
-    PPC_440_SPEC    = 0x00040000,
+    PPC_440_SPEC    = 0x0000000000040000ULL,
     /* Specific extensions */
     /* Power-to-PowerPC bridge (601)               */
-    PPC_POWER_BR    = 0x00080000,
+    PPC_POWER_BR    = 0x0000000000080000ULL,
     /* PowerPC 602 specific */
-    PPC_602_SPEC    = 0x00100000,
+    PPC_602_SPEC    = 0x0000000000100000ULL,
     /* Deprecated instructions                     */
     /* Original POWER instruction set              */
-    PPC_POWER       = 0x00200000,
+    PPC_POWER       = 0x0000000000200000ULL,
     /* POWER2 instruction set extension            */
-    PPC_POWER2      = 0x00400000,
+    PPC_POWER2      = 0x0000000000400000ULL,
     /* Power RTC support */
-    PPC_POWER_RTC   = 0x00800000,
+    PPC_POWER_RTC   = 0x0000000000800000ULL,
     /* 64 bits PowerPC instructions                */
     /* 64 bits PowerPC instruction set             */
-    PPC_64B         = 0x01000000,
+    PPC_64B         = 0x0000000001000000ULL,
     /* 64 bits hypervisor extensions               */
-    PPC_64H         = 0x02000000,
+    PPC_64H         = 0x0000000002000000ULL,
     /* 64 bits PowerPC "bridge" features           */
-    PPC_64_BRIDGE   = 0x04000000,
+    PPC_64_BRIDGE   = 0x0000000004000000ULL,
+    /* BookE (embedded) PowerPC specification      */
+    PPC_BOOKE       = 0x0000000008000000ULL,
+    /* eieio */
+    PPC_MEM_EIEIO   = 0x0000000010000000ULL,
+    /* e500 vector instructions */
+    PPC_E500_VECTOR = 0x0000000020000000ULL,
+    /* PowerPC 4xx dedicated instructions     */
+    PPC_4xx_COMMON  = 0x0000000040000000ULL,
+    /* PowerPC 2.03 specification extensions */
+    PPC_203         = 0x0000000080000000ULL,
+    /* PowerPC 2.03 SPE extension */
+    PPC_SPE         = 0x0000000100000000ULL,
+    /* PowerPC 2.03 SPE floating-point extension */
+    PPC_SPEFPU      = 0x0000000200000000ULL,
+    /* SLB management */
+    PPC_SLBI        = 0x0000000400000000ULL,
 };
 
 /* CPU run-time flags (MMU and exception model) */
 enum {
     /* MMU model */
-#define PPC_FLAGS_MMU_MASK (0x0000000F)
+    PPC_FLAGS_MMU_MASK       = 0x000000FF,
     /* Standard 32 bits PowerPC MMU */
-    PPC_FLAGS_MMU_32B      = 0x00000000,
+    PPC_FLAGS_MMU_32B        = 0x00000000,
     /* Standard 64 bits PowerPC MMU */
-    PPC_FLAGS_MMU_64B      = 0x00000001,
+    PPC_FLAGS_MMU_64B        = 0x00000001,
     /* PowerPC 601 MMU */
-    PPC_FLAGS_MMU_601      = 0x00000002,
+    PPC_FLAGS_MMU_601        = 0x00000002,
     /* PowerPC 6xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_6xx = 0x00000003,
+    PPC_FLAGS_MMU_SOFT_6xx   = 0x00000003,
     /* PowerPC 4xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_4xx = 0x00000004,
+    PPC_FLAGS_MMU_SOFT_4xx   = 0x00000004,
     /* PowerPC 403 MMU */
-    PPC_FLAGS_MMU_403      = 0x00000005,
+    PPC_FLAGS_MMU_403        = 0x00000005,
+    /* BookE FSL MMU model */
+    PPC_FLAGS_MMU_BOOKE_FSL  = 0x00000006,
+    /* BookE MMU model */
+    PPC_FLAGS_MMU_BOOKE      = 0x00000007,
+    /* 64 bits "bridge" PowerPC MMU */
+    PPC_FLAGS_MMU_64BRIDGE   = 0x00000008,
     /* Exception model */
-#define PPC_FLAGS_EXCP_MASK (0x000000F0)
+    PPC_FLAGS_EXCP_MASK      = 0x0000FF00,
     /* Standard PowerPC exception model */
-    PPC_FLAGS_EXCP_STD     = 0x00000000,
+    PPC_FLAGS_EXCP_STD       = 0x00000000,
     /* PowerPC 40x exception model */
-    PPC_FLAGS_EXCP_40x     = 0x00000010,
+    PPC_FLAGS_EXCP_40x       = 0x00000100,
     /* PowerPC 601 exception model */
-    PPC_FLAGS_EXCP_601     = 0x00000020,
+    PPC_FLAGS_EXCP_601       = 0x00000200,
     /* PowerPC 602 exception model */
-    PPC_FLAGS_EXCP_602     = 0x00000030,
+    PPC_FLAGS_EXCP_602       = 0x00000300,
     /* PowerPC 603 exception model */
-    PPC_FLAGS_EXCP_603     = 0x00000040,
+    PPC_FLAGS_EXCP_603       = 0x00000400,
     /* PowerPC 604 exception model */
-    PPC_FLAGS_EXCP_604     = 0x00000050,
+    PPC_FLAGS_EXCP_604       = 0x00000500,
     /* PowerPC 7x0 exception model */
-    PPC_FLAGS_EXCP_7x0     = 0x00000060,
+    PPC_FLAGS_EXCP_7x0       = 0x00000600,
     /* PowerPC 7x5 exception model */
-    PPC_FLAGS_EXCP_7x5     = 0x00000070,
+    PPC_FLAGS_EXCP_7x5       = 0x00000700,
     /* PowerPC 74xx exception model */
-    PPC_FLAGS_EXCP_74xx    = 0x00000080,
+    PPC_FLAGS_EXCP_74xx      = 0x00000800,
     /* PowerPC 970 exception model */
-    PPC_FLAGS_EXCP_970     = 0x00000090,
+    PPC_FLAGS_EXCP_970       = 0x00000900,
+    /* BookE exception model */
+    PPC_FLAGS_EXCP_BOOKE     = 0x00000A00,
+    /* Input pins model */
+    PPC_FLAGS_INPUT_MASK     = 0x000F0000,
+    PPC_FLAGS_INPUT_6xx      = 0x00000000,
+    PPC_FLAGS_INPUT_BookE    = 0x00010000,
+    PPC_FLAGS_INPUT_40x      = 0x00020000,
+    PPC_FLAGS_INPUT_970      = 0x00030000,
 };
 
 #define PPC_MMU(env) (env->flags & PPC_FLAGS_MMU_MASK)
 #define PPC_EXCP(env) (env->flags & PPC_FLAGS_EXCP_MASK)
+#define PPC_INPUT(env) (env->flags & PPC_FLAGS_INPUT_MASK)
 
 /*****************************************************************************/
 /* Supported instruction set definitions */
@@ -277,65 +461,92 @@
 #define PPC_FLAGS_TODO (0x00000000)
 
 /* PowerPC 40x instruction set */
-#define PPC_INSNS_4xx (PPC_INSNS_BASE | PPC_MEM_TLBSYNC | PPC_4xx_COMMON)
+#define PPC_INSNS_EMB (PPC_INSNS_BASE | PPC_MEM_TLBSYNC | PPC_EMB_COMMON)
 /* PowerPC 401 */
 #define PPC_INSNS_401 (PPC_INSNS_TODO)
 #define PPC_FLAGS_401 (PPC_FLAGS_TODO)
 /* PowerPC 403 */
-#define PPC_INSNS_403 (PPC_INSNS_4xx | PPC_MEM_SYNC | PPC_MEM_TLBIA |         \
-                       PPC_40x_EXCP | PPC_40x_SPEC)
-#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x)
+#define PPC_INSNS_403 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO |         \
+                       PPC_MEM_TLBIA | PPC_4xx_COMMON | PPC_40x_EXCP |        \
+                       PPC_40x_SPEC)
+#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x |               \
+                       PPC_FLAGS_INPUT_40x)
 /* PowerPC 405 */
-#define PPC_INSNS_405 (PPC_INSNS_4xx | PPC_MEM_SYNC | PPC_CACHE_OPT |         \
-                       PPC_MEM_TLBIA | PPC_TB | PPC_40x_SPEC | PPC_40x_EXCP | \
+#define PPC_INSNS_405 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO |         \
+                       PPC_CACHE_OPT | PPC_MEM_TLBIA | PPC_TB |               \
+                       PPC_4xx_COMMON | PPC_40x_SPEC |  PPC_40x_EXCP |        \
                        PPC_405_MAC)
-#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x)
+#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x |          \
+                       PPC_FLAGS_INPUT_40x)
 /* PowerPC 440 */
-#define PPC_INSNS_440 (PPC_INSNS_4xx | PPC_CACHE_OPT | PPC_405_MAC |          \
-                       PPC_440_SPEC)
-#define PPC_FLAGS_440 (PPC_FLAGS_TODO)
+#define PPC_INSNS_440 (PPC_INSNS_EMB | PPC_CACHE_OPT | PPC_BOOKE |            \
+                       PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC)
+#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE |           \
+                       PPC_FLAGS_INPUT_BookE)
+/* Generic BookE PowerPC */
+#define PPC_INSNS_BOOKE (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO |          \
+                         PPC_FLOAT | PPC_FLOAT_OPT | PPC_CACHE_OPT)
+#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE |         \
+                         PPC_FLAGS_INPUT_BookE)
+/* e500 core */
+#define PPC_INSNS_E500 (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO |           \
+                        PPC_CACHE_OPT | PPC_E500_VECTOR)
+#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x |         \
+                        PPC_FLAGS_INPUT_BookE)
 /* Non-embedded PowerPC */
 #define PPC_INSNS_COMMON  (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC |        \
-                           PPC_SEGMENT | PPC_MEM_TLBIE)
+                           PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE)
 /* PowerPC 601 */
 #define PPC_INSNS_601 (PPC_INSNS_COMMON | PPC_EXTERN | PPC_POWER_BR)
-#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601)
+#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 602 */
 #define PPC_INSNS_602 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |       \
-                       PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602)
+                       PPC_MEM_TLBSYNC | PPC_TB | PPC_602_SPEC)
+#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 603 */
 #define PPC_INSNS_603 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |       \
                        PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
-#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603)
+#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC G2 */
 #define PPC_INSNS_G2 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |        \
                       PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
-#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603)
+#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 |           \
+                      PPC_FLAGS_INPUT_6xx)
 /* PowerPC 604 */
 #define PPC_INSNS_604 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604)
+#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 740/750 (aka G3) */
 #define PPC_INSNS_7x0 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0)
+#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 745/755 */
 #define PPC_INSNS_7x5 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB | PPC_6xx_TLB)
-#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5)
+#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 74xx (aka G4) */
 #define PPC_INSNS_74xx (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_ALTIVEC |      \
                         PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx)
+#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx |             \
+                        PPC_FLAGS_INPUT_6xx)
+/* PowerPC 970 (aka G5) */
+#define PPC_INSNS_970  (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_FLOAT_OPT |    \
+                        PPC_ALTIVEC | PPC_MEM_TLBSYNC | PPC_TB |              \
+                        PPC_64B | PPC_64_BRIDGE | PPC_SLBI)
+#define PPC_FLAGS_970  (PPC_FLAGS_MMU_64BRIDGE | PPC_FLAGS_EXCP_970 |         \
+                        PPC_FLAGS_INPUT_970)
 
 /* Default PowerPC will be 604/970 */
 #define PPC_INSNS_PPC32 PPC_INSNS_604
 #define PPC_FLAGS_PPC32 PPC_FLAGS_604
-#if 0
 #define PPC_INSNS_PPC64 PPC_INSNS_970
 #define PPC_FLAGS_PPC64 PPC_FLAGS_970
-#endif
 #define PPC_INSNS_DEFAULT PPC_INSNS_604
 #define PPC_FLAGS_DEFAULT PPC_FLAGS_604
 typedef struct ppc_def_t ppc_def_t;
@@ -348,13 +559,16 @@
 typedef struct ppc_spr_t ppc_spr_t;
 typedef struct ppc_dcr_t ppc_dcr_t;
 typedef struct ppc_avr_t ppc_avr_t;
+typedef union ppc_tlb_t ppc_tlb_t;
 
 /* SPR access micro-ops generations callbacks */
 struct ppc_spr_t {
     void (*uea_read)(void *opaque, int spr_num);
     void (*uea_write)(void *opaque, int spr_num);
+#if !defined(CONFIG_USER_ONLY)
     void (*oea_read)(void *opaque, int spr_num);
     void (*oea_write)(void *opaque, int spr_num);
+#endif
     const unsigned char *name;
 };
 
@@ -364,46 +578,58 @@
 };
 
 /* Software TLB cache */
-typedef struct ppc_tlb_t ppc_tlb_t;
-struct ppc_tlb_t {
-    /* Physical page number */
+typedef struct ppc6xx_tlb_t ppc6xx_tlb_t;
+struct ppc6xx_tlb_t {
+    target_ulong pte0;
+    target_ulong pte1;
+    target_ulong EPN;
+};
+
+typedef struct ppcemb_tlb_t ppcemb_tlb_t;
+struct ppcemb_tlb_t {
     target_phys_addr_t RPN;
-    /* Virtual page number */
-    target_ulong VPN;
-    /* Page size */
+    target_ulong EPN;
+    target_ulong PID;
     target_ulong size;
-    /* Protection bits */
-    int prot;
-    int is_user;
-    uint32_t private;
-    uint32_t flags;
+    uint32_t prot;
+    uint32_t attr; /* Storage attributes */
 };
 
+union ppc_tlb_t {
+    ppc6xx_tlb_t tlb6;
+    ppcemb_tlb_t tlbe;
+};
+
 /*****************************************************************************/
 /* Machine state register bits definition                                    */
-#define MSR_SF   63 /* Sixty-four-bit mode                                   */
+#define MSR_SF   63 /* Sixty-four-bit mode                            hflags */
 #define MSR_ISF  61 /* Sixty-four-bit interrupt mode on 630                  */
-#define MSR_HV   60 /* hypervisor state                                      */
-#define MSR_VR   25 /* altivec available                                     */
-#define MSR_AP   23 /* Access privilege state on 602                         */
-#define MSR_SA   22 /* Supervisor access mode on 602                         */
+#define MSR_HV   60 /* hypervisor state                               hflags */
+#define MSR_CM   31 /* Computation mode for BookE                     hflags */
+#define MSR_ICM  30 /* Interrupt computation mode for BookE                  */
+#define MSR_UCLE 26 /* User-mode cache lock enable for BookE                 */
+#define MSR_VR   25 /* altivec available                              hflags */
+#define MSR_SPE  25 /* SPE enable for BookE                           hflags */
+#define MSR_AP   23 /* Access privilege state on 602                  hflags */
+#define MSR_SA   22 /* Supervisor access mode on 602                  hflags */
 #define MSR_KEY  19 /* key bit on 603e                                       */
 #define MSR_POW  18 /* Power management                                      */
 #define MSR_WE   18 /* Wait state enable on embedded PowerPC                 */
 #define MSR_TGPR 17 /* TGPR usage on 602/603                                 */
-#define MSR_TLB  17 /* TLB on ?                                              */
+#define MSR_TLB  17 /* TLB update on ?                                       */
 #define MSR_CE   17 /* Critical interrupt enable on embedded PowerPC         */
 #define MSR_ILE  16 /* Interrupt little-endian mode                          */
 #define MSR_EE   15 /* External interrupt enable                             */
-#define MSR_PR   14 /* Problem state                                         */
-#define MSR_FP   13 /* Floating point available                              */
+#define MSR_PR   14 /* Problem state                                  hflags */
+#define MSR_FP   13 /* Floating point available                       hflags */
 #define MSR_ME   12 /* Machine check interrupt enable                        */
-#define MSR_FE0  11 /* Floating point exception mode 0                       */
-#define MSR_SE   10 /* Single-step trace enable                              */
+#define MSR_FE0  11 /* Floating point exception mode 0                hflags */
+#define MSR_SE   10 /* Single-step trace enable                       hflags */
 #define MSR_DWE  10 /* Debug wait enable on 405                              */
-#define MSR_BE   9  /* Branch trace enable                                   */
+#define MSR_UBLE 10 /* User BTB lock enable on e500                          */
+#define MSR_BE   9  /* Branch trace enable                            hflags */
 #define MSR_DE   9  /* Debug interrupts enable on embedded PowerPC           */
-#define MSR_FE1  8  /* Floating point exception mode 1                       */
+#define MSR_FE1  8  /* Floating point exception mode 1                hflags */
 #define MSR_AL   7  /* AL bit on POWER                                       */
 #define MSR_IP   6  /* Interrupt prefix                                      */
 #define MSR_IR   5  /* Instruction relocate                                  */
@@ -415,42 +641,47 @@
 #define MSR_PX   2  /* Protection exclusive on 403                           */
 #define MSR_PMM  2  /* Performance monitor mark on POWER                     */
 #define MSR_RI   1  /* Recoverable interrupt                                 */
-#define MSR_LE   0  /* Little-endian mode                                    */
+#define MSR_LE   0  /* Little-endian mode                             hflags */
 #define msr_sf   env->msr[MSR_SF]
 #define msr_isf  env->msr[MSR_ISF]
 #define msr_hv   env->msr[MSR_HV]
+#define msr_cm   env->msr[MSR_CM]
+#define msr_icm  env->msr[MSR_ICM]
+#define msr_ucle env->msr[MSR_UCLE]
 #define msr_vr   env->msr[MSR_VR]
+#define msr_spe  env->msr[MSR_SPE]
 #define msr_ap   env->msr[MSR_AP]
 #define msr_sa   env->msr[MSR_SA]
 #define msr_key  env->msr[MSR_KEY]
-#define msr_pow env->msr[MSR_POW]
+#define msr_pow  env->msr[MSR_POW]
 #define msr_we   env->msr[MSR_WE]
 #define msr_tgpr env->msr[MSR_TGPR]
 #define msr_tlb  env->msr[MSR_TLB]
 #define msr_ce   env->msr[MSR_CE]
-#define msr_ile env->msr[MSR_ILE]
-#define msr_ee  env->msr[MSR_EE]
-#define msr_pr  env->msr[MSR_PR]
-#define msr_fp  env->msr[MSR_FP]
-#define msr_me  env->msr[MSR_ME]
-#define msr_fe0 env->msr[MSR_FE0]
-#define msr_se  env->msr[MSR_SE]
+#define msr_ile  env->msr[MSR_ILE]
+#define msr_ee   env->msr[MSR_EE]
+#define msr_pr   env->msr[MSR_PR]
+#define msr_fp   env->msr[MSR_FP]
+#define msr_me   env->msr[MSR_ME]
+#define msr_fe0  env->msr[MSR_FE0]
+#define msr_se   env->msr[MSR_SE]
 #define msr_dwe  env->msr[MSR_DWE]
-#define msr_be  env->msr[MSR_BE]
+#define msr_uble env->msr[MSR_UBLE]
+#define msr_be   env->msr[MSR_BE]
 #define msr_de   env->msr[MSR_DE]
-#define msr_fe1 env->msr[MSR_FE1]
+#define msr_fe1  env->msr[MSR_FE1]
 #define msr_al   env->msr[MSR_AL]
-#define msr_ip  env->msr[MSR_IP]
-#define msr_ir  env->msr[MSR_IR]
+#define msr_ip   env->msr[MSR_IP]
+#define msr_ir   env->msr[MSR_IR]
 #define msr_is   env->msr[MSR_IS]
-#define msr_dr  env->msr[MSR_DR]
+#define msr_dr   env->msr[MSR_DR]
 #define msr_ds   env->msr[MSR_DS]
 #define msr_pe   env->msr[MSR_PE]
 #define msr_ep   env->msr[MSR_EP]
 #define msr_px   env->msr[MSR_PX]
 #define msr_pmm  env->msr[MSR_PMM]
-#define msr_ri  env->msr[MSR_RI]
-#define msr_le  env->msr[MSR_LE]
+#define msr_ri   env->msr[MSR_RI]
+#define msr_le   env->msr[MSR_LE]
 
 /*****************************************************************************/
 /* The whole PowerPC CPU context */
@@ -458,14 +689,16 @@
     /* First are the most commonly used resources
      * during translated code execution
      */
-#if TARGET_LONG_BITS > HOST_LONG_BITS
+#if TARGET_GPR_BITS > HOST_LONG_BITS
     /* temporary fixed-point registers
      * used to emulate 64 bits target on 32 bits hosts
-     */
+     */ 
     target_ulong t0, t1, t2;
 #endif
+    ppc_avr_t t0_avr, t1_avr, t2_avr;
+
     /* general purpose registers */
-    target_ulong gpr[32];
+    ppc_gpr_t gpr[32];
     /* LR */
     target_ulong lr;
     /* CTR */
@@ -482,10 +715,10 @@
     /* machine state register */
     uint8_t msr[64];
     /* temporary general purpose registers */
-    target_ulong tgpr[4]; /* Used to speed-up TLB assist handlers */
+    ppc_gpr_t tgpr[4]; /* Used to speed-up TLB assist handlers */
 
     /* Floating point execution context */
-     /* temporary float registers */
+    /* temporary float registers */
     float64 ft0;
     float64 ft1;
     float64 ft2;
@@ -519,23 +752,25 @@
     /* Altivec registers */
     ppc_avr_t avr[32];
     uint32_t vscr;
+    /* SPE registers */
+    ppc_gpr_t spe_acc;
+    float_status spe_status;
+    uint32_t spe_fscr;
 
     /* Internal devices resources */
     /* Time base and decrementer */
     ppc_tb_t *tb_env;
     /* Device control registers */
-    int (*dcr_read)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong *val);
-    int (*dcr_write)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong val);
     ppc_dcr_t *dcr_env;
 
     /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
-    int nb_tlb;
-    int nb_ways, last_way;
-    ppc_tlb_t tlb[128];
-    /* Callbacks for specific checks on some implementations */
-    int (*tlb_check_more)(CPUPPCState *env, struct ppc_tlb_t *tlb, int *prot,
-                          target_ulong vaddr, int rw, int acc_type,
-                          int is_user);
+    int nb_tlb;      /* Total number of TLB                                  */
+    int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
+    int nb_ways;     /* Number of ways in the TLB set                        */
+    int last_way;    /* Last used way used to allocate TLB in a LRU way      */
+    int id_tlbs;     /* If 1, MMU has separated TLBs for instructions & data */
+    int nb_pids;     /* Number of available PID registers                    */
+    ppc_tlb_t *tlb;  /* TLB is optional. Allocate them only if needed        */
     /* 403 dedicated access protection registers */
     target_ulong pb[4];
 
@@ -547,6 +782,14 @@
     int exception_index;
     int error_code;
     int interrupt_request;
+    uint32_t pending_interrupts;
+#if !defined(CONFIG_USER_ONLY)
+    /* This is the IRQ controller, which is implementation dependant
+     * and only relevant when emulating a complete machine.
+     */
+    uint32_t irq_input_state;
+    void **irq_inputs;
+#endif
 
     /* Those resources are used only during code translation */
     /* Next instruction pointer */
@@ -568,6 +811,16 @@
     int (*osi_call)(struct CPUPPCState *env);
 };
 
+/* Context used internally during MMU translations */
+typedef struct mmu_ctx_t mmu_ctx_t;
+struct mmu_ctx_t {
+    target_phys_addr_t raddr;      /* Real address              */
+    int prot;                      /* Protection bits           */
+    target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
+    target_ulong ptem;             /* Virtual segment ID | API  */
+    int key;                       /* Access key                */
+};
+
 /*****************************************************************************/
 CPUPPCState *cpu_ppc_init(void);
 int cpu_ppc_exec(CPUPPCState *s);
@@ -575,15 +828,16 @@
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
-struct siginfo;
-int cpu_ppc_signal_handler(int host_signum, struct siginfo *info, 
+int cpu_ppc_signal_handler(int host_signum, void *pinfo, 
                            void *puc);
 
 void do_interrupt (CPUPPCState *env);
+void ppc_hw_interrupt (CPUPPCState *env);
 void cpu_loop_exit(void);
 
 void dump_stack (CPUPPCState *env);
 
+#if !defined(CONFIG_USER_ONLY)
 target_ulong do_load_ibatu (CPUPPCState *env, int nr);
 target_ulong do_load_ibatl (CPUPPCState *env, int nr);
 void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value);
@@ -592,25 +846,25 @@
 target_ulong do_load_dbatl (CPUPPCState *env, int nr);
 void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
 void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
-
-target_ulong do_load_nip (CPUPPCState *env);
-void do_store_nip (CPUPPCState *env, target_ulong value);
 target_ulong do_load_sdr1 (CPUPPCState *env);
 void do_store_sdr1 (CPUPPCState *env, target_ulong value);
-target_ulong do_load_asr (CPUPPCState *env);
-void do_store_asr (CPUPPCState *env, target_ulong value);
+#if defined(TARGET_PPC64)
+target_ulong ppc_load_asr (CPUPPCState *env);
+void ppc_store_asr (CPUPPCState *env, target_ulong value);
+#endif
 target_ulong do_load_sr (CPUPPCState *env, int srnum);
 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
-uint32_t do_load_cr (CPUPPCState *env);
-void do_store_cr (CPUPPCState *env, uint32_t value, uint32_t mask);
-uint32_t do_load_xer (CPUPPCState *env);
-void do_store_xer (CPUPPCState *env, uint32_t value);
+#endif
+uint32_t ppc_load_xer (CPUPPCState *env);
+void ppc_store_xer (CPUPPCState *env, uint32_t value);
 target_ulong do_load_msr (CPUPPCState *env);
 void do_store_msr (CPUPPCState *env, target_ulong value);
-float64 do_load_fpscr (CPUPPCState *env);
-void do_store_fpscr (CPUPPCState *env, float64 f, uint32_t mask);
+void ppc_store_msr_32 (CPUPPCState *env, uint32_t value);
 
 void do_compute_hflags (CPUPPCState *env);
+void cpu_ppc_reset (void *opaque);
+CPUPPCState *cpu_ppc_init (void);
+void cpu_ppc_close(CPUPPCState *env);
 
 int ppc_find_by_name (const unsigned char *name, ppc_def_t **def);
 int ppc_find_by_pvr (uint32_t apvr, ppc_def_t **def);
@@ -625,9 +879,26 @@
 void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value);
 uint32_t cpu_ppc_load_decr (CPUPPCState *env);
 void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
+uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
+uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
+#if !defined(CONFIG_USER_ONLY)
+void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value);
+void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value);
+target_ulong load_40x_pit (CPUPPCState *env);
+void store_40x_pit (CPUPPCState *env, target_ulong val);
+void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
+void store_40x_sler (CPUPPCState *env, uint32_t val);
+void store_booke_tcr (CPUPPCState *env, target_ulong val);
+void store_booke_tsr (CPUPPCState *env, target_ulong val);
+void ppc_tlb_invalidate_all (CPUPPCState *env);
+int ppcemb_tlb_search (CPUPPCState *env, target_ulong address);
 #endif
+#endif
 
-#define TARGET_PAGE_BITS 12
+/* Device control registers */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp);
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
+
 #include "cpu-all.h"
 
 /*****************************************************************************/
@@ -646,261 +917,308 @@
 #define xer_bc env->xer[0]
 
 /* SPR definitions */
-#define SPR_MQ         (0x000)
-#define SPR_XER        (0x001)
-#define SPR_601_VRTCU  (0x004)
-#define SPR_601_VRTCL  (0x005)
-#define SPR_601_UDECR  (0x006)
-#define SPR_LR         (0x008)
-#define SPR_CTR        (0x009)
-#define SPR_DSISR      (0x012)
-#define SPR_DAR        (0x013)
-#define SPR_601_RTCU   (0x014)
-#define SPR_601_RTCL   (0x015)
-#define SPR_DECR       (0x016)
-#define SPR_SDR1       (0x019)
-#define SPR_SRR0       (0x01A)
-#define SPR_SRR1       (0x01B)
-#define SPR_440_PID    (0x030)
-#define SPR_440_DECAR  (0x036)
-#define SPR_CSRR0      (0x03A)
-#define SPR_CSRR1      (0x03B)
-#define SPR_440_DEAR   (0x03D)
-#define SPR_440_ESR    (0x03E)
-#define SPR_440_IVPR   (0x03F)
-#define SPR_8xx_EIE    (0x050)
-#define SPR_8xx_EID    (0x051)
-#define SPR_8xx_NRE    (0x052)
-#define SPR_58x_CMPA   (0x090)
-#define SPR_58x_CMPB   (0x091)
-#define SPR_58x_CMPC   (0x092)
-#define SPR_58x_CMPD   (0x093)
-#define SPR_58x_ICR    (0x094)
-#define SPR_58x_DER    (0x094)
-#define SPR_58x_COUNTA (0x096)
-#define SPR_58x_COUNTB (0x097)
-#define SPR_58x_CMPE   (0x098)
-#define SPR_58x_CMPF   (0x099)
-#define SPR_58x_CMPG   (0x09A)
-#define SPR_58x_CMPH   (0x09B)
-#define SPR_58x_LCTRL1 (0x09C)
-#define SPR_58x_LCTRL2 (0x09D)
-#define SPR_58x_ICTRL  (0x09E)
-#define SPR_58x_BAR    (0x09F)
-#define SPR_VRSAVE     (0x100)
-#define SPR_USPRG0     (0x100)
-#define SPR_USPRG4     (0x104)
-#define SPR_USPRG5     (0x105)
-#define SPR_USPRG6     (0x106)
-#define SPR_USPRG7     (0x107)
-#define SPR_VTBL       (0x10C)
-#define SPR_VTBU       (0x10D)
-#define SPR_SPRG0      (0x110)
-#define SPR_SPRG1      (0x111)
-#define SPR_SPRG2      (0x112)
-#define SPR_SPRG3      (0x113)
-#define SPR_SPRG4      (0x114)
-#define SPR_SCOMC      (0x114)
-#define SPR_SPRG5      (0x115)
-#define SPR_SCOMD      (0x115)
-#define SPR_SPRG6      (0x116)
-#define SPR_SPRG7      (0x117)
-#define SPR_ASR        (0x118)
-#define SPR_EAR        (0x11A)
-#define SPR_TBL        (0x11C)
-#define SPR_TBU        (0x11D)
-#define SPR_SVR        (0x11E)
-#define SPR_440_PIR    (0x11E)
-#define SPR_PVR        (0x11F)
-#define SPR_HSPRG0     (0x130)
-#define SPR_440_DBSR   (0x130)
-#define SPR_HSPRG1     (0x131)
-#define SPR_440_DBCR0  (0x134)
-#define SPR_IBCR       (0x135)
-#define SPR_440_DBCR1  (0x135)
-#define SPR_DBCR       (0x136)
-#define SPR_HDEC       (0x136)
-#define SPR_440_DBCR2  (0x136)
-#define SPR_HIOR       (0x137)
-#define SPR_MBAR       (0x137)
-#define SPR_RMOR       (0x138)
-#define SPR_440_IAC1   (0x138)
-#define SPR_HRMOR      (0x139)
-#define SPR_440_IAC2   (0x139)
-#define SPR_HSSR0      (0x13A)
-#define SPR_440_IAC3   (0x13A)
-#define SPR_HSSR1      (0x13B)
-#define SPR_440_IAC4   (0x13B)
-#define SPR_LPCR       (0x13C)
-#define SPR_440_DAC1   (0x13C)
-#define SPR_LPIDR      (0x13D)
-#define SPR_DABR2      (0x13D)
-#define SPR_440_DAC2   (0x13D)
-#define SPR_440_DVC1   (0x13E)
-#define SPR_440_DVC2   (0x13F)
-#define SPR_440_TSR    (0x150)
-#define SPR_440_TCR    (0x154)
-#define SPR_440_IVOR0  (0x190)
-#define SPR_440_IVOR1  (0x191)
-#define SPR_440_IVOR2  (0x192)
-#define SPR_440_IVOR3  (0x193)
-#define SPR_440_IVOR4  (0x194)
-#define SPR_440_IVOR5  (0x195)
-#define SPR_440_IVOR6  (0x196)
-#define SPR_440_IVOR7  (0x197)
-#define SPR_440_IVOR8  (0x198)
-#define SPR_440_IVOR9  (0x199)
-#define SPR_440_IVOR10 (0x19A)
-#define SPR_440_IVOR11 (0x19B)
-#define SPR_440_IVOR12 (0x19C)
-#define SPR_440_IVOR13 (0x19D)
-#define SPR_440_IVOR14 (0x19E)
-#define SPR_440_IVOR15 (0x19F)
-#define SPR_IBAT0U     (0x210)
-#define SPR_IBAT0L     (0x211)
-#define SPR_IBAT1U     (0x212)
-#define SPR_IBAT1L     (0x213)
-#define SPR_IBAT2U     (0x214)
-#define SPR_IBAT2L     (0x215)
-#define SPR_IBAT3U     (0x216)
-#define SPR_IBAT3L     (0x217)
-#define SPR_DBAT0U     (0x218)
-#define SPR_DBAT0L     (0x219)
-#define SPR_DBAT1U     (0x21A)
-#define SPR_DBAT1L     (0x21B)
-#define SPR_DBAT2U     (0x21C)
-#define SPR_DBAT2L     (0x21D)
-#define SPR_DBAT3U     (0x21E)
-#define SPR_DBAT3L     (0x21F)
-#define SPR_IBAT4U     (0x230)
-#define SPR_IBAT4L     (0x231)
-#define SPR_IBAT5U     (0x232)
-#define SPR_IBAT5L     (0x233)
-#define SPR_IBAT6U     (0x234)
-#define SPR_IBAT6L     (0x235)
-#define SPR_IBAT7U     (0x236)
-#define SPR_IBAT7L     (0x237)
-#define SPR_DBAT4U     (0x238)
-#define SPR_DBAT4L     (0x239)
-#define SPR_DBAT5U     (0x23A)
-#define SPR_DBAT5L     (0x23B)
-#define SPR_DBAT6U     (0x23C)
-#define SPR_DBAT6L     (0x23D)
-#define SPR_DBAT7U     (0x23E)
-#define SPR_DBAT7L     (0x23F)
-#define SPR_440_INV0   (0x370)
-#define SPR_440_INV1   (0x371)
-#define SPR_440_INV2   (0x372)
-#define SPR_440_INV3   (0x373)
-#define SPR_440_IVT0   (0x374)
-#define SPR_440_IVT1   (0x375)
-#define SPR_440_IVT2   (0x376)
-#define SPR_440_IVT3   (0x377)
-#define SPR_440_DNV0   (0x390)
-#define SPR_440_DNV1   (0x391)
-#define SPR_440_DNV2   (0x392)
-#define SPR_440_DNV3   (0x393)
-#define SPR_440_DVT0   (0x394)
-#define SPR_440_DVT1   (0x395)
-#define SPR_440_DVT2   (0x396)
-#define SPR_440_DVT3   (0x397)
-#define SPR_440_DVLIM  (0x398)
-#define SPR_440_IVLIM  (0x399)
-#define SPR_440_RSTCFG (0x39B)
-#define SPR_440_DCBTRL (0x39C)
-#define SPR_440_DCBTRH (0x39D)
-#define SPR_440_ICBTRL (0x39E)
-#define SPR_440_ICBTRH (0x39F)
-#define SPR_UMMCR0     (0x3A8)
-#define SPR_UPMC1      (0x3A9)
-#define SPR_UPMC2      (0x3AA)
-#define SPR_USIA       (0x3AB)
-#define SPR_UMMCR1     (0x3AC)
-#define SPR_UPMC3      (0x3AD)
-#define SPR_UPMC4      (0x3AE)
-#define SPR_USDA       (0x3AF)
-#define SPR_40x_ZPR    (0x3B0)
-#define SPR_40x_PID    (0x3B1)
-#define SPR_440_MMUCR  (0x3B2)
-#define SPR_4xx_CCR0   (0x3B3)
-#define SPR_405_IAC3   (0x3B4)
-#define SPR_405_IAC4   (0x3B5)
-#define SPR_405_DVC1   (0x3B6)
-#define SPR_405_DVC2   (0x3B7)
-#define SPR_MMCR0      (0x3B8)
-#define SPR_PMC1       (0x3B9)
-#define SPR_40x_SGR    (0x3B9)
-#define SPR_PMC2       (0x3BA)
-#define SPR_40x_DCWR   (0x3BA)
-#define SPR_SIA        (0x3BB)
-#define SPR_405_SLER   (0x3BB)
-#define SPR_MMCR1      (0x3BC)
-#define SPR_405_SU0R   (0x3BC)
-#define SPR_PMC3       (0x3BD)
-#define SPR_405_DBCR1  (0x3BD)
-#define SPR_PMC4       (0x3BE)
-#define SPR_SDA        (0x3BF)
-#define SPR_403_VTBL   (0x3CC)
-#define SPR_403_VTBU   (0x3CD)
-#define SPR_DMISS      (0x3D0)
-#define SPR_DCMP       (0x3D1)
-#define SPR_DHASH1     (0x3D2)
-#define SPR_DHASH2     (0x3D3)
-#define SPR_4xx_ICDBDR (0x3D3)
-#define SPR_IMISS      (0x3D4)
-#define SPR_40x_ESR    (0x3D4)
-#define SPR_ICMP       (0x3D5)
-#define SPR_40x_DEAR   (0x3D5)
-#define SPR_RPA        (0x3D6)
-#define SPR_40x_EVPR   (0x3D6)
-#define SPR_403_CDBCR  (0x3D7)
-#define SPR_TCR        (0x3D8)
-#define SPR_40x_TSR    (0x3D8)
-#define SPR_IBR        (0x3DA)
-#define SPR_40x_TCR    (0x3DA)
-#define SPR_ESASR      (0x3DB)
-#define SPR_40x_PIT    (0x3DB)
-#define SPR_403_TBL    (0x3DC)
-#define SPR_403_TBU    (0x3DD)
-#define SPR_SEBR       (0x3DE)
-#define SPR_40x_SRR2   (0x3DE)
-#define SPR_SER        (0x3DF)
-#define SPR_40x_SRR3   (0x3DF)
-#define SPR_HID0       (0x3F0)
-#define SPR_40x_DBSR   (0x3F0)
-#define SPR_HID1       (0x3F1)
-#define SPR_IABR       (0x3F2)
-#define SPR_40x_DBCR0  (0x3F2)
-#define SPR_601_HID2   (0x3F2)
-#define SPR_HID2       (0x3F3)
-#define SPR_440_DBDR   (0x3F3)
-#define SPR_40x_IAC1   (0x3F4)
-#define SPR_DABR       (0x3F5)
+#define SPR_MQ           (0x000)
+#define SPR_XER          (0x001)
+#define SPR_601_VRTCU    (0x004)
+#define SPR_601_VRTCL    (0x005)
+#define SPR_601_UDECR    (0x006)
+#define SPR_LR           (0x008)
+#define SPR_CTR          (0x009)
+#define SPR_DSISR        (0x012)
+#define SPR_DAR          (0x013)
+#define SPR_601_RTCU     (0x014)
+#define SPR_601_RTCL     (0x015)
+#define SPR_DECR         (0x016)
+#define SPR_SDR1         (0x019)
+#define SPR_SRR0         (0x01A)
+#define SPR_SRR1         (0x01B)
+#define SPR_BOOKE_PID    (0x030)
+#define SPR_BOOKE_DECAR  (0x036)
+#define SPR_BOOKE_CSRR0  (0x03A)
+#define SPR_BOOKE_CSRR1  (0x03B)
+#define SPR_BOOKE_DEAR   (0x03D)
+#define SPR_BOOKE_ESR    (0x03E)
+#define SPR_BOOKE_IVPR   (0x03F)
+#define SPR_8xx_EIE      (0x050)
+#define SPR_8xx_EID      (0x051)
+#define SPR_8xx_NRE      (0x052)
+#define SPR_58x_CMPA     (0x090)
+#define SPR_58x_CMPB     (0x091)
+#define SPR_58x_CMPC     (0x092)
+#define SPR_58x_CMPD     (0x093)
+#define SPR_58x_ICR      (0x094)
+#define SPR_58x_DER      (0x094)
+#define SPR_58x_COUNTA   (0x096)
+#define SPR_58x_COUNTB   (0x097)
+#define SPR_58x_CMPE     (0x098)
+#define SPR_58x_CMPF     (0x099)
+#define SPR_58x_CMPG     (0x09A)
+#define SPR_58x_CMPH     (0x09B)
+#define SPR_58x_LCTRL1   (0x09C)
+#define SPR_58x_LCTRL2   (0x09D)
+#define SPR_58x_ICTRL    (0x09E)
+#define SPR_58x_BAR      (0x09F)
+#define SPR_VRSAVE       (0x100)
+#define SPR_USPRG0       (0x100)
+#define SPR_USPRG1       (0x101)
+#define SPR_USPRG2       (0x102)
+#define SPR_USPRG3       (0x103)
+#define SPR_USPRG4       (0x104)
+#define SPR_USPRG5       (0x105)
+#define SPR_USPRG6       (0x106)
+#define SPR_USPRG7       (0x107)
+#define SPR_VTBL         (0x10C)
+#define SPR_VTBU         (0x10D)
+#define SPR_SPRG0        (0x110)
+#define SPR_SPRG1        (0x111)
+#define SPR_SPRG2        (0x112)
+#define SPR_SPRG3        (0x113)
+#define SPR_SPRG4        (0x114)
+#define SPR_SCOMC        (0x114)
+#define SPR_SPRG5        (0x115)
+#define SPR_SCOMD        (0x115)
+#define SPR_SPRG6        (0x116)
+#define SPR_SPRG7        (0x117)
+#define SPR_ASR          (0x118)
+#define SPR_EAR          (0x11A)
+#define SPR_TBL          (0x11C)
+#define SPR_TBU          (0x11D)
+#define SPR_SVR          (0x11E)
+#define SPR_BOOKE_PIR    (0x11E)
+#define SPR_PVR          (0x11F)
+#define SPR_HSPRG0       (0x130)
+#define SPR_BOOKE_DBSR   (0x130)
+#define SPR_HSPRG1       (0x131)
+#define SPR_BOOKE_DBCR0  (0x134)
+#define SPR_IBCR         (0x135)
+#define SPR_BOOKE_DBCR1  (0x135)
+#define SPR_DBCR         (0x136)
+#define SPR_HDEC         (0x136)
+#define SPR_BOOKE_DBCR2  (0x136)
+#define SPR_HIOR         (0x137)
+#define SPR_MBAR         (0x137)
+#define SPR_RMOR         (0x138)
+#define SPR_BOOKE_IAC1   (0x138)
+#define SPR_HRMOR        (0x139)
+#define SPR_BOOKE_IAC2   (0x139)
+#define SPR_HSSR0        (0x13A)
+#define SPR_BOOKE_IAC3   (0x13A)
+#define SPR_HSSR1        (0x13B)
+#define SPR_BOOKE_IAC4   (0x13B)
+#define SPR_LPCR         (0x13C)
+#define SPR_BOOKE_DAC1   (0x13C)
+#define SPR_LPIDR        (0x13D)
+#define SPR_DABR2        (0x13D)
+#define SPR_BOOKE_DAC2   (0x13D)
+#define SPR_BOOKE_DVC1   (0x13E)
+#define SPR_BOOKE_DVC2   (0x13F)
+#define SPR_BOOKE_TSR    (0x150)
+#define SPR_BOOKE_TCR    (0x154)
+#define SPR_BOOKE_IVOR0  (0x190)
+#define SPR_BOOKE_IVOR1  (0x191)
+#define SPR_BOOKE_IVOR2  (0x192)
+#define SPR_BOOKE_IVOR3  (0x193)
+#define SPR_BOOKE_IVOR4  (0x194)
+#define SPR_BOOKE_IVOR5  (0x195)
+#define SPR_BOOKE_IVOR6  (0x196)
+#define SPR_BOOKE_IVOR7  (0x197)
+#define SPR_BOOKE_IVOR8  (0x198)
+#define SPR_BOOKE_IVOR9  (0x199)
+#define SPR_BOOKE_IVOR10 (0x19A)
+#define SPR_BOOKE_IVOR11 (0x19B)
+#define SPR_BOOKE_IVOR12 (0x19C)
+#define SPR_BOOKE_IVOR13 (0x19D)
+#define SPR_BOOKE_IVOR14 (0x19E)
+#define SPR_BOOKE_IVOR15 (0x19F)
+#define SPR_E500_SPEFSCR (0x200)
+#define SPR_E500_BBEAR   (0x201)
+#define SPR_E500_BBTAR   (0x202)
+#define SPR_BOOKE_ATBL   (0x20E)
+#define SPR_BOOKE_ATBU   (0x20F)
+#define SPR_IBAT0U       (0x210)
+#define SPR_BOOKE_IVOR32 (0x210)
+#define SPR_IBAT0L       (0x211)
+#define SPR_BOOKE_IVOR33 (0x211)
+#define SPR_IBAT1U       (0x212)
+#define SPR_BOOKE_IVOR34 (0x212)
+#define SPR_IBAT1L       (0x213)
+#define SPR_BOOKE_IVOR35 (0x213)
+#define SPR_IBAT2U       (0x214)
+#define SPR_BOOKE_IVOR36 (0x214)
+#define SPR_IBAT2L       (0x215)
+#define SPR_E500_L1CFG0  (0x215)
+#define SPR_BOOKE_IVOR37 (0x215)
+#define SPR_IBAT3U       (0x216)
+#define SPR_E500_L1CFG1  (0x216)
+#define SPR_IBAT3L       (0x217)
+#define SPR_DBAT0U       (0x218)
+#define SPR_DBAT0L       (0x219)
+#define SPR_DBAT1U       (0x21A)
+#define SPR_DBAT1L       (0x21B)
+#define SPR_DBAT2U       (0x21C)
+#define SPR_DBAT2L       (0x21D)
+#define SPR_DBAT3U       (0x21E)
+#define SPR_DBAT3L       (0x21F)
+#define SPR_IBAT4U       (0x230)
+#define SPR_IBAT4L       (0x231)
+#define SPR_IBAT5U       (0x232)
+#define SPR_IBAT5L       (0x233)
+#define SPR_IBAT6U       (0x234)
+#define SPR_IBAT6L       (0x235)
+#define SPR_IBAT7U       (0x236)
+#define SPR_IBAT7L       (0x237)
+#define SPR_DBAT4U       (0x238)
+#define SPR_DBAT4L       (0x239)
+#define SPR_DBAT5U       (0x23A)
+#define SPR_BOOKE_MCSRR0 (0x23A)
+#define SPR_DBAT5L       (0x23B)
+#define SPR_BOOKE_MCSRR1 (0x23B)
+#define SPR_DBAT6U       (0x23C)
+#define SPR_BOOKE_MCSR   (0x23C)
+#define SPR_DBAT6L       (0x23D)
+#define SPR_E500_MCAR    (0x23D)
+#define SPR_DBAT7U       (0x23E)
+#define SPR_BOOKE_DSRR0  (0x23E)
+#define SPR_DBAT7L       (0x23F)
+#define SPR_BOOKE_DSRR1  (0x23F)
+#define SPR_BOOKE_SPRG8  (0x25C)
+#define SPR_BOOKE_SPRG9  (0x25D)
+#define SPR_BOOKE_MAS0   (0x270)
+#define SPR_BOOKE_MAS1   (0x271)
+#define SPR_BOOKE_MAS2   (0x272)
+#define SPR_BOOKE_MAS3   (0x273)
+#define SPR_BOOKE_MAS4   (0x274)
+#define SPR_BOOKE_MAS6   (0x276)
+#define SPR_BOOKE_PID1   (0x279)
+#define SPR_BOOKE_PID2   (0x27A)
+#define SPR_BOOKE_TLB0CFG (0x2B0)
+#define SPR_BOOKE_TLB1CFG (0x2B1)
+#define SPR_BOOKE_TLB2CFG (0x2B2)
+#define SPR_BOOKE_TLB3CFG (0x2B3)
+#define SPR_BOOKE_EPR    (0x2BE)
+#define SPR_440_INV0     (0x370)
+#define SPR_440_INV1     (0x371)
+#define SPR_440_INV2     (0x372)
+#define SPR_440_INV3     (0x373)
+#define SPR_440_IVT0     (0x374)
+#define SPR_440_IVT1     (0x375)
+#define SPR_440_IVT2     (0x376)
+#define SPR_440_IVT3     (0x377)
+#define SPR_440_DNV0     (0x390)
+#define SPR_440_DNV1     (0x391)
+#define SPR_440_DNV2     (0x392)
+#define SPR_440_DNV3     (0x393)
+#define SPR_440_DVT0     (0x394)
+#define SPR_440_DVT1     (0x395)
+#define SPR_440_DVT2     (0x396)
+#define SPR_440_DVT3     (0x397)
+#define SPR_440_DVLIM    (0x398)
+#define SPR_440_IVLIM    (0x399)
+#define SPR_440_RSTCFG   (0x39B)
+#define SPR_BOOKE_DCBTRL (0x39C)
+#define SPR_BOOKE_DCBTRH (0x39D)
+#define SPR_BOOKE_ICBTRL (0x39E)
+#define SPR_BOOKE_ICBTRH (0x39F)
+#define SPR_UMMCR0       (0x3A8)
+#define SPR_UPMC1        (0x3A9)
+#define SPR_UPMC2        (0x3AA)
+#define SPR_USIA         (0x3AB)
+#define SPR_UMMCR1       (0x3AC)
+#define SPR_UPMC3        (0x3AD)
+#define SPR_UPMC4        (0x3AE)
+#define SPR_USDA         (0x3AF)
+#define SPR_40x_ZPR      (0x3B0)
+#define SPR_BOOKE_MAS7   (0x3B0)
+#define SPR_40x_PID      (0x3B1)
+#define SPR_440_MMUCR    (0x3B2)
+#define SPR_4xx_CCR0     (0x3B3)
+#define SPR_BOOKE_EPLC   (0x3B3)
+#define SPR_405_IAC3     (0x3B4)
+#define SPR_BOOKE_EPSC   (0x3B4)
+#define SPR_405_IAC4     (0x3B5)
+#define SPR_405_DVC1     (0x3B6)
+#define SPR_405_DVC2     (0x3B7)
+#define SPR_MMCR0        (0x3B8)
+#define SPR_PMC1         (0x3B9)
+#define SPR_40x_SGR      (0x3B9)
+#define SPR_PMC2         (0x3BA)
+#define SPR_40x_DCWR     (0x3BA)
+#define SPR_SIA          (0x3BB)
+#define SPR_405_SLER     (0x3BB)
+#define SPR_MMCR1        (0x3BC)
+#define SPR_405_SU0R     (0x3BC)
+#define SPR_PMC3         (0x3BD)
+#define SPR_405_DBCR1    (0x3BD)
+#define SPR_PMC4         (0x3BE)
+#define SPR_SDA          (0x3BF)
+#define SPR_403_VTBL     (0x3CC)
+#define SPR_403_VTBU     (0x3CD)
+#define SPR_DMISS        (0x3D0)
+#define SPR_DCMP         (0x3D1)
+#define SPR_HASH1        (0x3D2)
+#define SPR_HASH2        (0x3D3)
+#define SPR_BOOKE_ICBDR  (0x3D3)
+#define SPR_IMISS        (0x3D4)
+#define SPR_40x_ESR      (0x3D4)
+#define SPR_ICMP         (0x3D5)
+#define SPR_40x_DEAR     (0x3D5)
+#define SPR_RPA          (0x3D6)
+#define SPR_40x_EVPR     (0x3D6)
+#define SPR_403_CDBCR    (0x3D7)
+#define SPR_TCR          (0x3D8)
+#define SPR_40x_TSR      (0x3D8)
+#define SPR_IBR          (0x3DA)
+#define SPR_40x_TCR      (0x3DA)
+#define SPR_ESASR        (0x3DB)
+#define SPR_40x_PIT      (0x3DB)
+#define SPR_403_TBL      (0x3DC)
+#define SPR_403_TBU      (0x3DD)
+#define SPR_SEBR         (0x3DE)
+#define SPR_40x_SRR2     (0x3DE)
+#define SPR_SER          (0x3DF)
+#define SPR_40x_SRR3     (0x3DF)
+#define SPR_HID0         (0x3F0)
+#define SPR_40x_DBSR     (0x3F0)
+#define SPR_HID1         (0x3F1)
+#define SPR_IABR         (0x3F2)
+#define SPR_40x_DBCR0    (0x3F2)
+#define SPR_601_HID2     (0x3F2)
+#define SPR_E500_L1CSR0  (0x3F2)
+#define SPR_HID2         (0x3F3)
+#define SPR_E500_L1CSR1  (0x3F3)
+#define SPR_440_DBDR     (0x3F3)
+#define SPR_40x_IAC1     (0x3F4)
+#define SPR_BOOKE_MMUCSR0 (0x3F4)
+#define SPR_DABR         (0x3F5)
 #define DABR_MASK (~(target_ulong)0x7)
-#define SPR_40x_IAC2   (0x3F5)
-#define SPR_601_HID5   (0x3F5)
-#define SPR_40x_DAC1   (0x3F6)
-#define SPR_40x_DAC2   (0x3F7)
-#define SPR_L2PM       (0x3F8)
-#define SPR_750_HID2   (0x3F8)
-#define SPR_L2CR       (0x3F9)
-#define SPR_IABR2      (0x3FA)
-#define SPR_40x_DCCR   (0x3FA)
-#define SPR_ICTC       (0x3FB)
-#define SPR_40x_ICCR   (0x3FB)
-#define SPR_THRM1      (0x3FC)
-#define SPR_403_PBL1   (0x3FC)
-#define SPR_SP         (0x3FD)
-#define SPR_THRM2      (0x3FD)
-#define SPR_403_PBU1   (0x3FD)
-#define SPR_LT         (0x3FE)
-#define SPR_THRM3      (0x3FE)
-#define SPR_FPECR      (0x3FE)
-#define SPR_403_PBL2   (0x3FE)
-#define SPR_PIR        (0x3FF)
-#define SPR_403_PBU2   (0x3FF)
-#define SPR_601_HID15  (0x3FF)
+#define SPR_E500_BUCSR   (0x3F5)
+#define SPR_40x_IAC2     (0x3F5)
+#define SPR_601_HID5     (0x3F5)
+#define SPR_40x_DAC1     (0x3F6)
+#define SPR_40x_DAC2     (0x3F7)
+#define SPR_BOOKE_MMUCFG (0x3F7)
+#define SPR_L2PM         (0x3F8)
+#define SPR_750_HID2     (0x3F8)
+#define SPR_L2CR         (0x3F9)
+#define SPR_IABR2        (0x3FA)
+#define SPR_40x_DCCR     (0x3FA)
+#define SPR_ICTC         (0x3FB)
+#define SPR_40x_ICCR     (0x3FB)
+#define SPR_THRM1        (0x3FC)
+#define SPR_403_PBL1     (0x3FC)
+#define SPR_SP           (0x3FD)
+#define SPR_THRM2        (0x3FD)
+#define SPR_403_PBU1     (0x3FD)
+#define SPR_LT           (0x3FE)
+#define SPR_THRM3        (0x3FE)
+#define SPR_FPECR        (0x3FE)
+#define SPR_403_PBL2     (0x3FE)
+#define SPR_PIR          (0x3FF)
+#define SPR_403_PBU2     (0x3FF)
+#define SPR_601_HID15    (0x3FF)
+#define SPR_E500_SVR     (0x3FF)
 
+/*****************************************************************************/
 /* Memory access type :
  * may be needed for precise access rights control and precise exceptions.
  */
@@ -974,11 +1292,13 @@
 #define EXCP_970_MAINT     0x1600 /* Maintenance exception                   */
 #define EXCP_970_THRM      0x1800 /* Thermal exception                       */
 #define EXCP_970_VPUA      0x1700 /* VPU assist exception                    */
+/* SPE related exceptions                                                    */
+#define EXCP_NO_SPE        0x0F20 /* SPE unavailable exception               */
 /* End of exception vectors area                                             */
 #define EXCP_PPC_MAX       0x4000
 /* Qemu exceptions: special cases we want to stop translation                */
 #define EXCP_MTMSR         0x11000 /* mtmsr instruction:                     */
-                                /* may change privilege level       */
+                                   /* may change privilege level             */
 #define EXCP_BRANCH        0x11001 /* branch instruction                     */
 #define EXCP_SYSCALL_USER  0x12000 /* System call in user mode only          */
 #define EXCP_INTERRUPT_CRITICAL 0x13000 /* critical IRQ                      */
@@ -1022,6 +1342,71 @@
     EXCP_TRAP          = 0x40,
 };
 
+/* Hardware interruption sources:
+ * all those exception can be raised simulteaneously
+ */
+/* Input pins definitions */
+enum {
+    /* 6xx bus input pins */
+    PPC6xx_INPUT_HRESET     = 0,
+    PPC6xx_INPUT_SRESET     = 1,
+    PPC6xx_INPUT_CKSTP_IN   = 2,
+    PPC6xx_INPUT_MCP        = 3,
+    PPC6xx_INPUT_SMI        = 4,
+    PPC6xx_INPUT_INT        = 5,
+};
+
+enum {
+    /* Embedded PowerPC input pins */
+    PPCBookE_INPUT_HRESET     = 0,
+    PPCBookE_INPUT_SRESET     = 1,
+    PPCBookE_INPUT_CKSTP_IN   = 2,
+    PPCBookE_INPUT_MCP        = 3,
+    PPCBookE_INPUT_SMI        = 4,
+    PPCBookE_INPUT_INT        = 5,
+    PPCBookE_INPUT_CINT       = 6,
+};
+
+enum {
+    /* PowerPC 405 input pins */
+    PPC405_INPUT_RESET_CORE = 0,
+    PPC405_INPUT_RESET_CHIP = 1,
+    PPC405_INPUT_RESET_SYS  = 2,
+    PPC405_INPUT_CINT       = 3,
+    PPC405_INPUT_INT        = 4,
+    PPC405_INPUT_HALT       = 5,
+    PPC405_INPUT_DEBUG      = 6,
+};
+
+enum {
+    /* PowerPC 970 input pins */
+    PPC970_INPUT_HRESET     = 0,
+    PPC970_INPUT_SRESET     = 1,
+    PPC970_INPUT_CKSTP      = 2,
+    PPC970_INPUT_TBEN       = 3,
+    PPC970_INPUT_MCP        = 4,
+    PPC970_INPUT_INT        = 5,
+    PPC970_INPUT_THINT      = 6,
+};
+
+/* Hardware exceptions definitions */
+enum {
+    /* External hardware exception sources */
+    PPC_INTERRUPT_RESET  = 0,  /* Reset exception                      */
+    PPC_INTERRUPT_MCK    = 1,  /* Machine check exception              */
+    PPC_INTERRUPT_EXT    = 2,  /* External interrupt                   */
+    PPC_INTERRUPT_SMI    = 3,  /* System management interrupt          */
+    PPC_INTERRUPT_CEXT   = 4,  /* Critical external interrupt          */
+    PPC_INTERRUPT_DEBUG  = 5,  /* External debug exception             */
+    PPC_INTERRUPT_THERM  = 6,  /* Thermal exception                    */
+    /* Internal hardware exception sources */
+    PPC_INTERRUPT_DECR   = 7,  /* Decrementer exception                */
+    PPC_INTERRUPT_HDECR  = 8,  /* Hypervisor decrementer exception     */
+    PPC_INTERRUPT_PIT    = 9,  /* Programmable inteval timer interrupt */
+    PPC_INTERRUPT_FIT    = 10, /* Fixed interval timer interrupt       */
+    PPC_INTERRUPT_WDT    = 11, /* Watchdog timer interrupt             */
+};
+
 /*****************************************************************************/
 
 #endif /* !defined (__CPU_PPC_H__) */

Modified: trunk/src/host/qemu-neo1973/target-ppc/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation definitions for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -24,15 +24,44 @@
 
 #include "dyngen-exec.h"
 
-#define TARGET_LONG_BITS 32
+#include "cpu.h"
+#include "exec-all.h"
 
+/* For normal operations, precise emulation should not be needed */
+//#define USE_PRECISE_EMULATION 1
+#define USE_PRECISE_EMULATION 0
+
 register struct CPUPPCState *env asm(AREG0);
-register uint32_t T0 asm(AREG1);
-register uint32_t T1 asm(AREG2);
-register uint32_t T2 asm(AREG3);
+#if TARGET_LONG_BITS > HOST_LONG_BITS
+/* no registers can be used */
+#define T0 (env->t0)
+#define T1 (env->t1)
+#define T2 (env->t2)
+#else
+register unsigned long T0 asm(AREG1);
+register unsigned long T1 asm(AREG2);
+register unsigned long T2 asm(AREG3);
+#endif
+/* We may, sometime, need 64 bits registers on 32 bits target */
+#if defined(TARGET_PPC64) || defined(TARGET_PPCEMB) || (HOST_LONG_BITS == 64)
+#define T0_64 T0
+#define T1_64 T1
+#define T2_64 T2
+#else
+/* no registers can be used */
+#define T0_64 (env->t0)
+#define T1_64 (env->t1)
+#define T2_64 (env->t2)
+#endif
+/* Provision for Altivec */
+#define T0_avr (env->t0_avr)
+#define T1_avr (env->t1_avr)
+#define T2_avr (env->t2_avr)
 
+/* XXX: to clean: remove this mess */
 #define PARAM(n) ((uint32_t)PARAM##n)
 #define SPARAM(n) ((int32_t)PARAM##n)
+
 #define FT0 (env->ft0)
 #define FT1 (env->ft1)
 #define FT2 (env->ft2)
@@ -43,14 +72,28 @@
 # define RETURN() __asm__ __volatile__("" : : : "memory");
 #endif
 
-#include "cpu.h"
-#include "exec-all.h"
+static inline target_ulong rotl8 (target_ulong i, int n)
+{
+    return (((uint8_t)i << n) | ((uint8_t)i >> (8 - n)));
+}
 
-static inline uint32_t rotl (uint32_t i, int n)
+static inline target_ulong rotl16 (target_ulong i, int n)
 {
-    return ((i << n) | (i >> (32 - n)));
+    return (((uint16_t)i << n) | ((uint16_t)i >> (16 - n)));
 }
 
+static inline target_ulong rotl32 (target_ulong i, int n)
+{
+    return (((uint32_t)i << n) | ((uint32_t)i >> (32 - n)));
+}
+
+#if defined(TARGET_PPC64)
+static inline target_ulong rotl64 (target_ulong i, int n)
+{
+    return (((uint64_t)i << n) | ((uint64_t)i >> (64 - n)));
+}
+#endif
+
 #if !defined(CONFIG_USER_ONLY)
 #include "softmmu_exec.h"
 #endif /* !defined(CONFIG_USER_ONLY) */
@@ -58,24 +101,16 @@
 void do_raise_exception_err (uint32_t exception, int error_code);
 void do_raise_exception (uint32_t exception);
 
-void do_sraw(void);
+int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong vaddr,
+                          int rw, int access_type, int check_BATs);
 
-void do_fctiw (void);
-void do_fctiwz (void);
-void do_fnmadd (void);
-void do_fnmsub (void);
-void do_fsqrt (void);
-void do_fres (void);
-void do_frsqrte (void);
-void do_fsel (void);
-void do_fcmpu (void);
-void do_fcmpo (void);
+void ppc6xx_tlb_invalidate_all (CPUState *env);
+void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
+                                 int is_code);
+void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
+                       target_ulong pte0, target_ulong pte1);
+void ppc4xx_tlb_invalidate_all (CPUState *env);
 
-void do_check_reservation (void);
-void do_icbi (void);
-void do_tlbia (void);
-void do_tlbie (void);
-
 static inline void env_to_regs(void)
 {
 }
@@ -84,7 +119,7 @@
 {
 }
 
-int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                               int is_user, int is_softmmu);
 
 #endif /* !defined (__PPC_H__) */

Modified: trunk/src/host/qemu-neo1973/target-ppc/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation helpers for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -30,18 +30,19 @@
 
 //#define DEBUG_MMU
 //#define DEBUG_BATS
+//#define DEBUG_SOFTWARE_TLB
 //#define DEBUG_EXCEPTIONS
 //#define FLUSH_ALL_TLBS
 
 /*****************************************************************************/
 /* PowerPC MMU emulation */
 
-#if defined(CONFIG_USER_ONLY) 
-int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+#if defined(CONFIG_USER_ONLY)
+int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                               int is_user, int is_softmmu)
 {
     int exception, error_code;
-    
+
     if (rw == 2) {
         exception = EXCP_ISI;
         error_code = 0;
@@ -55,26 +56,306 @@
     }
     env->exception_index = exception;
     env->error_code = error_code;
+
     return 1;
 }
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+
+target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
 {
     return addr;
 }
 #else
+/* Common routines used by software and hardware TLBs emulation */
+static inline int pte_is_valid (target_ulong pte0)
+{
+    return pte0 & 0x80000000 ? 1 : 0;
+}
+
+static inline void pte_invalidate (target_ulong *pte0)
+{
+    *pte0 &= ~0x80000000;
+}
+
+#define PTE_PTEM_MASK 0x7FFFFFBF
+#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
+
+static int pte_check (mmu_ctx_t *ctx,
+                      target_ulong pte0, target_ulong pte1, int h, int rw)
+{
+    int access, ret;
+
+    access = 0;
+    ret = -1;
+    /* Check validity and table match */
+    if (pte_is_valid(pte0) && (h == ((pte0 >> 6) & 1))) {
+        /* Check vsid & api */
+        if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
+            if (ctx->raddr != (target_ulong)-1) {
+                /* all matches should have equal RPN, WIMG & PP */
+                if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
+                    if (loglevel > 0)
+                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
+                    return -3;
+                }
+            }
+            /* Compute access rights */
+            if (ctx->key == 0) {
+                access = PAGE_READ;
+                if ((pte1 & 0x00000003) != 0x3)
+                    access |= PAGE_WRITE;
+            } else {
+                switch (pte1 & 0x00000003) {
+                case 0x0:
+                    access = 0;
+                    break;
+                case 0x1:
+                case 0x3:
+                    access = PAGE_READ;
+                    break;
+                case 0x2:
+                    access = PAGE_READ | PAGE_WRITE;
+                    break;
+                }
+            }
+            /* Keep the matching PTE informations */
+            ctx->raddr = pte1;
+            ctx->prot = access;
+            if ((rw == 0 && (access & PAGE_READ)) ||
+                (rw == 1 && (access & PAGE_WRITE))) {
+                /* Access granted */
+#if defined (DEBUG_MMU)
+                if (loglevel != 0)
+                    fprintf(logfile, "PTE access granted !\n");
+#endif
+                ret = 0;
+            } else {
+                /* Access right violation */
+#if defined (DEBUG_MMU)
+                if (loglevel != 0)
+                    fprintf(logfile, "PTE access rejected\n");
+#endif
+                ret = -2;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
+                             int ret, int rw)
+{
+    int store = 0;
+
+    /* Update page flags */
+    if (!(*pte1p & 0x00000100)) {
+        /* Update accessed flag */
+        *pte1p |= 0x00000100;
+        store = 1;
+    }
+    if (!(*pte1p & 0x00000080)) {
+        if (rw == 1 && ret == 0) {
+            /* Update changed flag */
+            *pte1p |= 0x00000080;
+            store = 1;
+        } else {
+            /* Force page fault for first write access */
+            ctx->prot &= ~PAGE_WRITE;
+        }
+    }
+
+    return store;
+}
+
+/* Software driven TLB helpers */
+static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
+                              int way, int is_code)
+{
+    int nr;
+
+    /* Select TLB num in a way from address */
+    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
+    /* Select TLB way */
+    nr += env->tlb_per_way * way;
+    /* 6xx have separate TLBs for instructions and data */
+    if (is_code && env->id_tlbs == 1)
+        nr += env->nb_tlb;
+
+    return nr;
+}
+
+void ppc6xx_tlb_invalidate_all (CPUState *env)
+{
+    ppc6xx_tlb_t *tlb;
+    int nr, max;
+
+#if defined (DEBUG_SOFTWARE_TLB) && 0
+    if (loglevel != 0) {
+        fprintf(logfile, "Invalidate all TLBs\n");
+    }
+#endif
+    /* Invalidate all defined software TLB */
+    max = env->nb_tlb;
+    if (env->id_tlbs == 1)
+        max *= 2;
+    for (nr = 0; nr < max; nr++) {
+        tlb = &env->tlb[nr].tlb6;
+#if !defined(FLUSH_ALL_TLBS)
+        tlb_flush_page(env, tlb->EPN);
+#endif
+        pte_invalidate(&tlb->pte0);
+    }
+#if defined(FLUSH_ALL_TLBS)
+    tlb_flush(env, 1);
+#endif
+}
+
+static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
+                                                 target_ulong eaddr,
+                                                 int is_code, int match_epn)
+{
+#if !defined(FLUSH_ALL_TLBS)
+    ppc6xx_tlb_t *tlb;
+    int way, nr;
+
+    /* Invalidate ITLB + DTLB, all ways */
+    for (way = 0; way < env->nb_ways; way++) {
+        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
+        tlb = &env->tlb[nr].tlb6;
+        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
+#if defined (DEBUG_SOFTWARE_TLB)
+            if (loglevel != 0) {
+                fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
+                        nr, env->nb_tlb, eaddr);
+            }
+#endif
+            pte_invalidate(&tlb->pte0);
+            tlb_flush_page(env, tlb->EPN);
+        }
+    }
+#else
+    /* XXX: PowerPC specification say this is valid as well */
+    ppc6xx_tlb_invalidate_all(env);
+#endif
+}
+
+void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
+                                 int is_code)
+{
+    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
+}
+
+void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
+                       target_ulong pte0, target_ulong pte1)
+{
+    ppc6xx_tlb_t *tlb;
+    int nr;
+
+    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
+    tlb = &env->tlb[nr].tlb6;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX 
+                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
+    }
+#endif
+    /* Invalidate any pending reference in Qemu for this virtual address */
+    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
+    tlb->pte0 = pte0;
+    tlb->pte1 = pte1;
+    tlb->EPN = EPN;
+    /* Store last way for LRU mechanism */
+    env->last_way = way;
+}
+
+static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
+                             target_ulong eaddr, int rw, int access_type)
+{
+    ppc6xx_tlb_t *tlb;
+    int nr, best, way;
+    int ret;
+
+    best = -1;
+    ret = -1; /* No TLB found */
+    for (way = 0; way < env->nb_ways; way++) {
+        nr = ppc6xx_tlb_getnum(env, eaddr, way,
+                               access_type == ACCESS_CODE ? 1 : 0);
+        tlb = &env->tlb[nr].tlb6;
+        /* This test "emulates" the PTE index match for hardware TLBs */
+        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
+#if defined (DEBUG_SOFTWARE_TLB)
+            if (loglevel != 0) {
+                fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
+                        "] <> " ADDRX "\n",
+                        nr, env->nb_tlb,
+                        pte_is_valid(tlb->pte0) ? "valid" : "inval",
+                        tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
+            }
+#endif
+            continue;
+        }
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel != 0) {
+            fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
+                    " %c %c\n",
+                    nr, env->nb_tlb,
+                    pte_is_valid(tlb->pte0) ? "valid" : "inval",
+                    tlb->EPN, eaddr, tlb->pte1,
+                    rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
+        }
+#endif
+        switch (pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
+        case -3:
+            /* TLB inconsistency */
+            return -1;
+        case -2:
+            /* Access violation */
+            ret = -2;
+            best = nr;
+            break;
+        case -1:
+        default:
+            /* No match */
+            break;
+        case 0:
+            /* access granted */
+            /* XXX: we should go on looping to check all TLBs consistency
+             *      but we can speed-up the whole thing as the
+             *      result would be undefined if TLBs are not consistent.
+             */
+            ret = 0;
+            best = nr;
+            goto done;
+        }
+    }
+    if (best != -1) {
+    done:
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel != 0) {
+            fprintf(logfile, "found TLB at addr 0x%08lx prot=0x%01x ret=%d\n",
+                    ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
+        }
+#endif
+        /* Update page flags */
+        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
+    }
+
+    return ret;
+}
+
 /* Perform BAT hit & translation */
-static int get_bat (CPUState *env, uint32_t *real, int *prot,
-                    uint32_t virtual, int rw, int type)
+static int get_bat (CPUState *env, mmu_ctx_t *ctx,
+                    target_ulong virtual, int rw, int type)
 {
-    uint32_t *BATlt, *BATut, *BATu, *BATl;
-    uint32_t base, BEPIl, BEPIu, bl;
+    target_ulong *BATlt, *BATut, *BATu, *BATl;
+    target_ulong base, BEPIl, BEPIu, bl;
     int i;
     int ret = -1;
 
 #if defined (DEBUG_BATS)
-    if (loglevel > 0) {
-        fprintf(logfile, "%s: %cBAT v 0x%08x\n", __func__,
-               type == ACCESS_CODE ? 'I' : 'D', virtual);
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: %cBAT v 0x" ADDRX "\n", __func__,
+                type == ACCESS_CODE ? 'I' : 'D', virtual);
     }
 #endif
     switch (type) {
@@ -88,9 +369,9 @@
         break;
     }
 #if defined (DEBUG_BATS)
-    if (loglevel > 0) {
-        fprintf(logfile, "%s...: %cBAT v 0x%08x\n", __func__,
-               type == ACCESS_CODE ? 'I' : 'D', virtual);
+    if (loglevel != 0) {
+        fprintf(logfile, "%s...: %cBAT v 0x" ADDRX "\n", __func__,
+                type == ACCESS_CODE ? 'I' : 'D', virtual);
     }
 #endif
     base = virtual & 0xFFFC0000;
@@ -101,8 +382,9 @@
         BEPIl = *BATu & 0x0FFE0000;
         bl = (*BATu & 0x00001FFC) << 15;
 #if defined (DEBUG_BATS)
-        if (loglevel > 0) {
-            fprintf(logfile, "%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x\n",
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX 
+                    " BATl 0x" ADDRX "\n",
                     __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
                     *BATu, *BATl);
         }
@@ -113,18 +395,19 @@
             if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
                 (msr_pr == 1 && (*BATu & 0x00000001))) {
                 /* Get physical address */
-                *real = (*BATl & 0xF0000000) |
+                ctx->raddr = (*BATl & 0xF0000000) |
                     ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
                     (virtual & 0x0001F000);
                 if (*BATl & 0x00000001)
-                    *prot = PAGE_READ;
+                    ctx->prot = PAGE_READ;
                 if (*BATl & 0x00000002)
-                    *prot = PAGE_WRITE | PAGE_READ;
+                    ctx->prot = PAGE_WRITE | PAGE_READ;
 #if defined (DEBUG_BATS)
-                if (loglevel > 0) {
-                    fprintf(logfile, "BAT %d match: r 0x%08x prot=%c%c\n",
-                            i, *real, *prot & PAGE_READ ? 'R' : '-',
-                            *prot & PAGE_WRITE ? 'W' : '-');
+                if (loglevel != 0) {
+                    fprintf(logfile, "BAT %d match: r 0x" PADDRX
+                            " prot=%c%c\n",
+                            i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
+                            ctx->prot & PAGE_WRITE ? 'W' : '-');
                 }
 #endif
                 ret = 0;
@@ -134,17 +417,20 @@
     }
     if (ret < 0) {
 #if defined (DEBUG_BATS)
-        printf("no BAT match for 0x%08x:\n", virtual);
-        for (i = 0; i < 4; i++) {
-            BATu = &BATut[i];
-            BATl = &BATlt[i];
-            BEPIu = *BATu & 0xF0000000;
-            BEPIl = *BATu & 0x0FFE0000;
-            bl = (*BATu & 0x00001FFC) << 15;
-            printf("%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x \n\t"
-                   "0x%08x 0x%08x 0x%08x\n",
-                   __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
-                   *BATu, *BATl, BEPIu, BEPIl, bl);
+        if (loglevel != 0) {
+            fprintf(logfile, "no BAT match for 0x" ADDRX ":\n", virtual);
+            for (i = 0; i < 4; i++) {
+                BATu = &BATut[i];
+                BATl = &BATlt[i];
+                BEPIu = *BATu & 0xF0000000;
+                BEPIl = *BATu & 0x0FFE0000;
+                bl = (*BATu & 0x00001FFC) << 15;
+                fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
+                        " BATl 0x" ADDRX " \n\t"
+                        "0x" ADDRX " 0x" ADDRX " 0x" ADDRX "\n",
+                        __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
+                        *BATu, *BATl, BEPIu, BEPIl, bl);
+            }
         }
 #endif
     }
@@ -153,189 +439,156 @@
 }
 
 /* PTE table lookup */
-static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va,
-                     int h, int key, int rw)
+static int find_pte (mmu_ctx_t *ctx, int h, int rw)
 {
-    uint32_t pte0, pte1, keep = 0, access = 0;
-    int i, good = -1, store = 0;
-    int ret = -1; /* No entry found */
+    target_ulong base, pte0, pte1;
+    int i, good = -1;
+    int ret;
 
+    ret = -1; /* No entry found */
+    base = ctx->pg_addr[h];
     for (i = 0; i < 8; i++) {
         pte0 = ldl_phys(base + (i * 8));
         pte1 =  ldl_phys(base + (i * 8) + 4);
 #if defined (DEBUG_MMU)
         if (loglevel > 0) {
-	    fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x "
-		    "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1,
-		    pte0 >> 31, h, (pte0 >> 6) & 1, va);
-	}
+            fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX 
+                    " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
+                    base + (i * 8), pte0, pte1,
+                    pte0 >> 31, h, (pte0 >> 6) & 1, ctx->ptem);
+        }
 #endif
-        /* Check validity and table match */
-        if (pte0 & 0x80000000 && (h == ((pte0 >> 6) & 1))) {
-            /* Check vsid & api */
-            if ((pte0 & 0x7FFFFFBF) == va) {
-                if (good == -1) {
-                    good = i;
-                    keep = pte1;
-                } else {
-                    /* All matches should have equal RPN, WIMG & PP */
-                    if ((keep & 0xFFFFF07B) != (pte1 & 0xFFFFF07B)) {
-			if (loglevel > 0)
-			    fprintf(logfile, "Bad RPN/WIMG/PP\n");
-                        return -1;
-                    }
-                }
-                /* Check access rights */
-                if (key == 0) {
-                    access = PAGE_READ;
-                    if ((pte1 & 0x00000003) != 0x3)
-                        access |= PAGE_WRITE;
-                } else {
-                    switch (pte1 & 0x00000003) {
-                    case 0x0:
-                        access = 0;
-                        break;
-                    case 0x1:
-                    case 0x3:
-                        access = PAGE_READ;
-                        break;
-                    case 0x2:
-                        access = PAGE_READ | PAGE_WRITE;
-                        break;
-                    }
-                }
-                if (ret < 0) {
-		    if ((rw == 0 && (access & PAGE_READ)) ||
-			(rw == 1 && (access & PAGE_WRITE))) {
-#if defined (DEBUG_MMU)
-			if (loglevel > 0)
-			    fprintf(logfile, "PTE access granted !\n");
-#endif
-                        good = i;
-                        keep = pte1;
-                        ret = 0;
-		    } else {
-			/* Access right violation */
-                        ret = -2;
-#if defined (DEBUG_MMU)
-			if (loglevel > 0)
-			    fprintf(logfile, "PTE access rejected\n");
-#endif
-                    }
-		    *prot = access;
-		}
-            }
+        switch (pte_check(ctx, pte0, pte1, h, rw)) {
+        case -3:
+            /* PTE inconsistency */
+            return -1;
+        case -2:
+            /* Access violation */
+            ret = -2;
+            good = i;
+            break;
+        case -1:
+        default:
+            /* No PTE match */
+            break;
+        case 0:
+            /* access granted */
+            /* XXX: we should go on looping to check all PTEs consistency
+             *      but if we can speed-up the whole thing as the
+             *      result would be undefined if PTEs are not consistent.
+             */
+            ret = 0;
+            good = i;
+            goto done;
         }
     }
     if (good != -1) {
-        *RPN = keep & 0xFFFFF000;
+    done:
 #if defined (DEBUG_MMU)
-        if (loglevel > 0) {
-	    fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n",
-               *RPN, *prot, ret);
-	}
+        if (loglevel != 0) {
+            fprintf(logfile, "found PTE at addr 0x" PADDRX " prot=0x%01x "
+                    "ret=%d\n",
+                    ctx->raddr, ctx->prot, ret);
+        }
 #endif
         /* Update page flags */
-        if (!(keep & 0x00000100)) {
-	    /* Access flag */
-            keep |= 0x00000100;
-            store = 1;
-        }
-        if (!(keep & 0x00000080)) {
-	    if (rw && ret == 0) {
-		/* Change flag */
-                keep |= 0x00000080;
-                store = 1;
-	    } else {
-		/* Force page fault for first write access */
-		*prot &= ~PAGE_WRITE;
-            }
-        }
-        if (store) {
-	    stl_phys_notdirty(base + (good * 8) + 4, keep);
-	}
+        pte1 = ctx->raddr;
+        if (pte_update_flags(ctx, &pte1, ret, rw) == 1)
+            stl_phys_notdirty(base + (good * 8) + 4, pte1);
     }
 
     return ret;
 }
 
-static inline uint32_t get_pgaddr (uint32_t sdr1, uint32_t hash, uint32_t mask)
+static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
+                                             target_phys_addr_t hash,
+                                             target_phys_addr_t mask)
 {
     return (sdr1 & 0xFFFF0000) | (hash & mask);
 }
 
 /* Perform segment based translation */
-static int get_segment (CPUState *env, uint32_t *real, int *prot,
-                        uint32_t virtual, int rw, int type)
+static int get_segment (CPUState *env, mmu_ctx_t *ctx,
+                        target_ulong eaddr, int rw, int type)
 {
-    uint32_t pg_addr, sdr, ptem, vsid, pgidx;
-    uint32_t hash, mask;
-    uint32_t sr;
-    int key;
+    target_phys_addr_t sdr, hash, mask;
+    target_ulong sr, vsid, pgidx;
     int ret = -1, ret2;
 
-    sr = env->sr[virtual >> 28];
+    sr = env->sr[eaddr >> 28];
 #if defined (DEBUG_MMU)
     if (loglevel > 0) {
-	fprintf(logfile, "Check segment v=0x%08x %d 0x%08x nip=0x%08x "
-		"lr=0x%08x ir=%d dr=%d pr=%d %d t=%d\n",
-		virtual, virtual >> 28, sr, env->nip,
-		env->lr, msr_ir, msr_dr, msr_pr, rw, type);
+        fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX " nip=0x"
+                ADDRX " lr=0x" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
+                eaddr, eaddr >> 28, sr, env->nip,
+                env->lr, msr_ir, msr_dr, msr_pr, rw, type);
     }
 #endif
-    key = (((sr & 0x20000000) && msr_pr == 1) ||
-        ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
+    ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
+                ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
     if ((sr & 0x80000000) == 0) {
 #if defined (DEBUG_MMU)
-    if (loglevel > 0) 
-	    fprintf(logfile, "pte segment: key=%d n=0x%08x\n",
-		    key, sr & 0x10000000);
+        if (loglevel > 0) 
+            fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
+                    ctx->key, sr & 0x10000000);
 #endif
         /* Check if instruction fetch is allowed, if needed */
         if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
             /* Page address translation */
+            pgidx = (eaddr >> TARGET_PAGE_BITS) & 0xFFFF;
             vsid = sr & 0x00FFFFFF;
-            pgidx = (virtual >> 12) & 0xFFFF;
+            hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
+            /* Primary table address */
             sdr = env->sdr1;
-            hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
             mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
-            pg_addr = get_pgaddr(sdr, hash, mask);
-            ptem = (vsid << 7) | (pgidx >> 10);
+            ctx->pg_addr[0] = get_pgaddr(sdr, hash, mask);
+            /* Secondary table address */
+            hash = (~hash) & 0x01FFFFC0;
+            ctx->pg_addr[1] = get_pgaddr(sdr, hash, mask);
+            ctx->ptem = (vsid << 7) | (pgidx >> 10);
+            /* Initialize real address with an invalid value */
+            ctx->raddr = (target_ulong)-1;
+            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+                /* Software TLB search */
+                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
+            } else {
 #if defined (DEBUG_MMU)
-	    if (loglevel > 0) {
-		fprintf(logfile, "0 sdr1=0x%08x vsid=0x%06x api=0x%04x "
-			"hash=0x%07x pg_addr=0x%08x\n", sdr, vsid, pgidx, hash,
-			pg_addr);
-	    }
+                if (loglevel != 0) {
+                    fprintf(logfile, "0 sdr1=0x" PADDRX " vsid=0x%06x "
+                            "api=0x%04x hash=0x%07x pg_addr=0x" PADDRX "\n",
+                            sdr, (uint32_t)vsid, (uint32_t)pgidx,
+                            (uint32_t)hash, ctx->pg_addr[0]);
+                }
 #endif
-            /* Primary table lookup */
-            ret = find_pte(real, prot, pg_addr, ptem, 0, key, rw);
-            if (ret < 0) {
-                /* Secondary table lookup */
-                hash = (~hash) & 0x01FFFFC0;
-                pg_addr = get_pgaddr(sdr, hash, mask);
+                /* Primary table lookup */
+                ret = find_pte(ctx, 0, rw);
+                if (ret < 0) {
+                    /* Secondary table lookup */
 #if defined (DEBUG_MMU)
-		if (virtual != 0xEFFFFFFF && loglevel > 0) {
-		    fprintf(logfile, "1 sdr1=0x%08x vsid=0x%06x api=0x%04x "
-			    "hash=0x%05x pg_addr=0x%08x\n", sdr, vsid, pgidx,
-			    hash, pg_addr);
-		}
+                    if (eaddr != 0xEFFFFFFF && loglevel != 0) {
+                        fprintf(logfile,
+                                "1 sdr1=0x" PADDRX " vsid=0x%06x api=0x%04x "
+                                "hash=0x%05x pg_addr=0x" PADDRX "\n",
+                                sdr, (uint32_t)vsid, (uint32_t)pgidx,
+                                (uint32_t)hash, ctx->pg_addr[1]);
+                    }
 #endif
-                ret2 = find_pte(real, prot, pg_addr, ptem, 1, key, rw);
-                if (ret2 != -1)
-                    ret = ret2;
+                    ret2 = find_pte(ctx, 1, rw);
+                    if (ret2 != -1)
+                        ret = ret2;
+                }
             }
         } else {
 #if defined (DEBUG_MMU)
-	    if (loglevel > 0)
-		fprintf(logfile, "No access allowed\n");
+            if (loglevel != 0)
+                fprintf(logfile, "No access allowed\n");
 #endif
-	    ret = -3;
+            ret = -3;
         }
     } else {
 #if defined (DEBUG_MMU)
-        if (loglevel > 0)
-	    fprintf(logfile, "direct store...\n");
+        if (loglevel != 0)
+            fprintf(logfile, "direct store...\n");
 #endif
         /* Direct-store segment : absolutely *BUGGY* for now */
         switch (type) {
@@ -356,7 +609,7 @@
             /* Should make the instruction do no-op.
              * As it already do no-op, it's quite easy :-)
              */
-            *real = virtual;
+            ctx->raddr = eaddr;
             return 0;
         case ACCESS_EXT:
             /* eciwx or ecowx */
@@ -366,12 +619,10 @@
                 fprintf(logfile, "ERROR: instruction should not need "
                         "address translation\n");
             }
-            printf("ERROR: instruction should not need "
-                   "address translation\n");
             return -4;
         }
-        if ((rw == 1 || key != 1) && (rw == 0 || key != 0)) {
-            *real = virtual;
+        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
+            ctx->raddr = eaddr;
             ret = 2;
         } else {
             ret = -2;
@@ -381,54 +632,309 @@
     return ret;
 }
 
-static int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
-                                 uint32_t address, int rw, int access_type)
+/* Generic TLB check function for embedded PowerPC implementations */
+static int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
+                             target_phys_addr_t *raddrp,
+                             target_ulong address, int i)
 {
+    target_ulong mask;
+
+    /* Check valid flag */
+    if (!(tlb->prot & PAGE_VALID)) {
+        if (loglevel != 0)
+            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
+        return -1;
+    }
+    mask = ~(tlb->size - 1);
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
+                ADDRX " " ADDRX " %d\n",
+                __func__, i, address, (int)env->spr[SPR_40x_PID],
+                tlb->EPN, mask, (int)tlb->PID);
+    }
+    /* Check PID */
+    if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
+        return -1;
+    /* Check effective address */
+    if ((address & mask) != tlb->EPN)
+        return -1;
+    *raddrp = (tlb->RPN & mask) | (address & ~mask);
+
+    return 0;
+}
+
+/* Generic TLB search function for PowerPC embedded implementations */
+int ppcemb_tlb_search (CPUState *env, target_ulong address)
+{
+    ppcemb_tlb_t *tlb;
+    target_phys_addr_t raddr;
+    int i, ret;
+
+    /* Default return value is no match */
+    ret = -1;
+    for (i = 0; i < 64; i++) {
+        tlb = &env->tlb[i].tlbe;
+        if (ppcemb_tlb_check(env, tlb, &raddr, address, i) == 0) {
+            ret = i;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+/* Helpers specific to PowerPC 40x implementations */
+void ppc4xx_tlb_invalidate_all (CPUState *env)
+{
+    ppcemb_tlb_t *tlb;
+    int i;
+
+    for (i = 0; i < env->nb_tlb; i++) {
+        tlb = &env->tlb[i].tlbe;
+        if (tlb->prot & PAGE_VALID) {
+#if 0 // XXX: TLB have variable sizes then we flush all Qemu TLB.
+            end = tlb->EPN + tlb->size;
+            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
+                tlb_flush_page(env, page);
+#endif
+            tlb->prot &= ~PAGE_VALID;
+        }
+    }
+    tlb_flush(env, 1);
+}
+
+int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
+                                 target_ulong address, int rw, int access_type)
+{
+    ppcemb_tlb_t *tlb;
+    target_phys_addr_t raddr;
+    int i, ret, zsel, zpr;
+            
+    ret = -1;
+    raddr = -1;
+    for (i = 0; i < env->nb_tlb; i++) {
+        tlb = &env->tlb[i].tlbe;
+        if (ppcemb_tlb_check(env, tlb, &raddr, address, i) < 0)
+            continue;
+        zsel = (tlb->attr >> 4) & 0xF;
+        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
+                    __func__, i, zsel, zpr, rw, tlb->attr);
+        }
+        if (access_type == ACCESS_CODE) {
+            /* Check execute enable bit */
+            switch (zpr) {
+            case 0x2:
+                if (msr_pr)
+                    goto check_exec_perm;
+                goto exec_granted;
+            case 0x0:
+                if (msr_pr) {
+                    ctx->prot = 0;
+                    ret = -3;
+                    break;
+                }
+                /* No break here */
+            case 0x1:
+            check_exec_perm:
+                /* Check from TLB entry */
+                if (!(tlb->prot & PAGE_EXEC)) {
+                    ret = -3;
+                } else {
+                    if (tlb->prot & PAGE_WRITE) {
+                        ctx->prot = PAGE_READ | PAGE_WRITE;
+                    } else {
+                        ctx->prot = PAGE_READ;
+                    }
+                    ret = 0;
+                }
+                break;
+            case 0x3:
+            exec_granted:
+                /* All accesses granted */
+                ctx->prot = PAGE_READ | PAGE_WRITE;
+                ret = 0;
+                break;
+            }
+        } else {
+            switch (zpr) {
+            case 0x2:
+                if (msr_pr)
+                    goto check_rw_perm;
+                goto rw_granted;
+            case 0x0:
+                if (msr_pr) {
+                    ctx->prot = 0;
+                    ret = -2;
+                    break;
+                }
+                /* No break here */
+            case 0x1:
+            check_rw_perm:
+                /* Check from TLB entry */
+                /* Check write protection bit */
+                if (tlb->prot & PAGE_WRITE) {
+                    ctx->prot = PAGE_READ | PAGE_WRITE;
+                    ret = 0;
+                } else {
+                    ctx->prot = PAGE_READ;
+                    if (rw)
+                        ret = -2;
+                    else
+                        ret = 0;
+                }
+                break;
+            case 0x3:
+            rw_granted:
+                /* All accesses granted */
+                ctx->prot = PAGE_READ | PAGE_WRITE;
+                ret = 0;
+                break;
+            }
+        }
+        if (ret >= 0) {
+            ctx->raddr = raddr;
+            if (loglevel != 0) {
+                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
+                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
+                        ret);
+            }
+            return 0;
+        }
+    }
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: access refused " ADDRX " => " REGX
+                " %d %d\n", __func__, address, raddr, ctx->prot,
+                ret);
+    }
+    
+    return ret;
+}
+
+void store_40x_sler (CPUPPCState *env, uint32_t val)
+{
+    /* XXX: TO BE FIXED */
+    if (val != 0x00000000) {
+        cpu_abort(env, "Little-endian regions are not supported by now\n");
+    }
+    env->spr[SPR_405_SLER] = val;
+}
+
+static int check_physical (CPUState *env, mmu_ctx_t *ctx,
+                           target_ulong eaddr, int rw)
+{
+    int in_plb, ret;
+        
+    ctx->raddr = eaddr;
+    ctx->prot = PAGE_READ;
+    ret = 0;
+    if (unlikely(msr_pe != 0 && PPC_MMU(env) == PPC_FLAGS_MMU_403)) {
+        /* 403 family add some particular protections,
+         * using PBL/PBU registers for accesses with no translation.
+         */
+        in_plb =
+            /* Check PLB validity */
+            (env->pb[0] < env->pb[1] &&
+             /* and address in plb area */
+             eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
+            (env->pb[2] < env->pb[3] &&
+             eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
+        if (in_plb ^ msr_px) {
+            /* Access in protected area */
+            if (rw == 1) {
+                /* Access is not allowed */
+                ret = -2;
+            }
+        } else {
+            /* Read-write access is allowed */
+            ctx->prot |= PAGE_WRITE;
+        }
+    } else {
+        ctx->prot |= PAGE_WRITE;
+    }
+
+    return ret;
+}
+
+int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
+                          int rw, int access_type, int check_BATs)
+{
     int ret;
 #if 0
-    if (loglevel > 0) {
+    if (loglevel != 0) {
         fprintf(logfile, "%s\n", __func__);
     }
-#endif    
+#endif
     if ((access_type == ACCESS_CODE && msr_ir == 0) ||
         (access_type != ACCESS_CODE && msr_dr == 0)) {
         /* No address translation */
-        *physical = address & ~0xFFF;
-        *prot = PAGE_READ | PAGE_WRITE;
-        ret = 0;
+        ret = check_physical(env, ctx, eaddr, rw);
     } else {
-        /* Try to find a BAT */
-        ret = get_bat(env, physical, prot, address, rw, access_type);
-        if (ret < 0) {
-            /* We didn't match any BAT entry */
-            ret = get_segment(env, physical, prot, address, rw, access_type);
+        ret = -1;
+        switch (PPC_MMU(env)) {
+        case PPC_FLAGS_MMU_32B:
+        case PPC_FLAGS_MMU_SOFT_6xx:
+            /* Try to find a BAT */
+            if (check_BATs)
+                ret = get_bat(env, ctx, eaddr, rw, access_type);
+            /* No break here */
+#if defined(TARGET_PPC64)
+        case PPC_FLAGS_MMU_64B:
+        case PPC_FLAGS_MMU_64BRIDGE:
+#endif
+            if (ret < 0) {
+                /* We didn't match any BAT entry or don't have BATs */
+                ret = get_segment(env, ctx, eaddr, rw, access_type);
+            }
+            break;
+        case PPC_FLAGS_MMU_SOFT_4xx:
+        case PPC_FLAGS_MMU_403:
+            ret = mmu4xx_get_physical_address(env, ctx, eaddr,
+                                              rw, access_type);
+            break;
+        case PPC_FLAGS_MMU_601:
+            /* XXX: TODO */
+            cpu_abort(env, "601 MMU model not implemented\n");
+            return -1;
+        case PPC_FLAGS_MMU_BOOKE:
+            /* XXX: TODO */
+            cpu_abort(env, "BookeE MMU model not implemented\n");
+            return -1;
+        case PPC_FLAGS_MMU_BOOKE_FSL:
+            /* XXX: TODO */
+            cpu_abort(env, "BookE FSL MMU model not implemented\n");
+            return -1;
+        default:
+            cpu_abort(env, "Unknown or invalid MMU model\n");
+            return -1;
         }
     }
 #if 0
-    if (loglevel > 0) {
-        fprintf(logfile, "%s address %08x => %08x\n",
-		__func__, address, *physical);
+    if (loglevel != 0) {
+        fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
+                __func__, eaddr, ret, ctx->raddr);
     }
-#endif    
+#endif
+
     return ret;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
 {
-    uint32_t phys_addr;
-    int prot;
+    mmu_ctx_t ctx;
 
-    if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
+    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
         return -1;
-    return phys_addr;
+
+    return ctx.raddr & TARGET_PAGE_MASK;
 }
 
 /* Perform address translation */
-int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
+int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                               int is_user, int is_softmmu)
 {
-    uint32_t physical;
-    int prot;
+    mmu_ctx_t ctx;
     int exception = 0, error_code = 0;
     int access_type;
     int ret = 0;
@@ -444,35 +950,71 @@
         access_type = ACCESS_INT;
         //        access_type = env->access_type;
     }
-    if (env->user_mode_only) {
-        /* user mode only emulation */
-        ret = -2;
-        goto do_fault;
-    }
-    ret = get_physical_address(env, &physical, &prot,
-                               address, rw, access_type);
+    ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
     if (ret == 0) {
-	ret = tlb_set_page(env, address & ~0xFFF, physical, prot,
-			   is_user, is_softmmu);
+        ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
+                           ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
+                           is_user, is_softmmu);
     } else if (ret < 0) {
-    do_fault:
 #if defined (DEBUG_MMU)
-	if (loglevel > 0)
-	    cpu_dump_state(env, logfile, fprintf, 0);
+        if (loglevel != 0)
+            cpu_dump_state(env, logfile, fprintf, 0);
 #endif
         if (access_type == ACCESS_CODE) {
             exception = EXCP_ISI;
             switch (ret) {
             case -1:
-                /* No matches in page tables */
-                error_code = 0x40000000;
+                /* No matches in page tables or TLB */
+                switch (PPC_MMU(env)) {
+                case PPC_FLAGS_MMU_SOFT_6xx:
+                    exception = EXCP_I_TLBMISS;
+                    env->spr[SPR_IMISS] = address;
+                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
+                    error_code = 1 << 18;
+                    goto tlb_miss;
+                case PPC_FLAGS_MMU_SOFT_4xx:
+                case PPC_FLAGS_MMU_403:
+                    exception = EXCP_40x_ITLBMISS;
+                    error_code = 0;
+                    env->spr[SPR_40x_DEAR] = address;
+                    env->spr[SPR_40x_ESR] = 0x00000000;
+                    break;
+                case PPC_FLAGS_MMU_32B:
+                    error_code = 0x40000000;
+                    break;
+#if defined(TARGET_PPC64)
+                case PPC_FLAGS_MMU_64B:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_64BRIDGE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+#endif
+                case PPC_FLAGS_MMU_601:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE_FSL:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                default:
+                    cpu_abort(env, "Unknown or invalid MMU model\n");
+                    return -1;
+                }
                 break;
             case -2:
                 /* Access rights violation */
                 error_code = 0x08000000;
                 break;
             case -3:
-		/* No execute protection violation */
+                /* No execute protection violation */
                 error_code = 0x10000000;
                 break;
             case -4:
@@ -490,8 +1032,63 @@
             exception = EXCP_DSI;
             switch (ret) {
             case -1:
-                /* No matches in page tables */
-                error_code = 0x40000000;
+                /* No matches in page tables or TLB */
+                switch (PPC_MMU(env)) {
+                case PPC_FLAGS_MMU_SOFT_6xx:
+                    if (rw == 1) {
+                        exception = EXCP_DS_TLBMISS;
+                        error_code = 1 << 16;
+                    } else {
+                        exception = EXCP_DL_TLBMISS;
+                        error_code = 0;
+                    }
+                    env->spr[SPR_DMISS] = address;
+                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
+                tlb_miss:
+                    error_code |= ctx.key << 19;
+                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
+                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
+                    /* Do not alter DAR nor DSISR */
+                    goto out;
+                case PPC_FLAGS_MMU_SOFT_4xx:
+                case PPC_FLAGS_MMU_403:
+                    exception = EXCP_40x_DTLBMISS;
+                    error_code = 0;
+                    env->spr[SPR_40x_DEAR] = address;
+                    if (rw)
+                        env->spr[SPR_40x_ESR] = 0x00800000;
+                    else
+                        env->spr[SPR_40x_ESR] = 0x00000000;
+                    break;
+                case PPC_FLAGS_MMU_32B:
+                    error_code = 0x40000000;
+                    break;
+#if defined(TARGET_PPC64)
+                case PPC_FLAGS_MMU_64B:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_64BRIDGE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+#endif
+                case PPC_FLAGS_MMU_601:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                case PPC_FLAGS_MMU_BOOKE_FSL:
+                    /* XXX: TODO */
+                    cpu_abort(env, "MMU model not implemented\n");
+                    return -1;
+                default:
+                    cpu_abort(env, "Unknown or invalid MMU model\n");
+                    return -1;
+                }
                 break;
             case -2:
                 /* Access rights violation */
@@ -514,7 +1111,7 @@
                     error_code = 0x04100000;
                     break;
                 default:
-		    printf("DSI: invalid exception (%d)\n", ret);
+                    printf("DSI: invalid exception (%d)\n", ret);
                     exception = EXCP_PROGRAM;
                     error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
                     break;
@@ -528,10 +1125,11 @@
             }
             if (exception == EXCP_DSI && rw == 1)
                 error_code |= 0x02000000;
-	    /* Store fault address */
-	    env->spr[SPR_DAR] = address;
+            /* Store fault address */
+            env->spr[SPR_DAR] = address;
             env->spr[SPR_DSISR] = error_code;
         }
+    out:
 #if 0
         printf("%s: set exception to %d %02x\n",
                __func__, exception, error_code);
@@ -540,9 +1138,9 @@
         env->error_code = error_code;
         ret = 1;
     }
+
     return ret;
 }
-#endif
 
 /*****************************************************************************/
 /* BATs management */
@@ -551,11 +1149,14 @@
                                       target_ulong BATu, target_ulong mask)
 {
     target_ulong base, end, page;
+
     base = BATu & ~0x0001FFFF;
     end = base + mask + 0x00020000;
 #if defined (DEBUG_BATS)
-    if (loglevel != 0)
-        fprintf(logfile, "Flush BAT from %08x to %08x (%08x)\n", base, end, mask);
+    if (loglevel != 0) {
+        fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
+                base, end, mask);
+    }
 #endif
     for (page = base; page != end; page += TARGET_PAGE_SIZE)
         tlb_flush_page(env, page);
@@ -571,9 +1172,8 @@
 {
 #if defined (DEBUG_BATS)
     if (loglevel != 0) {
-        fprintf(logfile, "Set %cBAT%d%c to 0x%08lx (0x%08lx)\n",
-                ID, nr, ul == 0 ? 'u' : 'l', (unsigned long)value,
-                (unsigned long)env->nip);
+        fprintf(logfile, "Set %cBAT%d%c to 0x" ADDRX " (0x" ADDRX ")\n",
+                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
     }
 #endif
 }
@@ -608,8 +1208,7 @@
             (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
 #if !defined(FLUSH_ALL_TLBS)
         do_invalidate_BAT(env, env->IBAT[0][nr], mask);
-#endif
-#if defined(FLUSH_ALL_TLBS)
+#else
         tlb_flush(env, 1);
 #endif
     }
@@ -663,23 +1262,36 @@
     env->DBAT[1][nr] = value;
 }
 
-static inline void invalidate_all_tlbs (CPUPPCState *env)
+
+/*****************************************************************************/
+/* TLB management */
+void ppc_tlb_invalidate_all (CPUPPCState *env)
 {
-    /* XXX: this needs to be completed for sotware driven TLB support */
-    tlb_flush(env, 1);
+    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+        ppc6xx_tlb_invalidate_all(env);
+    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+        ppc4xx_tlb_invalidate_all(env);
+    } else {
+        tlb_flush(env, 1);
+    }
 }
 
 /*****************************************************************************/
 /* Special registers manipulation */
-target_ulong do_load_nip (CPUPPCState *env)
+#if defined(TARGET_PPC64)
+target_ulong ppc_load_asr (CPUPPCState *env)
 {
-    return env->nip;
+    return env->asr;
 }
 
-void do_store_nip (CPUPPCState *env, target_ulong value)
+void ppc_store_asr (CPUPPCState *env, target_ulong value)
 {
-    env->nip = value;
+    if (env->asr != value) {
+        env->asr = value;
+        tlb_flush(env, 1);
+    }
 }
+#endif
 
 target_ulong do_load_sdr1 (CPUPPCState *env)
 {
@@ -690,12 +1302,12 @@
 {
 #if defined (DEBUG_MMU)
     if (loglevel != 0) {
-        fprintf(logfile, "%s: 0x%08lx\n", __func__, (unsigned long)value);
+        fprintf(logfile, "%s: 0x" ADDRX "\n", __func__, value);
     }
 #endif
     if (env->sdr1 != value) {
         env->sdr1 = value;
-        invalidate_all_tlbs(env);
+        tlb_flush(env, 1);
     }
 }
 
@@ -708,8 +1320,8 @@
 {
 #if defined (DEBUG_MMU)
     if (loglevel != 0) {
-        fprintf(logfile, "%s: reg=%d 0x%08lx %08lx\n",
-                __func__, srnum, (unsigned long)value, env->sr[srnum]);
+        fprintf(logfile, "%s: reg=%d 0x" ADDRX " " ADDRX "\n",
+                __func__, srnum, value, env->sr[srnum]);
     }
 #endif
     if (env->sr[srnum] != value) {
@@ -724,35 +1336,14 @@
                 tlb_flush_page(env, page);
         }
 #else
-        invalidate_all_tlbs(env);
+        tlb_flush(env, 1);
 #endif
     }
 }
+#endif /* !defined (CONFIG_USER_ONLY) */
 
-uint32_t do_load_cr (CPUPPCState *env)
+uint32_t ppc_load_xer (CPUPPCState *env)
 {
-    return (env->crf[0] << 28) |
-        (env->crf[1] << 24) |
-        (env->crf[2] << 20) |
-        (env->crf[3] << 16) |
-        (env->crf[4] << 12) |
-        (env->crf[5] << 8) |
-        (env->crf[6] << 4) |
-        (env->crf[7] << 0);
-}
-
-void do_store_cr (CPUPPCState *env, uint32_t value, uint32_t mask)
-{
-    int i, sh;
-
-    for (i = 0, sh = 7; i < 8; i++, sh --) {
-        if (mask & (1 << sh))
-            env->crf[i] = (value >> (sh * 4)) & 0xFUL;
-    }
-}
-
-uint32_t do_load_xer (CPUPPCState *env)
-{
     return (xer_so << XER_SO) |
         (xer_ov << XER_OV) |
         (xer_ca << XER_CA) |
@@ -760,49 +1351,67 @@
         (xer_cmp << XER_CMP);
 }
 
-void do_store_xer (CPUPPCState *env, uint32_t value)
+void ppc_store_xer (CPUPPCState *env, uint32_t value)
 {
     xer_so = (value >> XER_SO) & 0x01;
     xer_ov = (value >> XER_OV) & 0x01;
     xer_ca = (value >> XER_CA) & 0x01;
     xer_cmp = (value >> XER_CMP) & 0xFF;
-    xer_bc = (value >> XER_BC) & 0x3F;
+    xer_bc = (value >> XER_BC) & 0x7F;
 }
 
-target_ulong do_load_msr (CPUPPCState *env)
+/* Swap temporary saved registers with GPRs */
+static inline void swap_gpr_tgpr (CPUPPCState *env)
 {
-    return (msr_vr << MSR_VR)  |
-        (msr_ap  << MSR_AP)  |
-        (msr_sa  << MSR_SA)  |
-        (msr_key << MSR_KEY) |
-        (msr_pow << MSR_POW) |
-        (msr_tlb << MSR_TLB) |
-        (msr_ile << MSR_ILE) |
-        (msr_ee << MSR_EE) |
-        (msr_pr << MSR_PR) |
-        (msr_fp << MSR_FP) |
-        (msr_me << MSR_ME) |
-        (msr_fe0 << MSR_FE0) |
-        (msr_se << MSR_SE) |
-        (msr_be << MSR_BE) |
-        (msr_fe1 << MSR_FE1) |
-        (msr_al  << MSR_AL)  |
-        (msr_ip << MSR_IP) |
-        (msr_ir << MSR_IR) |
-        (msr_dr << MSR_DR) |
-        (msr_pe  << MSR_PE)  |
-        (msr_px  << MSR_PX)  |
-        (msr_ri << MSR_RI) |
-        (msr_le << MSR_LE);
+    ppc_gpr_t tmp;
+
+    tmp = env->gpr[0];
+    env->gpr[0] = env->tgpr[0];
+    env->tgpr[0] = tmp;
+    tmp = env->gpr[1];
+    env->gpr[1] = env->tgpr[1];
+    env->tgpr[1] = tmp;
+    tmp = env->gpr[2];
+    env->gpr[2] = env->tgpr[2];
+    env->tgpr[2] = tmp;
+    tmp = env->gpr[3];
+    env->gpr[3] = env->tgpr[3];
+    env->tgpr[3] = tmp;
 }
 
-void do_compute_hflags (CPUPPCState *env)
+/* GDBstub can read and write MSR... */
+target_ulong do_load_msr (CPUPPCState *env)
 {
-    /* Compute current hflags */
-    env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |
-        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |
-        (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | 
-        (msr_se << MSR_SE) | (msr_be << MSR_BE);
+    return
+#if defined (TARGET_PPC64)
+        ((target_ulong)msr_sf   << MSR_SF)   |
+        ((target_ulong)msr_isf  << MSR_ISF)  |
+        ((target_ulong)msr_hv   << MSR_HV)   |
+#endif
+        ((target_ulong)msr_ucle << MSR_UCLE) |
+        ((target_ulong)msr_vr   << MSR_VR)   | /* VR / SPE */
+        ((target_ulong)msr_ap   << MSR_AP)   |
+        ((target_ulong)msr_sa   << MSR_SA)   |
+        ((target_ulong)msr_key  << MSR_KEY)  |
+        ((target_ulong)msr_pow  << MSR_POW)  | /* POW / WE */
+        ((target_ulong)msr_tlb  << MSR_TLB)  | /* TLB / TGPE / CE */
+        ((target_ulong)msr_ile  << MSR_ILE)  |
+        ((target_ulong)msr_ee   << MSR_EE)   |
+        ((target_ulong)msr_pr   << MSR_PR)   |
+        ((target_ulong)msr_fp   << MSR_FP)   |
+        ((target_ulong)msr_me   << MSR_ME)   |
+        ((target_ulong)msr_fe0  << MSR_FE0)  |
+        ((target_ulong)msr_se   << MSR_SE)   | /* SE / DWE / UBLE */
+        ((target_ulong)msr_be   << MSR_BE)   | /* BE / DE */
+        ((target_ulong)msr_fe1  << MSR_FE1)  |
+        ((target_ulong)msr_al   << MSR_AL)   |
+        ((target_ulong)msr_ip   << MSR_IP)   |
+        ((target_ulong)msr_ir   << MSR_IR)   | /* IR / IS */
+        ((target_ulong)msr_dr   << MSR_DR)   | /* DR / DS */
+        ((target_ulong)msr_pe   << MSR_PE)   | /* PE / EP */
+        ((target_ulong)msr_px   << MSR_PX)   | /* PX / PMM */
+        ((target_ulong)msr_ri   << MSR_RI)   |
+        ((target_ulong)msr_le   << MSR_LE);
 }
 
 void do_store_msr (CPUPPCState *env, target_ulong value)
@@ -812,10 +1421,7 @@
     value &= env->msr_mask;
     if (((value >> MSR_IR) & 1) != msr_ir ||
         ((value >> MSR_DR) & 1) != msr_dr) {
-        /* Flush all tlb when changing translation mode
-         * When using software driven TLB, we may also need to reload
-         * all defined TLBs
-         */
+        /* Flush all tlb when changing translation mode */
         tlb_flush(env, 1);
         env->interrupt_request |= CPU_INTERRUPT_EXITTB;
     }
@@ -824,35 +1430,63 @@
         fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
     }
 #endif
-    msr_vr  = (value >> MSR_VR)  & 1;
-    msr_ap  = (value >> MSR_AP)  & 1;
-    msr_sa  = (value >> MSR_SA)  & 1;
-    msr_key = (value >> MSR_KEY) & 1;
-    msr_pow = (value >> MSR_POW) & 1;
-    msr_tlb = (value >> MSR_TLB)  & 1;
-    msr_ile = (value >> MSR_ILE) & 1;
-    msr_ee  = (value >> MSR_EE)  & 1;
-    msr_pr  = (value >> MSR_PR)  & 1;
-    msr_fp  = (value >> MSR_FP)  & 1;
-    msr_me  = (value >> MSR_ME)  & 1;
-    msr_fe0 = (value >> MSR_FE0) & 1;
-    msr_se  = (value >> MSR_SE)  & 1;
-    msr_be  = (value >> MSR_BE)  & 1;
-    msr_fe1 = (value >> MSR_FE1) & 1;
-    msr_al  = (value >> MSR_AL)  & 1;
-    msr_ip  = (value >> MSR_IP)  & 1;
-    msr_ir  = (value >> MSR_IR)  & 1;
-    msr_dr  = (value >> MSR_DR)  & 1;
-    msr_pe  = (value >> MSR_PE)  & 1;
-    msr_px  = (value >> MSR_PX)  & 1;
-    msr_ri  = (value >> MSR_RI)  & 1;
-    msr_le  = (value >> MSR_LE)  & 1;
+    switch (PPC_EXCP(env)) {
+    case PPC_FLAGS_EXCP_602:
+    case PPC_FLAGS_EXCP_603:
+        if (((value >> MSR_TGPR) & 1) != msr_tgpr) {
+            /* Swap temporary saved registers with GPRs */
+            swap_gpr_tgpr(env);
+        }
+        break;
+    default:
+        break;
+    }
+#if defined (TARGET_PPC64)
+    msr_sf   = (value >> MSR_SF)   & 1;
+    msr_isf  = (value >> MSR_ISF)  & 1;
+    msr_hv   = (value >> MSR_HV)   & 1;
+#endif
+    msr_ucle = (value >> MSR_UCLE) & 1;
+    msr_vr   = (value >> MSR_VR)   & 1; /* VR / SPE */
+    msr_ap   = (value >> MSR_AP)   & 1;
+    msr_sa   = (value >> MSR_SA)   & 1;
+    msr_key  = (value >> MSR_KEY)  & 1;
+    msr_pow  = (value >> MSR_POW)  & 1; /* POW / WE */
+    msr_tlb  = (value >> MSR_TLB)  & 1; /* TLB / TGPR / CE */
+    msr_ile  = (value >> MSR_ILE)  & 1;
+    msr_ee   = (value >> MSR_EE)   & 1;
+    msr_pr   = (value >> MSR_PR)   & 1;
+    msr_fp   = (value >> MSR_FP)   & 1;
+    msr_me   = (value >> MSR_ME)   & 1;
+    msr_fe0  = (value >> MSR_FE0)  & 1;
+    msr_se   = (value >> MSR_SE)   & 1; /* SE / DWE / UBLE */
+    msr_be   = (value >> MSR_BE)   & 1; /* BE / DE */
+    msr_fe1  = (value >> MSR_FE1)  & 1;
+    msr_al   = (value >> MSR_AL)   & 1;
+    msr_ip   = (value >> MSR_IP)   & 1;
+    msr_ir   = (value >> MSR_IR)   & 1; /* IR / IS */
+    msr_dr   = (value >> MSR_DR)   & 1; /* DR / DS */
+    msr_pe   = (value >> MSR_PE)   & 1; /* PE / EP */
+    msr_px   = (value >> MSR_PX)   & 1; /* PX / PMM */
+    msr_ri   = (value >> MSR_RI)   & 1;
+    msr_le   = (value >> MSR_LE)   & 1;
     do_compute_hflags(env);
 
     enter_pm = 0;
     switch (PPC_EXCP(env)) {
+    case PPC_FLAGS_EXCP_603:
+        /* Don't handle SLEEP mode: we should disable all clocks...
+         * No dynamic power-management.
+         */
+        if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0)
+            enter_pm = 1;
+        break;
+    case PPC_FLAGS_EXCP_604:
+        if (msr_pow == 1)
+            enter_pm = 1;
+        break;
     case PPC_FLAGS_EXCP_7x0:
-	if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
+        if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
             enter_pm = 1;
         break;
     default:
@@ -866,75 +1500,25 @@
     }
 }
 
-float64 do_load_fpscr (CPUPPCState *env)
+#if defined(TARGET_PPC64)
+void ppc_store_msr_32 (CPUPPCState *env, uint32_t value)
 {
-    /* The 32 MSB of the target fpr are undefined.
-     * They'll be zero...
-     */
-    union {
-        float64 d;
-        struct {
-            uint32_t u[2];
-        } s;
-    } u;
-    int i;
-
-#ifdef WORDS_BIGENDIAN
-#define WORD0 0
-#define WORD1 1
-#else
-#define WORD0 1
-#define WORD1 0
+    do_store_msr(env,
+                 (do_load_msr(env) & ~0xFFFFFFFFULL) | (value & 0xFFFFFFFF));
+}
 #endif
-    u.s.u[WORD0] = 0;
-    u.s.u[WORD1] = 0;
-    for (i = 0; i < 8; i++)
-        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
-    return u.d;
-}
 
-void do_store_fpscr (CPUPPCState *env, float64 f, uint32_t mask)
+void do_compute_hflags (CPUPPCState *env)
 {
-    /*
-     * We use only the 32 LSB of the incoming fpr
-     */
-    union {
-        double d;
-        struct {
-            uint32_t u[2];
-        } s;
-    } u;
-    int i, rnd_type;
-
-    u.d = f;
-    if (mask & 0x80)
-        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
-    for (i = 1; i < 7; i++) {
-        if (mask & (1 << (7 - i)))
-            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
-    }
-    /* TODO: update FEX & VX */
-    /* Set rounding mode */
-    switch (env->fpscr[0] & 0x3) {
-    case 0:
-        /* Best approximation (round to nearest) */
-        rnd_type = float_round_nearest_even;
-        break;
-    case 1:
-        /* Smaller magnitude (round toward zero) */
-        rnd_type = float_round_to_zero;
-        break;
-    case 2:
-        /* Round toward +infinite */
-        rnd_type = float_round_up;
-        break;
-    default:
-    case 3:
-        /* Round toward -infinite */
-        rnd_type = float_round_down;
-        break;
-    }
-    set_float_rounding_mode(rnd_type, &env->fp_status);
+    /* Compute current hflags */
+    env->hflags = (msr_cm << MSR_CM) | (msr_vr << MSR_VR) |
+        (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) |
+        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) |
+        (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE);
+#if defined (TARGET_PPC64)
+    /* No care here: PowerPC 64 MSR_SF means the same as MSR_CM for BookE */
+    env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32));
+#endif
 }
 
 /*****************************************************************************/
@@ -944,58 +1528,85 @@
 {
     env->exception_index = -1;
 }
-#else
+
+void ppc_hw_interrupt (CPUState *env)
+{
+    env->exception_index = -1;
+}
+#else /* defined (CONFIG_USER_ONLY) */
 static void dump_syscall(CPUState *env)
 {
-    fprintf(logfile, "syscall r0=0x%08x r3=0x%08x r4=0x%08x r5=0x%08x r6=0x%08x nip=0x%08x\n",
+    fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
+            " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
             env->gpr[0], env->gpr[3], env->gpr[4],
             env->gpr[5], env->gpr[6], env->nip);
 }
 
 void do_interrupt (CPUState *env)
 {
-    target_ulong msr, *srr_0, *srr_1, tmp;
-    int excp;
+    target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
+    int excp, idx;
 
     excp = env->exception_index;
     msr = do_load_msr(env);
     /* The default is to use SRR0 & SRR1 to save the exception context */
     srr_0 = &env->spr[SPR_SRR0];
     srr_1 = &env->spr[SPR_SRR1];
+    asrr_0 = NULL;
+    asrr_1 = NULL;
 #if defined (DEBUG_EXCEPTIONS)
     if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
         if (loglevel != 0) {
-            fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
-                    (unsigned long)env->nip, excp, env->error_code);
- 	    cpu_dump_state(env, logfile, fprintf, 0);
+            fprintf(logfile,
+                    "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
+                    env->nip, excp, env->error_code);
+            cpu_dump_state(env, logfile, fprintf, 0);
         }
     }
 #endif
     if (loglevel & CPU_LOG_INT) {
-        fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
-                (unsigned long)env->nip, excp, env->error_code);
+        fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
+                env->nip, excp, env->error_code);
     }
     msr_pow = 0;
+    idx = -1;
     /* Generate informations in save/restore registers */
     switch (excp) {
-        /* Generic PowerPC exceptions */
+    /* Generic PowerPC exceptions */
     case EXCP_RESET: /* 0x0100 */
-        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) {
+        switch (PPC_EXCP(env)) {
+        case PPC_FLAGS_EXCP_40x:
+            srr_0 = &env->spr[SPR_40x_SRR2];
+            srr_1 = &env->spr[SPR_40x_SRR3];
+            break;
+        case PPC_FLAGS_EXCP_BOOKE:
+            idx = 0;
+            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
+            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
+            break;
+        default:
             if (msr_ip)
                 excp += 0xFFC00;
             excp |= 0xFFC00000;
-        } else {
-            srr_0 = &env->spr[SPR_40x_SRR2];
-            srr_1 = &env->spr[SPR_40x_SRR3];
+            break;
         }
         goto store_next;
     case EXCP_MACHINE_CHECK: /* 0x0200 */
-        if (msr_me == 0) {
-            cpu_abort(env, "Machine check exception while not allowed\n");
-        }
-        if (PPC_EXCP(env) == PPC_FLAGS_EXCP_40x) {
+        switch (PPC_EXCP(env)) {
+        case PPC_FLAGS_EXCP_40x:
             srr_0 = &env->spr[SPR_40x_SRR2];
             srr_1 = &env->spr[SPR_40x_SRR3];
+            break;
+        case PPC_FLAGS_EXCP_BOOKE:
+            idx = 1;
+            srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
+            srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
+            asrr_0 = &env->spr[SPR_BOOKE_CSRR0];
+            asrr_1 = &env->spr[SPR_BOOKE_CSRR1];
+            msr_ce = 0;
+            break;
+        default:
+            break;
         }
         msr_me = 0;
         break;
@@ -1004,43 +1615,34 @@
         /* data location address has been stored
          * when the fault has been detected
          */
-	msr &= ~0xFFFF0000;
+        idx = 2;
+        msr &= ~0xFFFF0000;
 #if defined (DEBUG_EXCEPTIONS)
-	if (loglevel) {
-	    fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
-		    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
-	} else {
-	    printf("DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
-		   env->spr[SPR_DSISR], env->spr[SPR_DAR]);
-	}
+        if (loglevel != 0) {
+            fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
+                    "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
+        }
 #endif
         goto store_next;
     case EXCP_ISI: /* 0x0400 */
         /* Store exception cause */
-	msr &= ~0xFFFF0000;
+        idx = 3;
+        msr &= ~0xFFFF0000;
         msr |= env->error_code;
 #if defined (DEBUG_EXCEPTIONS)
-	if (loglevel != 0) {
-	    fprintf(logfile, "ISI exception: msr=0x%08x, nip=0x%08x\n",
-		    msr, env->nip);
-	}
+        if (loglevel != 0) {
+            fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
+                    "\n", msr, env->nip);
+        }
 #endif
         goto store_next;
     case EXCP_EXTERNAL: /* 0x0500 */
-        if (msr_ee == 0) {
-#if defined (DEBUG_EXCEPTIONS)
-            if (loglevel > 0) {
-                fprintf(logfile, "Skipping hardware interrupt\n");
-            }
-#endif
-            /* Requeue it */
-            env->interrupt_request |= CPU_INTERRUPT_HARD;
-            return;
-        }
+        idx = 4;
         goto store_next;
     case EXCP_ALIGN: /* 0x0600 */
-        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_601) {
+        if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) {
             /* Store exception cause */
+            idx = 5;
             /* Get rS/rD and rA from faulting opcode */
             env->spr[SPR_DSISR] |=
                 (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
@@ -1055,15 +1657,18 @@
         }
         goto store_current;
     case EXCP_PROGRAM: /* 0x0700 */
+        idx = 6;
         msr &= ~0xFFFF0000;
         switch (env->error_code & ~0xF) {
         case EXCP_FP:
             if (msr_fe0 == 0 && msr_fe1 == 0) {
 #if defined (DEBUG_EXCEPTIONS)
-                printf("Ignore floating point exception\n");
+                if (loglevel != 0) {
+                    fprintf(logfile, "Ignore floating point exception\n");
+                }
 #endif
                 return;
-        }
+            }
             msr |= 0x00100000;
             /* Set FX */
             env->fpscr[7] |= 0x8;
@@ -1071,36 +1676,37 @@
             if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
                 ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
                 env->fpscr[7] |= 0x4;
-        break;
+            break;
         case EXCP_INVAL:
-            //	    printf("Invalid instruction at 0x%08x\n", env->nip);
+#if defined (DEBUG_EXCEPTIONS)
+            if (loglevel != 0) {
+                fprintf(logfile, "Invalid instruction at 0x" ADDRX "\n",
+                        env->nip);
+            }
+#endif
             msr |= 0x00080000;
-        break;
+            break;
         case EXCP_PRIV:
             msr |= 0x00040000;
-        break;
+            break;
         case EXCP_TRAP:
+            idx = 15;
             msr |= 0x00020000;
             break;
         default:
             /* Should never occur */
-        break;
-    }
+            break;
+        }
         msr |= 0x00010000;
         goto store_current;
     case EXCP_NO_FP: /* 0x0800 */
+        idx = 7;
         msr &= ~0xFFFF0000;
         goto store_current;
     case EXCP_DECR:
-        if (msr_ee == 0) {
-#if 1
-            /* Requeue it */
-            env->interrupt_request |= CPU_INTERRUPT_TIMER;
-#endif
-            return;
-        }
         goto store_next;
     case EXCP_SYSCALL: /* 0x0C00 */
+        idx = 8;
         /* NOTE: this is a temporary hack to support graphics OSI
            calls from the MOL driver */
         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
@@ -1125,7 +1731,7 @@
         cpu_abort(env, "Floating point assist exception "
                   "is not implemented yet !\n");
         goto store_next;
-    /* 64 bits PowerPC exceptions */
+        /* 64 bits PowerPC exceptions */
     case EXCP_DSEG: /* 0x0380 */
         /* XXX: TODO */
         cpu_abort(env, "Data segment exception is not implemented yet !\n");
@@ -1136,19 +1742,14 @@
                   "Instruction segment exception is not implemented yet !\n");
         goto store_next;
     case EXCP_HDECR: /* 0x0980 */
-        if (msr_ee == 0) {
-#if 1
-            /* Requeue it */
-            env->interrupt_request |= CPU_INTERRUPT_TIMER;
-#endif
-        return;
-        }
-        cpu_abort(env,
-                  "Hypervisor decrementer exception is not implemented yet !\n");
+        /* XXX: TODO */
+        cpu_abort(env, "Hypervisor decrementer exception is not implemented "
+                  "yet !\n");
         goto store_next;
     /* Implementation specific exceptions */
     case 0x0A00:
-        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_602) {
+        if (likely(env->spr[SPR_PVR] == CPU_PPC_G2 ||
+                   env->spr[SPR_PVR] == CPU_PPC_G2LE)) {
             /* Critical interrupt on G2 */
             /* XXX: TODO */
             cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
@@ -1158,6 +1759,7 @@
         }
         return;
     case 0x0F20:
+        idx = 9;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* APU unavailable on 405 */
@@ -1177,29 +1779,38 @@
         }
         return;
     case 0x1000:
+        idx = 10;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* PIT on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env, "40x PIT exception is not implemented yet !\n");
+            msr &= ~0xFFFF0000;
+#if defined (DEBUG_EXCEPTIONS)
+            if (loglevel != 0)
+                fprintf(logfile, "PIT exception\n");
+#endif
             goto store_next;
         case PPC_FLAGS_EXCP_602:
         case PPC_FLAGS_EXCP_603:
             /* ITLBMISS on 602/603 */
-            msr &= ~0xF00F0000;
-            msr_tgpr = 1;
             goto store_gprs;
+        case PPC_FLAGS_EXCP_7x5:
+            /* ITLBMISS on 745/755 */
+            goto tlb_miss;
         default:
             cpu_abort(env, "Invalid exception 0x1000 !\n");
             break;
         }
         return;
     case 0x1010:
+        idx = 11;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* FIT on 4xx */
-            cpu_abort(env, "40x FIT exception is not implemented yet !\n");
-            /* XXX: TODO */
+            msr &= ~0xFFFF0000;
+#if defined (DEBUG_EXCEPTIONS)
+            if (loglevel != 0)
+                fprintf(logfile, "FIT exception\n");
+#endif
             goto store_next;
         default:
             cpu_abort(env, "Invalid exception 0x1010 !\n");
@@ -1207,79 +1818,93 @@
         }
         return;
     case 0x1020:
+        idx = 12;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* Watchdog on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "40x watchdog exception is not implemented yet !\n");
+            msr &= ~0xFFFF0000;
+#if defined (DEBUG_EXCEPTIONS)
+            if (loglevel != 0)
+                fprintf(logfile, "WDT exception\n");
+#endif
             goto store_next;
+        case PPC_FLAGS_EXCP_BOOKE:
+            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
+            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
+            break;
         default:
             cpu_abort(env, "Invalid exception 0x1020 !\n");
             break;
         }
         return;
     case 0x1100:
+        idx = 13;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* DTLBMISS on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "40x DTLBMISS exception is not implemented yet !\n");
+            msr &= ~0xFFFF0000;
             goto store_next;
         case PPC_FLAGS_EXCP_602:
         case PPC_FLAGS_EXCP_603:
             /* DLTLBMISS on 602/603 */
-            msr &= ~0xF00F0000;
-            msr_tgpr = 1;
             goto store_gprs;
+        case PPC_FLAGS_EXCP_7x5:
+            /* DLTLBMISS on 745/755 */
+            goto tlb_miss;
         default:
             cpu_abort(env, "Invalid exception 0x1100 !\n");
             break;
         }
         return;
     case 0x1200:
+        idx = 14;
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_40x:
             /* ITLBMISS on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "40x ITLBMISS exception is not implemented yet !\n");
+            msr &= ~0xFFFF0000;
             goto store_next;
         case PPC_FLAGS_EXCP_602:
         case PPC_FLAGS_EXCP_603:
             /* DSTLBMISS on 602/603 */
-            msr &= ~0xF00F0000;
+        store_gprs:
+            /* Swap temporary saved registers with GPRs */
+            swap_gpr_tgpr(env);
             msr_tgpr = 1;
-        store_gprs:
 #if defined (DEBUG_SOFTWARE_TLB)
             if (loglevel != 0) {
-                fprintf(logfile, "6xx %sTLB miss: IM %08x DM %08x IC %08x "
-                        "DC %08x H1 %08x H2 %08x %08x\n",
-                        excp == 0x1000 ? "I" : excp == 0x1100 ? "DL" : "DS",
-                        env->spr[SPR_IMISS], env->spr[SPR_DMISS],
-                        env->spr[SPR_ICMP], env->spr[SPR_DCMP],
-                        env->spr[SPR_DHASH1], env->spr[SPR_DHASH2],
+                const unsigned char *es;
+                target_ulong *miss, *cmp;
+                int en;
+                if (excp == 0x1000) {
+                    es = "I";
+                    en = 'I';
+                    miss = &env->spr[SPR_IMISS];
+                    cmp = &env->spr[SPR_ICMP];
+                } else {
+                    if (excp == 0x1100)
+                        es = "DL";
+                    else
+                        es = "DS";
+                    en = 'D';
+                    miss = &env->spr[SPR_DMISS];
+                    cmp = &env->spr[SPR_DCMP];
+                }
+                fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
+                        " H1 " ADDRX " H2 " ADDRX " %08x\n",
+                        es, en, *miss, en, *cmp,
+                        env->spr[SPR_HASH1], env->spr[SPR_HASH2],
                         env->error_code);
             }
 #endif
-            /* Swap temporary saved registers with GPRs */
-            tmp = env->gpr[0];
-            env->gpr[0] = env->tgpr[0];
-            env->tgpr[0] = tmp;
-            tmp = env->gpr[1];
-            env->gpr[1] = env->tgpr[1];
-            env->tgpr[1] = tmp;
-            tmp = env->gpr[2];
-            env->gpr[2] = env->tgpr[2];
-            env->tgpr[2] = tmp;
-            tmp = env->gpr[3];
-            env->gpr[3] = env->tgpr[3];
-            env->tgpr[3] = tmp;
+            goto tlb_miss;
+        case PPC_FLAGS_EXCP_7x5:
+            /* DSTLBMISS on 745/755 */
+        tlb_miss:
+            msr &= ~0xF83F0000;
             msr |= env->crf[0] << 28;
             msr |= env->error_code; /* key, D/I, S/L bits */
             /* Set way using a LRU mechanism */
-            msr |= (env->last_way ^ 1) << 17;
+            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
             goto store_next;
         default:
             cpu_abort(env, "Invalid exception 0x1200 !\n");
@@ -1324,6 +1949,7 @@
         switch (PPC_EXCP(env)) {
         case PPC_FLAGS_EXCP_602:
             /* Watchdog on 602 */
+            /* XXX: TODO */
             cpu_abort(env,
                       "602 watchdog exception is not implemented yet !\n");
             goto store_next;
@@ -1408,6 +2034,10 @@
             cpu_abort(env,
                       "601 run mode exception is not implemented yet !\n");
             goto store_next;
+        case PPC_FLAGS_EXCP_BOOKE:
+            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
+            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
+            break;
         default:
             cpu_abort(env, "Invalid exception 0x1800 !\n");
             break;
@@ -1422,15 +2052,19 @@
         return;
     store_current:
         /* save current instruction location */
-        *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL;
+        *srr_0 = env->nip - 4;
         break;
     store_next:
         /* save next instruction location */
-        *srr_0 = env->nip & 0xFFFFFFFFULL;
+        *srr_0 = env->nip;
         break;
     }
     /* Save msr */
     *srr_1 = msr;
+    if (asrr_0 != NULL)
+        *asrr_0 = *srr_0;
+    if (asrr_1 != NULL)
+        *asrr_1 = *srr_1;
     /* If we disactivated any translation, flush TLBs */
     if (msr_ir || msr_dr) {
         tlb_flush(env, 1);
@@ -1447,10 +2081,191 @@
     msr_dr = 0;
     msr_ri = 0;
     msr_le = msr_ile;
-    msr_sf = msr_isf;
+    if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) {
+        msr_cm = msr_icm;
+        if (idx == -1 || (idx >= 16 && idx < 32)) {
+            cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",
+                      excp, excp, idx);
+        }
+#if defined(TARGET_PPC64)
+        if (msr_cm)
+            env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR];
+        else
+#endif
+            env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR];
+        if (idx < 16)
+            env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx];
+        else if (idx < 38)
+            env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32];
+    } else {
+        msr_sf = msr_isf;
+        env->nip = excp;
+    }
     do_compute_hflags(env);
     /* Jump to handler */
-    env->nip = excp;
     env->exception_index = EXCP_NONE;
 }
+
+void ppc_hw_interrupt (CPUPPCState *env)
+{
+    int raised = 0;
+
+#if 1
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
+                __func__, env, env->pending_interrupts,
+                env->interrupt_request, msr_me, msr_ee);
+    }
+#endif
+    /* Raise it */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
+        /* External reset / critical input */
+        /* XXX: critical input should be handled another way.
+         *      This code is not correct !
+         */
+        env->exception_index = EXCP_RESET;
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
+        raised = 1;
+    }
+    if (raised == 0 && msr_me != 0) {
+        /* Machine check exception */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
+            env->exception_index = EXCP_MACHINE_CHECK;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
+            raised = 1;
+        }
+    }
+    if (raised == 0 && msr_ee != 0) {
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        /* Hypervisor decrementer exception */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+            env->exception_index = EXCP_HDECR;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
+            raised = 1;
+        } else
+#endif
+        /* Decrementer exception */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
+            env->exception_index = EXCP_DECR;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
+            raised = 1;
+        /* Programmable interval timer on embedded PowerPC */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
+            env->exception_index = EXCP_40x_PIT;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
+            raised = 1;
+        /* Fixed interval timer on embedded PowerPC */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
+            env->exception_index = EXCP_40x_FIT;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
+            raised = 1;
+        /* Watchdog timer on embedded PowerPC */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
+            env->exception_index = EXCP_40x_WATCHDOG;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
+            raised = 1;
+        /* External interrupt */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
+            env->exception_index = EXCP_EXTERNAL;
+            /* Taking an external interrupt does not clear the external
+             * interrupt status
+             */
+#if 0
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
+#endif
+            raised = 1;
+#if 0 // TODO
+        /* Thermal interrupt */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
+            env->exception_index = EXCP_970_THRM;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
+            raised = 1;
+#endif
+        }
+#if 0 // TODO
+    /* External debug exception */
+    } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
+        env->exception_index = EXCP_xxx;
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
+        raised = 1;
+#endif
+    }
+    if (raised != 0) {
+        env->error_code = 0;
+        do_interrupt(env);
+    }
+}
 #endif /* !CONFIG_USER_ONLY */
+
+void cpu_dump_EA (target_ulong EA)
+{
+    FILE *f;
+
+    if (logfile) {
+        f = logfile;
+    } else {
+        f = stdout;
+        return;
+    }
+    fprintf(f, "Memory access at address " ADDRX "\n", EA);
+}
+
+void cpu_dump_rfi (target_ulong RA, target_ulong msr)
+{
+    FILE *f;
+
+    if (logfile) {
+        f = logfile;
+    } else {
+        f = stdout;
+        return;
+    }
+    fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
+            RA, msr);
+}
+
+void cpu_ppc_reset (void *opaque)
+{
+    CPUPPCState *env;
+
+    env = opaque;
+#if defined (DO_SINGLE_STEP) && 0
+    /* Single step trace mode */
+    msr_se = 1;
+    msr_be = 1;
+#endif
+    msr_fp = 1; /* Allow floating point exceptions */
+    msr_me = 1; /* Allow machine check exceptions  */
+#if defined(TARGET_PPC64)
+    msr_sf = 0; /* Boot in 32 bits mode */
+    msr_cm = 0;
+#endif
+#if defined(CONFIG_USER_ONLY)
+    msr_pr = 1;
+    tlb_flush(env, 1);
+#else
+    env->nip = 0xFFFFFFFC;
+    ppc_tlb_invalidate_all(env);
+#endif
+    do_compute_hflags(env);
+    env->reserve = -1;
+}
+
+CPUPPCState *cpu_ppc_init (void)
+{
+    CPUPPCState *env;
+
+    env = qemu_mallocz(sizeof(CPUPPCState));
+    if (!env)
+        return NULL;
+    cpu_exec_init(env);
+    cpu_ppc_reset(env);
+
+    return env;
+}
+
+void cpu_ppc_close (CPUPPCState *env)
+{
+    /* Should also remove all opcode tables... */
+    free(env);
+}

Added: trunk/src/host/qemu-neo1973/target-ppc/mfrom_table.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/mfrom_table.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/mfrom_table.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,79 @@
+static const uint8_t mfrom_ROM_table[602] =
+{
+     77,  77,  76,  76,  75,  75,  74,  74, 
+     73,  73,  72,  72,  71,  71,  70,  70, 
+     69,  69,  68,  68,  68,  67,  67,  66, 
+     66,  65,  65,  64,  64,  64,  63,  63, 
+     62,  62,  61,  61,  61,  60,  60,  59, 
+     59,  58,  58,  58,  57,  57,  56,  56, 
+     56,  55,  55,  54,  54,  54,  53,  53, 
+     53,  52,  52,  51,  51,  51,  50,  50, 
+     50,  49,  49,  49,  48,  48,  47,  47, 
+     47,  46,  46,  46,  45,  45,  45,  44, 
+     44,  44,  43,  43,  43,  42,  42,  42, 
+     42,  41,  41,  41,  40,  40,  40,  39, 
+     39,  39,  39,  38,  38,  38,  37,  37, 
+     37,  37,  36,  36,  36,  35,  35,  35, 
+     35,  34,  34,  34,  34,  33,  33,  33, 
+     33,  32,  32,  32,  32,  31,  31,  31, 
+     31,  30,  30,  30,  30,  29,  29,  29, 
+     29,  28,  28,  28,  28,  28,  27,  27, 
+     27,  27,  26,  26,  26,  26,  26,  25, 
+     25,  25,  25,  25,  24,  24,  24,  24, 
+     24,  23,  23,  23,  23,  23,  23,  22, 
+     22,  22,  22,  22,  21,  21,  21,  21, 
+     21,  21,  20,  20,  20,  20,  20,  20, 
+     19,  19,  19,  19,  19,  19,  19,  18, 
+     18,  18,  18,  18,  18,  17,  17,  17, 
+     17,  17,  17,  17,  16,  16,  16,  16, 
+     16,  16,  16,  16,  15,  15,  15,  15, 
+     15,  15,  15,  15,  14,  14,  14,  14, 
+     14,  14,  14,  14,  13,  13,  13,  13, 
+     13,  13,  13,  13,  13,  12,  12,  12, 
+     12,  12,  12,  12,  12,  12,  12,  11, 
+     11,  11,  11,  11,  11,  11,  11,  11, 
+     11,  11,  10,  10,  10,  10,  10,  10, 
+     10,  10,  10,  10,  10,   9,   9,   9, 
+      9,   9,   9,   9,   9,   9,   9,   9, 
+      9,   9,   8,   8,   8,   8,   8,   8, 
+      8,   8,   8,   8,   8,   8,   8,   8, 
+      7,   7,   7,   7,   7,   7,   7,   7, 
+      7,   7,   7,   7,   7,   7,   7,   7, 
+      7,   6,   6,   6,   6,   6,   6,   6, 
+      6,   6,   6,   6,   6,   6,   6,   6, 
+      6,   6,   6,   6,   5,   5,   5,   5, 
+      5,   5,   5,   5,   5,   5,   5,   5, 
+      5,   5,   5,   5,   5,   5,   5,   5, 
+      5,   5,   5,   4,   4,   4,   4,   4, 
+      4,   4,   4,   4,   4,   4,   4,   4, 
+      4,   4,   4,   4,   4,   4,   4,   4, 
+      4,   4,   4,   4,   4,   4,   4,   3, 
+      3,   3,   3,   3,   3,   3,   3,   3, 
+      3,   3,   3,   3,   3,   3,   3,   3, 
+      3,   3,   3,   3,   3,   3,   3,   3, 
+      3,   3,   3,   3,   3,   3,   3,   3, 
+      3,   3,   3,   3,   3,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   2,   2, 
+      2,   2,   2,   2,   2,   2,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   1,   1,   1,   1,   1,   1,   1, 
+      1,   0, 
+};

Added: trunk/src/host/qemu-neo1973/target-ppc/mfrom_table_gen.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/mfrom_table_gen.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/mfrom_table_gen.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,33 @@
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <math.h>
+
+int main (void)
+{
+    double d;
+    uint8_t n;
+    int i;
+    
+    printf("static const uint8_t mfrom_ROM_table[602] =\n{\n    ");
+    for (i = 0; i < 602; i++) {
+        /* Extremly decomposed:
+         *                    -T0 / 256
+         * T0 = 256 * log10(10          + 1.0) + 0.5
+         */
+        d = -i;
+        d /= 256.0;
+        d = exp10(d);
+        d += 1.0;
+        d = log10(d);
+        d *= 256;
+        d += 0.5;
+        n = d;
+        printf("%3d, ", n);
+        if ((i & 7) == 7)
+            printf("\n    ");
+    }
+    printf("\n};\n");
+
+    return 0;
+}

Modified: trunk/src/host/qemu-neo1973/target-ppc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation micro-operations for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -22,17 +22,17 @@
 
 #include "config.h"
 #include "exec.h"
+#include "op_helper.h"
 
+/* XXX: this is to be suppressed */
 #define regs (env)
-#define Ts0 (int32_t)T0
-#define Ts1 (int32_t)T1
-#define Ts2 (int32_t)T2
 
 #define FT0 (env->ft0)
 #define FT1 (env->ft1)
 #define FT2 (env->ft2)
 
-#define PPC_OP(name) void glue(op_, name)(void)
+/* XXX: this is to be suppressed... */
+#define PPC_OP(name) void OPPROTO glue(op_, name)(void)
 
 #define REG 0
 #include "op_template.h"
@@ -130,35 +130,18 @@
 #define REG 31
 #include "op_template.h"
 
-/* PowerPC state maintenance operations */
-/* set_Rc0 */
-PPC_OP(set_Rc0)
-{
-    uint32_t tmp;
 
-    if (Ts0 < 0) {
-        tmp = 0x08;
-    } else if (Ts0 > 0) {
-        tmp = 0x04;
-    } else {
-        tmp = 0x02;
-    }
-    tmp |= xer_ov;
-    env->crf[0] = tmp;
-    RETURN();
-}
-
-/* reset_Rc0 */
-PPC_OP(reset_Rc0)
+void OPPROTO op_print_mem_EA (void)
 {
-    env->crf[0] = 0x02 | xer_ov;
+    do_print_mem_EA(T0);
     RETURN();
 }
 
-/* set_Rc0_1 */
-PPC_OP(set_Rc0_1)
+/* PowerPC state maintenance operations */
+/* set_Rc0 */
+PPC_OP(set_Rc0)
 {
-    env->crf[0] = 0x04 | xer_ov;
+    env->crf[0] = T0 | xer_ov;
     RETURN();
 }
 
@@ -170,70 +153,85 @@
 }
 
 /* Constants load */
-PPC_OP(set_T0)
+void OPPROTO op_reset_T0 (void)
 {
-    T0 = PARAM(1);
+    T0 = 0;
     RETURN();
 }
 
-PPC_OP(set_T1)
+PPC_OP(set_T0)
 {
-    T1 = PARAM(1);
+    T0 = (uint32_t)PARAM1;
     RETURN();
 }
 
-PPC_OP(set_T2)
+#if defined(TARGET_PPC64)
+void OPPROTO op_set_T0_64 (void)
 {
-    T2 = PARAM(1);
+    T0 = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
     RETURN();
 }
+#endif
 
-/* Generate exceptions */
-PPC_OP(raise_exception_err)
+PPC_OP(set_T1)
 {
-    do_raise_exception_err(PARAM(1), PARAM(2));
+    T1 = (uint32_t)PARAM1;
+    RETURN();
 }
 
-PPC_OP(raise_exception)
+#if defined(TARGET_PPC64)
+void OPPROTO op_set_T1_64 (void)
 {
-    do_raise_exception(PARAM(1));
+    T1 = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    RETURN();
 }
+#endif
 
-PPC_OP(update_nip)
+#if 0 // unused
+PPC_OP(set_T2)
 {
-    env->nip = PARAM(1);
+    T2 = PARAM(1);
+    RETURN();
 }
+#endif
 
-PPC_OP(debug)
+void OPPROTO op_move_T1_T0 (void)
 {
-    do_raise_exception(EXCP_DEBUG);
+    T1 = T0;
+    RETURN();
 }
 
-/* Segment registers load and store with immediate index */
-PPC_OP(load_srin)
+void OPPROTO op_move_T2_T0 (void)
 {
-    T0 = regs->sr[T1 >> 28];
+    T2 = T0;
     RETURN();
 }
 
-PPC_OP(store_srin)
+/* Generate exceptions */
+PPC_OP(raise_exception_err)
 {
-    do_store_sr(env, ((uint32_t)T1 >> 28), T0);
-    RETURN();
+    do_raise_exception_err(PARAM(1), PARAM(2));
 }
 
-PPC_OP(load_sdr1)
+PPC_OP(update_nip)
 {
-    T0 = regs->sdr1;
+    env->nip = (uint32_t)PARAM1;
     RETURN();
 }
 
-PPC_OP(store_sdr1)
+#if defined(TARGET_PPC64)
+void OPPROTO op_update_nip_64 (void)
 {
-    do_store_sdr1(env, T0);
+    env->nip = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
     RETURN();
 }
+#endif
 
+PPC_OP(debug)
+{
+    do_raise_exception(EXCP_DEBUG);
+}
+
 PPC_OP(exit_tb)
 {
     EXIT_TB();
@@ -242,26 +240,43 @@
 /* Load/store special registers */
 PPC_OP(load_cr)
 {
-    T0 = do_load_cr(env);
+    do_load_cr();
     RETURN();
 }
 
 PPC_OP(store_cr)
 {
-    do_store_cr(env, T0, PARAM(1));
+    do_store_cr(PARAM(1));
     RETURN();
 }
 
+void OPPROTO op_load_cro (void)
+{
+    T0 = env->crf[PARAM1];
+    RETURN();
+}
+
+void OPPROTO op_store_cro (void)
+{
+    env->crf[PARAM1] = T0;
+    RETURN();
+}
+
 PPC_OP(load_xer_cr)
 {
     T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);
     RETURN();
 }
 
-PPC_OP(clear_xer_cr)
+PPC_OP(clear_xer_ov)
 {
     xer_so = 0;
     xer_ov = 0;
+    RETURN();
+}
+
+PPC_OP(clear_xer_ca)
+{
     xer_ca = 0;
     RETURN();
 }
@@ -272,18 +287,64 @@
     RETURN();
 }
 
+void OPPROTO op_store_xer_bc (void)
+{
+    xer_bc = T0;
+    RETURN();
+}
+
 PPC_OP(load_xer)
 {
-    T0 = do_load_xer(env);
+    do_load_xer();
     RETURN();
 }
 
 PPC_OP(store_xer)
 {
-    do_store_xer(env, T0);
+    do_store_xer();
     RETURN();
 }
 
+#if !defined(CONFIG_USER_ONLY)
+/* Segment registers load and store */
+PPC_OP(load_sr)
+{
+    T0 = regs->sr[T1];
+    RETURN();
+}
+
+PPC_OP(store_sr)
+{
+    do_store_sr(env, T1, T0);
+    RETURN();
+}
+
+PPC_OP(load_sdr1)
+{
+    T0 = regs->sdr1;
+    RETURN();
+}
+
+PPC_OP(store_sdr1)
+{
+    do_store_sdr1(env, T0);
+    RETURN();
+}
+
+#if defined (TARGET_PPC64)
+void OPPROTO op_load_asr (void)
+{
+    T0 = env->asr;
+    RETURN();
+}
+
+void OPPROTO op_store_asr (void)
+{
+    ppc_store_asr(env, T0);
+    RETURN();
+}
+#endif
+
 PPC_OP(load_msr)
 {
     T0 = do_load_msr(env);
@@ -296,19 +357,46 @@
     RETURN();
 }
 
+#if defined (TARGET_PPC64)
+void OPPROTO op_store_msr_32 (void)
+{
+    ppc_store_msr_32(env, T0);
+    RETURN();
+}
+#endif
+#endif
+
 /* SPR */
-PPC_OP(load_spr)
+void OPPROTO op_load_spr (void)
 {
-    T0 = regs->spr[PARAM(1)];
+    T0 = env->spr[PARAM1];
     RETURN();
 }
 
-PPC_OP(store_spr)
+void OPPROTO op_store_spr (void)
 {
-    regs->spr[PARAM(1)] = T0;
+    env->spr[PARAM1] = T0;
     RETURN();
 }
 
+void OPPROTO op_load_dump_spr (void)
+{
+    T0 = ppc_load_dump_spr(PARAM1);
+    RETURN();
+}
+
+void OPPROTO op_store_dump_spr (void)
+{
+    ppc_store_dump_spr(PARAM1, T0);
+    RETURN();
+}
+
+void OPPROTO op_mask_spr (void)
+{
+    env->spr[PARAM1] &= ~T0;
+    RETURN();
+}
+
 PPC_OP(load_lr)
 {
     T0 = regs->lr;
@@ -345,6 +433,7 @@
     RETURN();
 }
 
+#if !defined(CONFIG_USER_ONLY)
 PPC_OP(store_tbl)
 {
     cpu_ppc_store_tbl(regs, T0);
@@ -360,7 +449,8 @@
 PPC_OP(load_decr)
 {
     T0 = cpu_ppc_load_decr(regs);
-    }
+    RETURN();
+}
 
 PPC_OP(store_decr)
 {
@@ -371,15 +461,16 @@
 PPC_OP(load_ibat)
 {
     T0 = regs->IBAT[PARAM(1)][PARAM(2)];
+    RETURN();
 }
 
-void op_store_ibatu (void)
+void OPPROTO op_store_ibatu (void)
 {
     do_store_ibatu(env, PARAM1, T0);
     RETURN();
 }
 
-void op_store_ibatl (void)
+void OPPROTO op_store_ibatl (void)
 {
 #if 1
     env->IBAT[1][PARAM1] = T0;
@@ -392,15 +483,16 @@
 PPC_OP(load_dbat)
 {
     T0 = regs->DBAT[PARAM(1)][PARAM(2)];
+    RETURN();
 }
 
-void op_store_dbatu (void)
+void OPPROTO op_store_dbatu (void)
 {
     do_store_dbatu(env, PARAM1, T0);
     RETURN();
 }
 
-void op_store_dbatl (void)
+void OPPROTO op_store_dbatl (void)
 {
 #if 1
     env->DBAT[1][PARAM1] = T0;
@@ -409,17 +501,18 @@
 #endif
     RETURN();
 }
+#endif /* !defined(CONFIG_USER_ONLY) */
 
 /* FPSCR */
 PPC_OP(load_fpscr)
 {
-    FT0 = do_load_fpscr(env);
+    do_load_fpscr();
     RETURN();
 }
 
 PPC_OP(store_fpscr)
 {
-    do_store_fpscr(env, FT0, PARAM1);
+    do_store_fpscr(PARAM1);
     RETURN();
 }
 
@@ -444,7 +537,7 @@
 
 PPC_OP(setcrfbit)
 {
-    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2)); 
+    T1 = (T1 & PARAM(1)) | (T0 << PARAM(2));
     RETURN();
 }
 
@@ -453,9 +546,18 @@
 
 PPC_OP(setlr)
 {
-    regs->lr = PARAM1;
+    regs->lr = (uint32_t)PARAM1;
+    RETURN();
 }
 
+#if defined (TARGET_PPC64)
+void OPPROTO op_setlr_64 (void)
+{
+    regs->lr = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    RETURN();
+}
+#endif
+
 PPC_OP(goto_tb0)
 {
     GOTO_TB(op_goto_tb0, PARAM1, 0);
@@ -466,11 +568,20 @@
     GOTO_TB(op_goto_tb1, PARAM1, 1);
 }
 
-PPC_OP(b_T1)
+void OPPROTO op_b_T1 (void)
 {
-    regs->nip = T1 & ~3;
+    regs->nip = (uint32_t)(T1 & ~3);
+    RETURN();
 }
 
+#if defined (TARGET_PPC64)
+void OPPROTO op_b_T1_64 (void)
+{
+    regs->nip = (uint64_t)(T1 & ~3);
+    RETURN();
+}
+#endif
+
 PPC_OP(jz_T0)
 {
     if (!T0)
@@ -478,66 +589,135 @@
     RETURN();
 }
 
-PPC_OP(btest_T1) 
+void OPPROTO op_btest_T1 (void)
 {
     if (T0) {
-        regs->nip = T1 & ~3;
+        regs->nip = (uint32_t)(T1 & ~3);
     } else {
-        regs->nip = PARAM1;
+        regs->nip = (uint32_t)PARAM1;
     }
     RETURN();
 }
 
+#if defined (TARGET_PPC64)
+void OPPROTO op_btest_T1_64 (void)
+{
+    if (T0) {
+        regs->nip = (uint64_t)(T1 & ~3);
+    } else {
+        regs->nip = ((uint64_t)PARAM1 << 32) | (uint64_t)PARAM2;
+    }
+    RETURN();
+}
+#endif
+
 PPC_OP(movl_T1_ctr)
 {
     T1 = regs->ctr;
+    RETURN();
 }
 
 PPC_OP(movl_T1_lr)
 {
     T1 = regs->lr;
+    RETURN();
 }
 
 /* tests with result in T0 */
+void OPPROTO op_test_ctr (void)
+{
+    T0 = (uint32_t)regs->ctr;
+    RETURN();
+}
 
-PPC_OP(test_ctr)
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctr_64 (void)
 {
-    T0 = regs->ctr;
+    T0 = (uint64_t)regs->ctr;
+    RETURN();
 }
+#endif
 
-PPC_OP(test_ctr_true)
+void OPPROTO op_test_ctr_true (void)
 {
-    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) != 0);
+    T0 = ((uint32_t)regs->ctr != 0 && (T0 & PARAM1) != 0);
+    RETURN();
 }
 
-PPC_OP(test_ctr_false)
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctr_true_64 (void)
 {
-    T0 = (regs->ctr != 0 && (T0 & PARAM(1)) == 0);
+    T0 = ((uint64_t)regs->ctr != 0 && (T0 & PARAM1) != 0);
+    RETURN();
 }
+#endif
 
-PPC_OP(test_ctrz)
+void OPPROTO op_test_ctr_false (void)
 {
-    T0 = (regs->ctr == 0);
+    T0 = ((uint32_t)regs->ctr != 0 && (T0 & PARAM1) == 0);
+    RETURN();
 }
 
-PPC_OP(test_ctrz_true)
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctr_false_64 (void)
 {
-    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) != 0);
+    T0 = ((uint64_t)regs->ctr != 0 && (T0 & PARAM1) == 0);
+    RETURN();
 }
+#endif
 
-PPC_OP(test_ctrz_false)
+void OPPROTO op_test_ctrz (void)
 {
-    T0 = (regs->ctr == 0 && (T0 & PARAM(1)) == 0);
+    T0 = ((uint32_t)regs->ctr == 0);
+    RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctrz_64 (void)
+{
+    T0 = ((uint64_t)regs->ctr == 0);
+    RETURN();
+}
+#endif
+
+void OPPROTO op_test_ctrz_true (void)
+{
+    T0 = ((uint32_t)regs->ctr == 0 && (T0 & PARAM1) != 0);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctrz_true_64 (void)
+{
+    T0 = ((uint64_t)regs->ctr == 0 && (T0 & PARAM1) != 0);
+    RETURN();
+}
+#endif
+
+void OPPROTO op_test_ctrz_false (void)
+{
+    T0 = ((uint32_t)regs->ctr == 0 && (T0 & PARAM1) == 0);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_test_ctrz_false_64 (void)
+{
+    T0 = ((uint64_t)regs->ctr == 0 && (T0 & PARAM1) == 0);
+    RETURN();
+}
+#endif
+
 PPC_OP(test_true)
 {
     T0 = (T0 & PARAM(1));
+    RETURN();
 }
 
 PPC_OP(test_false)
 {
     T0 = ((T0 & PARAM(1)) == 0);
+    RETURN();
 }
 
 /* CTR maintenance */
@@ -555,191 +735,296 @@
     RETURN();
 }
 
-void do_addo (void);
-void op_addo (void)
+void OPPROTO op_check_addo (void)
 {
-    do_addo();
+    if (likely(!(((uint32_t)T2 ^ (uint32_t)T1 ^ UINT32_MAX) &
+                 ((uint32_t)T2 ^ (uint32_t)T0) & (1UL << 31)))) {
+        xer_ov = 0;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+    }
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_check_addo_64 (void)
+{
+    if (likely(!(((uint64_t)T2 ^ (uint64_t)T1 ^ UINT64_MAX) &
+                 ((uint64_t)T2 ^ (uint64_t)T0) & (1ULL << 63)))) {
+        xer_ov = 0;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+    }
+    RETURN();
+}
+#endif
+
 /* add carrying */
-PPC_OP(addc)
+void OPPROTO op_check_addc (void)
 {
-    T2 = T0;
-    T0 += T1;
-    if (T0 < T2) {
+    if (likely((uint32_t)T0 >= (uint32_t)T2)) {
+        xer_ca = 0;
+    } else {
         xer_ca = 1;
-    } else {
-        xer_ca = 0;
     }
     RETURN();
 }
 
-void do_addco (void);
-void op_addco (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_check_addc_64 (void)
 {
-    do_addco();
+    if (likely((uint64_t)T0 >= (uint64_t)T2)) {
+        xer_ca = 0;
+    } else {
+        xer_ca = 1;
+    }
     RETURN();
 }
+#endif
 
 /* add extended */
-void do_adde (void);
-void op_adde (void)
+void OPPROTO op_adde (void)
 {
     do_adde();
+    RETURN();
 }
 
-void do_addeo (void);
-PPC_OP(addeo)
+#if defined(TARGET_PPC64)
+void OPPROTO op_adde_64 (void)
 {
-    do_addeo();
+    do_adde_64();
     RETURN();
 }
+#endif
 
 /* add immediate */
 PPC_OP(addi)
 {
-    T0 += PARAM(1);
+    T0 += (int32_t)PARAM(1);
     RETURN();
 }
 
-/* add immediate carrying */
-PPC_OP(addic)
+/* add to minus one extended */
+void OPPROTO op_add_me (void)
 {
-    T1 = T0;
-    T0 += PARAM(1);
-    if (T0 < T1) {
+    T0 += xer_ca + (-1);
+    if (likely((uint32_t)T1 != 0))
         xer_ca = 1;
-    } else {
-        xer_ca = 0;
-    }
     RETURN();
 }
 
-/* add to minus one extended */
-PPC_OP(addme)
+#if defined(TARGET_PPC64)
+void OPPROTO op_add_me_64 (void)
 {
-    T1 = T0;
     T0 += xer_ca + (-1);
-    if (T1 != 0)
+    if (likely((uint64_t)T1 != 0))
         xer_ca = 1;
     RETURN();
 }
+#endif
 
-void do_addmeo (void);
-void op_addmeo (void)
+void OPPROTO op_addmeo (void)
 {
     do_addmeo();
     RETURN();
 }
 
+void OPPROTO op_addmeo_64 (void)
+{
+    do_addmeo();
+    RETURN();
+}
+
 /* add to zero extended */
-PPC_OP(addze)
+void OPPROTO op_add_ze (void)
 {
-    T1 = T0;
     T0 += xer_ca;
-    if (T0 < T1) {
-        xer_ca = 1;
-    } else {
-        xer_ca = 0;
-    }
     RETURN();
 }
 
-void do_addzeo (void);
-void op_addzeo (void)
+/* divide word */
+void OPPROTO op_divw (void)
 {
-    do_addzeo();
+    if (unlikely(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
+                 (int32_t)T1 == 0)) {
+        T0 = (int32_t)((-1) * ((uint32_t)T0 >> 31));
+    } else {
+        T0 = (int32_t)T0 / (int32_t)T1;
+    }
     RETURN();
 }
 
-/* divide word */
-PPC_OP(divw)
+#if defined(TARGET_PPC64)
+void OPPROTO op_divd (void)
 {
-    if ((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0) {
-        T0 = (int32_t)((-1) * (T0 >> 31));
+    if (unlikely(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1) ||
+                 (int64_t)T1 == 0)) {
+        T0 = (int64_t)((-1ULL) * ((uint64_t)T0 >> 63));
     } else {
-        T0 = (Ts0 / Ts1);
+        T0 = (int64_t)T0 / (int64_t)T1;
     }
     RETURN();
 }
+#endif
 
-void do_divwo (void);
-void op_divwo (void)
+void OPPROTO op_divwo (void)
 {
     do_divwo();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_divdo (void)
+{
+    do_divdo();
+    RETURN();
+}
+#endif
+
 /* divide word unsigned */
-PPC_OP(divwu)
+void OPPROTO op_divwu (void)
 {
-    if (T1 == 0) {
+    if (unlikely(T1 == 0)) {
         T0 = 0;
     } else {
+        T0 = (uint32_t)T0 / (uint32_t)T1;
+    }
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_divdu (void)
+{
+    if (unlikely(T1 == 0)) {
+        T0 = 0;
+    } else {
         T0 /= T1;
     }
     RETURN();
 }
+#endif
 
-void do_divwuo (void);
-void op_divwuo (void)
+void OPPROTO op_divwuo (void)
 {
     do_divwuo();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_divduo (void)
+{
+    do_divduo();
+    RETURN();
+}
+#endif
+
 /* multiply high word */
-PPC_OP(mulhw)
+void OPPROTO op_mulhw (void)
 {
-    T0 = ((int64_t)Ts0 * (int64_t)Ts1) >> 32;
+    T0 = ((int64_t)((int32_t)T0) * (int64_t)((int32_t)T1)) >> 32;
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_mulhd (void)
+{
+    uint64_t tl, th;
+
+    do_imul64(&tl, &th);
+    T0 = th;
+    RETURN();
+}
+#endif
+
 /* multiply high word unsigned */
-PPC_OP(mulhwu)
+void OPPROTO op_mulhwu (void)
 {
-    T0 = ((uint64_t)T0 * (uint64_t)T1) >> 32;
+    T0 = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1) >> 32;
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_mulhdu (void)
+{
+    uint64_t tl, th;
+
+    do_mul64(&tl, &th);
+    T0 = th;
+    RETURN();
+}
+#endif
+
 /* multiply low immediate */
 PPC_OP(mulli)
 {
-    T0 = (Ts0 * SPARAM(1));
+    T0 = ((int32_t)T0 * (int32_t)PARAM1);
     RETURN();
 }
 
 /* multiply low word */
 PPC_OP(mullw)
 {
+    T0 = (int32_t)(T0 * T1);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_mulld (void)
+{
     T0 *= T1;
     RETURN();
 }
+#endif
 
-void do_mullwo (void);
-void op_mullwo (void)
+void OPPROTO op_mullwo (void)
 {
     do_mullwo();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_mulldo (void)
+{
+    do_mulldo();
+    RETURN();
+}
+#endif
+
 /* negate */
-PPC_OP(neg)
+void OPPROTO op_neg (void)
 {
-    if (T0 != 0x80000000) {
-        T0 = -Ts0;
+    if (likely(T0 != INT32_MIN)) {
+        T0 = -(int32_t)T0;
     }
     RETURN();
 }
 
-void do_nego (void);
-void op_nego (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_neg_64 (void)
 {
+    if (likely(T0 != INT64_MIN)) {
+        T0 = -(int64_t)T0;
+    }
+    RETURN();
+}
+#endif
+
+void OPPROTO op_nego (void)
+{
     do_nego();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_nego_64 (void)
+{
+    do_nego_64();
+    RETURN();
+}
+#endif
+
 /* substract from */
 PPC_OP(subf)
 {
@@ -747,52 +1032,75 @@
     RETURN();
 }
 
-void do_subfo (void);
-void op_subfo (void)
+void OPPROTO op_check_subfo (void)
 {
-    do_subfo();
+    if (likely(!(((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
+                 ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)))) {
+        xer_ov = 0;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+    }
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_check_subfo_64 (void)
+{
+    if (likely(!(((uint64_t)(~T2) ^ (uint64_t)T1 ^ UINT64_MAX) &
+                 ((uint64_t)(~T2) ^ (uint64_t)T0) & (1ULL << 63)))) {
+        xer_ov = 0;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+    }
+    RETURN();
+}
+#endif
+
 /* substract from carrying */
-PPC_OP(subfc)
+void OPPROTO op_check_subfc (void)
 {
-    T0 = T1 - T0;
-    if (T0 <= T1) {
+    if (likely((uint32_t)T0 > (uint32_t)T1)) {
+        xer_ca = 0;
+    } else {
         xer_ca = 1;
-    } else {
-        xer_ca = 0;
     }
     RETURN();
 }
 
-void do_subfco (void);
-void op_subfco (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_check_subfc_64 (void)
 {
-    do_subfco();
+    if (likely((uint64_t)T0 > (uint64_t)T1)) {
+        xer_ca = 0;
+    } else {
+        xer_ca = 1;
+    }
     RETURN();
 }
+#endif
 
 /* substract from extended */
-void do_subfe (void);
-void op_subfe (void)
+void OPPROTO op_subfe (void)
 {
     do_subfe();
     RETURN();
 }
 
-void do_subfeo (void);
-PPC_OP(subfeo)
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfe_64 (void)
 {
-    do_subfeo();
+    do_subfe_64();
     RETURN();
 }
+#endif
 
 /* substract from immediate carrying */
-PPC_OP(subfic)
+void OPPROTO op_subfic (void)
 {
-    T0 = PARAM(1) + ~T0 + 1;
-    if (T0 <= PARAM(1)) {
+    T0 = (int32_t)PARAM1 + ~T0 + 1;
+    if ((uint32_t)T0 <= (uint32_t)PARAM1) {
         xer_ca = 1;
     } else {
         xer_ca = 0;
@@ -800,29 +1108,58 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfic_64 (void)
+{
+    T0 = PARAM1 + ~T0 + 1;
+    if ((uint64_t)T0 <= (uint64_t)PARAM1) {
+        xer_ca = 1;
+    } else {
+        xer_ca = 0;
+    }
+    RETURN();
+}
+#endif
+
 /* substract from minus one extended */
-PPC_OP(subfme)
+void OPPROTO op_subfme (void)
 {
     T0 = ~T0 + xer_ca - 1;
+    if (likely((uint32_t)T0 != (uint32_t)-1))
+        xer_ca = 1;
+    RETURN();
+}
 
-    if (T0 != -1)
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfme_64 (void)
+{
+    T0 = ~T0 + xer_ca - 1;
+    if (likely((uint64_t)T0 != (uint64_t)-1))
         xer_ca = 1;
     RETURN();
 }
+#endif
 
-void do_subfmeo (void);
-void op_subfmeo (void)
+void OPPROTO op_subfmeo (void)
 {
     do_subfmeo();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfmeo_64 (void)
+{
+    do_subfmeo_64();
+    RETURN();
+}
+#endif
+
 /* substract from zero extended */
-PPC_OP(subfze)
+void OPPROTO op_subfze (void)
 {
     T1 = ~T0;
     T0 = T1 + xer_ca;
-    if (T0 < T1) {
+    if ((uint32_t)T0 < (uint32_t)T1) {
         xer_ca = 1;
     } else {
         xer_ca = 0;
@@ -830,20 +1167,41 @@
     RETURN();
 }
 
-void do_subfzeo (void);
-void op_subfzeo (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfze_64 (void)
 {
+    T1 = ~T0;
+    T0 = T1 + xer_ca;
+    if ((uint64_t)T0 < (uint64_t)T1) {
+        xer_ca = 1;
+    } else {
+        xer_ca = 0;
+    }
+    RETURN();
+}
+#endif
+
+void OPPROTO op_subfzeo (void)
+{
     do_subfzeo();
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_subfzeo_64 (void)
+{
+    do_subfzeo_64();
+    RETURN();
+}
+#endif
+
 /***                           Integer comparison                          ***/
 /* compare */
-PPC_OP(cmp)
+void OPPROTO op_cmp (void)
 {
-    if (Ts0 < Ts1) {
+    if ((int32_t)T0 < (int32_t)T1) {
         T0 = 0x08;
-    } else if (Ts0 > Ts1) {
+    } else if ((int32_t)T0 > (int32_t)T1) {
         T0 = 0x04;
     } else {
         T0 = 0x02;
@@ -851,12 +1209,26 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_cmp_64 (void)
+{
+    if ((int64_t)T0 < (int64_t)T1) {
+        T0 = 0x08;
+    } else if ((int64_t)T0 > (int64_t)T1) {
+        T0 = 0x04;
+    } else {
+        T0 = 0x02;
+    }
+    RETURN();
+}
+#endif
+
 /* compare immediate */
-PPC_OP(cmpi)
+void OPPROTO op_cmpi (void)
 {
-    if (Ts0 < SPARAM(1)) {
+    if ((int32_t)T0 < (int32_t)PARAM1) {
         T0 = 0x08;
-    } else if (Ts0 > SPARAM(1)) {
+    } else if ((int32_t)T0 > (int32_t)PARAM1) {
         T0 = 0x04;
     } else {
         T0 = 0x02;
@@ -864,12 +1236,26 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_cmpi_64 (void)
+{
+    if ((int64_t)T0 < (int64_t)((int32_t)PARAM1)) {
+        T0 = 0x08;
+    } else if ((int64_t)T0 > (int64_t)((int32_t)PARAM1)) {
+        T0 = 0x04;
+    } else {
+        T0 = 0x02;
+    }
+    RETURN();
+}
+#endif
+
 /* compare logical */
-PPC_OP(cmpl)
+void OPPROTO op_cmpl (void)
 {
-    if (T0 < T1) {
+    if ((uint32_t)T0 < (uint32_t)T1) {
         T0 = 0x08;
-    } else if (T0 > T1) {
+    } else if ((uint32_t)T0 > (uint32_t)T1) {
         T0 = 0x04;
     } else {
         T0 = 0x02;
@@ -877,12 +1263,26 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_cmpl_64 (void)
+{
+    if ((uint64_t)T0 < (uint64_t)T1) {
+        T0 = 0x08;
+    } else if ((uint64_t)T0 > (uint64_t)T1) {
+        T0 = 0x04;
+    } else {
+        T0 = 0x02;
+    }
+    RETURN();
+}
+#endif
+
 /* compare logical immediate */
-PPC_OP(cmpli)
+void OPPROTO op_cmpli (void)
 {
-    if (T0 < PARAM(1)) {
+    if ((uint32_t)T0 < (uint32_t)PARAM1) {
         T0 = 0x08;
-    } else if (T0 > PARAM(1)) {
+    } else if ((uint32_t)T0 > (uint32_t)PARAM1) {
         T0 = 0x04;
     } else {
         T0 = 0x02;
@@ -890,6 +1290,43 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_cmpli_64 (void)
+{
+    if ((uint64_t)T0 < (uint64_t)PARAM1) {
+        T0 = 0x08;
+    } else if ((uint64_t)T0 > (uint64_t)PARAM1) {
+        T0 = 0x04;
+    } else {
+        T0 = 0x02;
+    }
+    RETURN();
+}
+#endif
+
+void OPPROTO op_isel (void)
+{
+    if (T0)
+        T0 = T1;
+    else
+        T0 = T2;
+    RETURN();
+}
+
+void OPPROTO op_popcntb (void)
+{
+    do_popcntb();
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_popcntb_64 (void)
+{
+    do_popcntb_64();
+    RETURN();
+}
+#endif
+
 /***                            Integer logical                            ***/
 /* and */
 PPC_OP(and)
@@ -906,21 +1343,33 @@
 }
 
 /* andi. */
-PPC_OP(andi_)
+void OPPROTO op_andi_T0 (void)
 {
     T0 &= PARAM(1);
     RETURN();
 }
 
+void OPPROTO op_andi_T1 (void)
+{
+    T1 &= PARAM1;
+    RETURN();
+}
+
 /* count leading zero */
-PPC_OP(cntlzw)
+void OPPROTO op_cntlzw (void)
 {
-    T1 = T0;
-    for (T0 = 32; T1 > 0; T0--)
-        T1 = T1 >> 1;
+    T0 = _do_cntlzw(T0);
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_cntlzd (void)
+{
+    T0 = _do_cntlzd(T0);
+    RETURN();
+}
+#endif
+
 /* eqv */
 PPC_OP(eqv)
 {
@@ -929,19 +1378,35 @@
 }
 
 /* extend sign byte */
-PPC_OP(extsb)
+void OPPROTO op_extsb (void)
 {
-    T0 = (int32_t)((int8_t)(Ts0));
+#if defined (TARGET_PPC64)
+    T0 = (int64_t)((int8_t)T0);
+#else
+    T0 = (int32_t)((int8_t)T0);
+#endif
     RETURN();
 }
 
 /* extend sign half word */
-PPC_OP(extsh)
+void OPPROTO op_extsh (void)
 {
-    T0 = (int32_t)((int16_t)(Ts0));
+#if defined (TARGET_PPC64)
+    T0 = (int64_t)((int16_t)T0);
+#else
+    T0 = (int32_t)((int16_t)T0);
+#endif
     RETURN();
 }
 
+#if defined (TARGET_PPC64)
+void OPPROTO op_extsw (void)
+{
+    T0 = (int64_t)((int32_t)T0);
+    RETURN();
+}
+#endif
+
 /* nand */
 PPC_OP(nand)
 {
@@ -992,113 +1457,196 @@
 }
 
 /***                             Integer rotate                            ***/
-/* rotate left word immediate then mask insert */
-PPC_OP(rlwimi)
+void OPPROTO op_rotl32_T0_T1 (void)
 {
-    T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
+    T0 = rotl32(T0, T1 & 0x1F);
     RETURN();
 }
 
-/* rotate left immediate then and with mask insert */
-PPC_OP(rotlwi)
+void OPPROTO op_rotli32_T0 (void)
 {
-    T0 = rotl(T0, PARAM(1));
+    T0 = rotl32(T0, PARAM1);
     RETURN();
 }
 
-PPC_OP(slwi)
+#if defined(TARGET_PPC64)
+void OPPROTO op_rotl64_T0_T1 (void)
 {
-    T0 = T0 << PARAM(1);
+    T0 = rotl64(T0, T1 & 0x3F);
     RETURN();
 }
 
-PPC_OP(srwi)
+void OPPROTO op_rotli64_T0 (void)
 {
-    T0 = T0 >> PARAM(1);
+    T0 = rotl64(T0, PARAM1);
     RETURN();
 }
+#endif
 
-/* rotate left word then and with mask insert */
-PPC_OP(rlwinm)
+/***                             Integer shift                             ***/
+/* shift left word */
+void OPPROTO op_slw (void)
 {
-    T0 = rotl(T0, PARAM(1)) & PARAM(2);
+    if (T1 & 0x20) {
+        T0 = 0;
+    } else {
+        T0 = (uint32_t)(T0 << T1);
+    }
     RETURN();
 }
 
-PPC_OP(rotl)
+#if defined(TARGET_PPC64)
+void OPPROTO op_sld (void)
 {
-    T0 = rotl(T0, T1);
+    if (T1 & 0x40) {
+        T0 = 0;
+    } else {
+        T0 = T0 << T1;
+    }
     RETURN();
 }
+#endif
 
-PPC_OP(rlwnm)
+/* shift right algebraic word */
+void OPPROTO op_sraw (void)
 {
-    T0 = rotl(T0, T1) & PARAM(1);
+    do_sraw();
     RETURN();
 }
 
-/***                             Integer shift                             ***/
-/* shift left word */
-PPC_OP(slw)
+#if defined(TARGET_PPC64)
+void OPPROTO op_srad (void)
 {
-    if (T1 & 0x20) {
-        T0 = 0;
-    } else {
-        T0 = T0 << T1;
-    }
+    do_srad();
     RETURN();
 }
+#endif
 
-/* shift right algebraic word */
-void op_sraw (void)
+/* shift right algebraic word immediate */
+void OPPROTO op_srawi (void)
 {
-    do_sraw();
+    uint32_t mask = (uint32_t)PARAM2;
+
+    T0 = (int32_t)T0 >> PARAM1;
+    if ((int32_t)T1 < 0 && (T1 & mask) != 0) {
+        xer_ca = 1;
+    } else {
+        xer_ca = 0;
+    }
     RETURN();
 }
 
-/* shift right algebraic word immediate */
-PPC_OP(srawi)
+#if defined(TARGET_PPC64)
+void OPPROTO op_sradi (void)
 {
-    T1 = T0;
-    T0 = (Ts0 >> PARAM(1));
-    if (Ts1 < 0 && (Ts1 & PARAM(2)) != 0) {
+    uint64_t mask = ((uint64_t)PARAM2 << 32) | (uint64_t)PARAM3;
+
+    T0 = (int64_t)T0 >> PARAM1;
+    if ((int64_t)T1 < 0 && ((uint64_t)T1 & mask) != 0) {
         xer_ca = 1;
     } else {
         xer_ca = 0;
     }
     RETURN();
 }
+#endif
 
 /* shift right word */
-PPC_OP(srw)
+void OPPROTO op_srw (void)
 {
     if (T1 & 0x20) {
         T0 = 0;
     } else {
-        T0 = T0 >> T1;
+        T0 = (uint32_t)T0 >> T1;
     }
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_srd (void)
+{
+    if (T1 & 0x40) {
+        T0 = 0;
+    } else {
+        T0 = (uint64_t)T0 >> T1;
+    }
+    RETURN();
+}
+#endif
+
+void OPPROTO op_sl_T0_T1 (void)
+{
+    T0 = T0 << T1;
+    RETURN();
+}
+
+void OPPROTO op_sli_T0 (void)
+{
+    T0 = T0 << PARAM1;
+    RETURN();
+}
+
+void OPPROTO op_srl_T0_T1 (void)
+{
+    T0 = (uint32_t)T0 >> T1;
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_srl_T0_T1_64 (void)
+{
+    T0 = (uint32_t)T0 >> T1;
+    RETURN();
+}
+#endif
+
+void OPPROTO op_srli_T0 (void)
+{
+    T0 = (uint32_t)T0 >> PARAM1;
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_srli_T0_64 (void)
+{
+    T0 = (uint64_t)T0 >> PARAM1;
+    RETURN();
+}
+#endif
+
+void OPPROTO op_srli_T1 (void)
+{
+    T1 = (uint32_t)T1 >> PARAM1;
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_srli_T1_64 (void)
+{
+    T1 = (uint64_t)T1 >> PARAM1;
+    RETURN();
+}
+#endif
+
 /***                       Floating-Point arithmetic                       ***/
 /* fadd - fadd. */
 PPC_OP(fadd)
 {
-    FT0 += FT1;
+    FT0 = float64_add(FT0, FT1, &env->fp_status);
     RETURN();
 }
 
 /* fsub - fsub. */
 PPC_OP(fsub)
 {
-    FT0 -= FT1;
+    FT0 = float64_sub(FT0, FT1, &env->fp_status);
     RETURN();
 }
 
 /* fmul - fmul. */
 PPC_OP(fmul)
 {
-    FT0 *= FT1;
+    FT0 = float64_mul(FT0, FT1, &env->fp_status);
     RETURN();
 }
 
@@ -1141,14 +1689,24 @@
 /* fmadd - fmadd. */
 PPC_OP(fmadd)
 {
-    FT0 = (FT0 * FT1) + FT2;
+#if USE_PRECISE_EMULATION
+    do_fmadd();
+#else
+    FT0 = float64_mul(FT0, FT1, &env->fp_status);
+    FT0 = float64_add(FT0, FT2, &env->fp_status);
+#endif
     RETURN();
 }
 
 /* fmsub - fmsub. */
 PPC_OP(fmsub)
 {
-    FT0 = (FT0 * FT1) - FT2;
+#if USE_PRECISE_EMULATION
+    do_fmsub();
+#else
+    FT0 = float64_mul(FT0, FT1, &env->fp_status);
+    FT0 = float64_sub(FT0, FT2, &env->fp_status);
+#endif
     RETURN();
 }
 
@@ -1170,7 +1728,7 @@
 /* frsp - frsp. */
 PPC_OP(frsp)
 {
-    FT0 = (float)FT0;
+    FT0 = float64_to_float32(FT0, &env->fp_status);
     RETURN();
 }
 
@@ -1188,7 +1746,29 @@
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+/* fcfid - fcfid. */
+PPC_OP(fcfid)
+{
+    do_fcfid();
+    RETURN();
+}
 
+/* fctid - fctid. */
+PPC_OP(fctid)
+{
+    do_fctid();
+    RETURN();
+}
+
+/* fctidz - fctidz. */
+PPC_OP(fctidz)
+{
+    do_fctidz();
+    RETURN();
+}
+#endif
+
 /***                         Floating-Point compare                        ***/
 /* fcmpu */
 PPC_OP(fcmpu)
@@ -1229,52 +1809,67 @@
 
 /* Load and store */
 #define MEMSUFFIX _raw
+#include "op_helper.h"
 #include "op_mem.h"
 #if !defined(CONFIG_USER_ONLY)
 #define MEMSUFFIX _user
+#include "op_helper.h"
 #include "op_mem.h"
-
 #define MEMSUFFIX _kernel
+#include "op_helper.h"
 #include "op_mem.h"
 #endif
 
 /* Special op to check and maybe clear reservation */
-PPC_OP(check_reservation)
+void OPPROTO op_check_reservation (void)
 {
     if ((uint32_t)env->reserve == (uint32_t)(T0 & ~0x00000003))
         env->reserve = -1;
     RETURN();
 }
 
+#if defined(TARGET_PPC64)
+void OPPROTO op_check_reservation_64 (void)
+{
+    if ((uint64_t)env->reserve == (uint64_t)(T0 & ~0x00000003))
+        env->reserve = -1;
+    RETURN();
+}
+#endif
+
 /* Return from interrupt */
-void do_rfi (void);
-void op_rfi (void)
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_rfi (void)
 {
     do_rfi();
     RETURN();
 }
 
-/* Trap word */
-void do_tw (uint32_t cmp, int flags);
-void op_tw (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_rfid (void)
 {
-    do_tw(T1, PARAM(1));
+    do_rfid();
     RETURN();
 }
+#endif
+#endif
 
-void op_twi (void)
+/* Trap word */
+void OPPROTO op_tw (void)
 {
-    do_tw(PARAM(1), PARAM(2));
+    do_tw(PARAM1);
     RETURN();
 }
 
-/* Instruction cache block invalidate */
-PPC_OP(icbi)
+#if defined(TARGET_PPC64)
+void OPPROTO op_td (void)
 {
-    do_icbi();
+    do_td(PARAM1);
     RETURN();
 }
+#endif
 
+#if !defined(CONFIG_USER_ONLY)
 /* tlbia */
 PPC_OP(tlbia)
 {
@@ -1283,14 +1878,1324 @@
 }
 
 /* tlbie */
-PPC_OP(tlbie)
+void OPPROTO op_tlbie (void)
 {
     do_tlbie();
     RETURN();
 }
 
-void op_store_pir (void)
+#if defined(TARGET_PPC64)
+void OPPROTO op_tlbie_64 (void)
 {
+    do_tlbie_64();
+    RETURN();
+}
+#endif
+
+#if defined(TARGET_PPC64)
+void OPPROTO op_slbia (void)
+{
+    do_slbia();
+    RETURN();
+}
+
+void OPPROTO op_slbie (void)
+{
+    do_slbie();
+    RETURN();
+}
+#endif
+#endif
+
+/* PowerPC 602/603/755 software TLB load instructions */
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_6xx_tlbld (void)
+{
+    do_load_6xx_tlb(0);
+    RETURN();
+}
+
+void OPPROTO op_6xx_tlbli (void)
+{
+    do_load_6xx_tlb(1);
+    RETURN();
+}
+#endif
+
+/* 601 specific */
+void OPPROTO op_load_601_rtcl (void)
+{
+    T0 = cpu_ppc601_load_rtcl(env);
+    RETURN();
+}
+
+void OPPROTO op_load_601_rtcu (void)
+{
+    T0 = cpu_ppc601_load_rtcu(env);
+    RETURN();
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_store_601_rtcl (void)
+{
+    cpu_ppc601_store_rtcl(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_601_rtcu (void)
+{
+    cpu_ppc601_store_rtcu(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_load_601_bat (void)
+{
+    T0 = env->IBAT[PARAM1][PARAM2];
+    RETURN();
+}
+#endif /* !defined(CONFIG_USER_ONLY) */
+
+/* 601 unified BATs store.
+ * To avoid using specific MMU code for 601, we store BATs in
+ * IBAT and DBAT simultaneously, then emulate unified BATs.
+ */
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_store_601_batl (void)
+{
+    int nr = PARAM1;
+
+    env->IBAT[1][nr] = T0;
+    env->DBAT[1][nr] = T0;
+    RETURN();
+}
+
+void OPPROTO op_store_601_batu (void)
+{
+    do_store_601_batu(PARAM1);
+    RETURN();
+}
+#endif /* !defined(CONFIG_USER_ONLY) */
+
+/* PowerPC 601 specific instructions (POWER bridge) */
+/* XXX: those micro-ops need tests ! */
+void OPPROTO op_POWER_abs (void)
+{
+    if (T0 == INT32_MIN)
+        T0 = INT32_MAX;
+    else if (T0 < 0)
+        T0 = -T0;
+    RETURN();
+}
+
+void OPPROTO op_POWER_abso (void)
+{
+    do_POWER_abso();
+    RETURN();
+}
+
+void OPPROTO op_POWER_clcs (void)
+{
+    do_POWER_clcs();
+    RETURN();
+}
+
+void OPPROTO op_POWER_div (void)
+{
+    do_POWER_div();
+    RETURN();
+}
+
+void OPPROTO op_POWER_divo (void)
+{
+    do_POWER_divo();
+    RETURN();
+}
+
+void OPPROTO op_POWER_divs (void)
+{
+    do_POWER_divs();
+    RETURN();
+}
+
+void OPPROTO op_POWER_divso (void)
+{
+    do_POWER_divso();
+    RETURN();
+}
+
+void OPPROTO op_POWER_doz (void)
+{
+    if ((int32_t)T1 > (int32_t)T0)
+        T0 = T1 - T0;
+    else
+        T0 = 0;
+    RETURN();
+}
+
+void OPPROTO op_POWER_dozo (void)
+{
+    do_POWER_dozo();
+    RETURN();
+}
+
+void OPPROTO op_load_xer_cmp (void)
+{
+    T2 = xer_cmp;
+    RETURN();
+}
+
+void OPPROTO op_POWER_maskg (void)
+{
+    do_POWER_maskg();
+    RETURN();
+}
+
+void OPPROTO op_POWER_maskir (void)
+{
+    T0 = (T0 & ~T2) | (T1 & T2);
+    RETURN();
+}
+
+void OPPROTO op_POWER_mul (void)
+{
+    uint64_t tmp;
+
+    tmp = (uint64_t)T0 * (uint64_t)T1;
+    env->spr[SPR_MQ] = tmp >> 32;
+    T0 = tmp;
+    RETURN();
+}
+
+void OPPROTO op_POWER_mulo (void)
+{
+    do_POWER_mulo();
+    RETURN();
+}
+
+void OPPROTO op_POWER_nabs (void)
+{
+    if (T0 > 0)
+        T0 = -T0;
+    RETURN();
+}
+
+void OPPROTO op_POWER_nabso (void)
+{
+    /* nabs never overflows */
+    if (T0 > 0)
+        T0 = -T0;
+    xer_ov = 0;
+    RETURN();
+}
+
+/* XXX: factorise POWER rotates... */
+void OPPROTO op_POWER_rlmi (void)
+{
+    T0 = rotl32(T0, T2) & PARAM1;
+    T0 |= T1 & PARAM2;
+    RETURN();
+}
+
+void OPPROTO op_POWER_rrib (void)
+{
+    T2 &= 0x1FUL;
+    T0 = rotl32(T0 & INT32_MIN, T2);
+    T0 |= T1 & ~rotl32(INT32_MIN, T2);
+    RETURN();
+}
+
+void OPPROTO op_POWER_sle (void)
+{
+    T1 &= 0x1FUL;
+    env->spr[SPR_MQ] = rotl32(T0, T1);
+    T0 = T0 << T1;
+    RETURN();
+}
+
+void OPPROTO op_POWER_sleq (void)
+{
+    uint32_t tmp = env->spr[SPR_MQ];
+
+    T1 &= 0x1FUL;
+    env->spr[SPR_MQ] = rotl32(T0, T1);
+    T0 = T0 << T1;
+    T0 |= tmp >> (32 - T1);
+    RETURN();
+}
+
+void OPPROTO op_POWER_sllq (void)
+{
+    uint32_t msk = -1;
+
+    msk = msk << (T1 & 0x1FUL);
+    if (T1 & 0x20UL)
+        msk = ~msk;
+    T1 &= 0x1FUL;
+    T0 = (T0 << T1) & msk;
+    T0 |= env->spr[SPR_MQ] & ~msk;
+    RETURN();
+}
+
+void OPPROTO op_POWER_slq (void)
+{
+    uint32_t msk = -1, tmp;
+
+    msk = msk << (T1 & 0x1FUL);
+    if (T1 & 0x20UL)
+        msk = ~msk;
+    T1 &= 0x1FUL;
+    tmp = rotl32(T0, T1);
+    T0 = tmp & msk;
+    env->spr[SPR_MQ] = tmp;
+    RETURN();
+}
+
+void OPPROTO op_POWER_sraq (void)
+{
+    env->spr[SPR_MQ] = rotl32(T0, 32 - (T1 & 0x1FUL));
+    if (T1 & 0x20UL)
+        T0 = -1L;
+    else
+        T0 = (int32_t)T0 >> T1;
+    RETURN();
+}
+
+void OPPROTO op_POWER_sre (void)
+{
+    T1 &= 0x1FUL;
+    env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
+    T0 = (int32_t)T0 >> T1;
+    RETURN();
+}
+
+void OPPROTO op_POWER_srea (void)
+{
+    T1 &= 0x1FUL;
+    env->spr[SPR_MQ] = T0 >> T1;
+    T0 = (int32_t)T0 >> T1;
+    RETURN();
+}
+
+void OPPROTO op_POWER_sreq (void)
+{
+    uint32_t tmp;
+    int32_t msk;
+
+    T1 &= 0x1FUL;
+    msk = INT32_MIN >> T1;
+    tmp = env->spr[SPR_MQ];
+    env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
+    T0 = T0 >> T1;
+    T0 |= tmp & msk;
+    RETURN();
+}
+
+void OPPROTO op_POWER_srlq (void)
+{
+    uint32_t tmp;
+    int32_t msk;
+
+    msk = INT32_MIN >> (T1 & 0x1FUL);
+    if (T1 & 0x20UL)
+        msk = ~msk;
+    T1 &= 0x1FUL;
+    tmp = env->spr[SPR_MQ];
+    env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
+    T0 = T0 >> T1;
+    T0 &= msk;
+    T0 |= tmp & ~msk;
+    RETURN();
+}
+
+void OPPROTO op_POWER_srq (void)
+{
+    T1 &= 0x1FUL;
+    env->spr[SPR_MQ] = rotl32(T0, 32 - T1);
+    T0 = T0 >> T1;
+    RETURN();
+}
+
+/* POWER instructions not implemented in PowerPC 601 */
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_POWER_mfsri (void)
+{
+    T1 = T0 >> 28;
+    T0 = env->sr[T1];
+    RETURN();
+}
+
+void OPPROTO op_POWER_rac (void)
+{
+    do_POWER_rac();
+    RETURN();
+}
+
+void OPPROTO op_POWER_rfsvc (void)
+{
+    do_POWER_rfsvc();
+    RETURN();
+}
+#endif
+
+/* PowerPC 602 specific instruction */
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_602_mfrom (void)
+{
+    do_op_602_mfrom();
+    RETURN();
+}
+#endif
+
+/* PowerPC 4xx specific micro-ops */
+void OPPROTO op_405_add_T0_T2 (void)
+{
+    T0 = (int32_t)T0 + (int32_t)T2;
+    RETURN();
+}
+
+void OPPROTO op_405_mulchw (void)
+{
+    T0 = ((int16_t)T0) * ((int16_t)(T1 >> 16));
+    RETURN();
+}
+
+void OPPROTO op_405_mulchwu (void)
+{
+    T0 = ((uint16_t)T0) * ((uint16_t)(T1 >> 16));
+    RETURN();
+}
+
+void OPPROTO op_405_mulhhw (void)
+{
+    T0 = ((int16_t)(T0 >> 16)) * ((int16_t)(T1 >> 16));
+    RETURN();
+}
+
+void OPPROTO op_405_mulhhwu (void)
+{
+    T0 = ((uint16_t)(T0 >> 16)) * ((uint16_t)(T1 >> 16));
+    RETURN();
+}
+
+void OPPROTO op_405_mullhw (void)
+{
+    T0 = ((int16_t)T0) * ((int16_t)T1);
+    RETURN();
+}
+
+void OPPROTO op_405_mullhwu (void)
+{
+    T0 = ((uint16_t)T0) * ((uint16_t)T1);
+    RETURN();
+}
+
+void OPPROTO op_405_check_ov (void)
+{
+    do_405_check_ov();
+    RETURN();
+}
+
+void OPPROTO op_405_check_sat (void)
+{
+    do_405_check_sat();
+    RETURN();
+}
+
+void OPPROTO op_405_check_ovu (void)
+{
+    if (likely(T0 >= T2)) {
+        xer_ov = 0;
+    } else {
+        xer_ov = 1;
+        xer_so = 1;
+    }
+    RETURN();
+}
+
+void OPPROTO op_405_check_satu (void)
+{
+    if (unlikely(T0 < T2)) {
+        /* Saturate result */
+        T0 = -1;
+    }
+    RETURN();
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_load_dcr (void)
+{
+    do_load_dcr();
+    RETURN();
+}
+
+void OPPROTO op_store_dcr (void)
+{
+    do_store_dcr();
+    RETURN();
+}
+
+/* Return from critical interrupt :
+ * same as rfi, except nip & MSR are loaded from SRR2/3 instead of SRR0/1
+ */
+void OPPROTO op_40x_rfci (void)
+{
+    do_40x_rfci();
+    RETURN();
+}
+
+void OPPROTO op_rfci (void)
+{
+    do_rfci();
+    RETURN();
+}
+
+void OPPROTO op_rfdi (void)
+{
+    do_rfdi();
+    RETURN();
+}
+
+void OPPROTO op_rfmci (void)
+{
+    do_rfmci();
+    RETURN();
+}
+
+void OPPROTO op_wrte (void)
+{
+    msr_ee = T0 >> 16;
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbre_lo (void)
+{
+    do_4xx_tlbre_lo();
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbre_hi (void)
+{
+    do_4xx_tlbre_hi();
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbsx (void)
+{
+    do_4xx_tlbsx();
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbsx_ (void)
+{
+    do_4xx_tlbsx_();
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbwe_lo (void)
+{
+    do_4xx_tlbwe_lo();
+    RETURN();
+}
+
+void OPPROTO op_4xx_tlbwe_hi (void)
+{
+    do_4xx_tlbwe_hi();
+    RETURN();
+}
+#endif
+
+/* SPR micro-ops */
+/* 440 specific */
+void OPPROTO op_440_dlmzb (void)
+{
+    do_440_dlmzb();
+    RETURN();
+}
+
+void OPPROTO op_440_dlmzb_update_Rc (void)
+{
+    if (T0 == 8)
+        T0 = 0x2;
+    else if (T0 < 4)
+        T0 = 0x4;
+    else
+        T0 = 0x8;
+    RETURN();
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void OPPROTO op_store_pir (void)
+{
     env->spr[SPR_PIR] = T0 & 0x0000000FUL;
     RETURN();
 }
+
+void OPPROTO op_load_403_pb (void)
+{
+    do_load_403_pb(PARAM1);
+    RETURN();
+}
+
+void OPPROTO op_store_403_pb (void)
+{
+    do_store_403_pb(PARAM1);
+    RETURN();
+}
+
+void OPPROTO op_load_40x_pit (void)
+{
+    T0 = load_40x_pit(env);
+    RETURN();
+}
+
+void OPPROTO op_store_40x_pit (void)
+{
+    store_40x_pit(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_40x_dbcr0 (void)
+{
+    store_40x_dbcr0(env, T0);
+}
+
+void OPPROTO op_store_40x_sler (void)
+{
+    store_40x_sler(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_booke_tcr (void)
+{
+    store_booke_tcr(env, T0);
+    RETURN();
+}
+
+void OPPROTO op_store_booke_tsr (void)
+{
+    store_booke_tsr(env, T0);
+    RETURN();
+}
+
+#endif /* !defined(CONFIG_USER_ONLY) */
+
+#if defined(TARGET_PPCEMB)
+/* SPE extension */
+void OPPROTO op_splatw_T1_64 (void)
+{
+    T1_64 = (T1_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
+    RETURN();
+}
+
+void OPPROTO op_splatwi_T0_64 (void)
+{
+    uint64_t tmp = PARAM1;
+
+    T0_64 = (tmp << 32) | tmp;
+    RETURN();
+}
+
+void OPPROTO op_splatwi_T1_64 (void)
+{
+    uint64_t tmp = PARAM1;
+
+    T1_64 = (tmp << 32) | tmp;
+    RETURN();
+}
+
+void OPPROTO op_extsh_T1_64 (void)
+{
+    T1_64 = (int32_t)((int16_t)T1_64);
+    RETURN();
+}
+
+void OPPROTO op_sli16_T1_64 (void)
+{
+    T1_64 = T1_64 << 16;
+    RETURN();
+}
+
+void OPPROTO op_sli32_T1_64 (void)
+{
+    T1_64 = T1_64 << 32;
+    RETURN();
+}
+
+void OPPROTO op_srli32_T1_64 (void)
+{
+    T1_64 = T1_64 >> 32;
+    RETURN();
+}
+
+void OPPROTO op_evsel (void)
+{
+    do_evsel();
+    RETURN();
+}
+
+void OPPROTO op_evaddw (void)
+{
+    do_evaddw();
+    RETURN();
+}
+
+void OPPROTO op_evsubfw (void)
+{
+    do_evsubfw();
+    RETURN();
+}
+
+void OPPROTO op_evneg (void)
+{
+    do_evneg();
+    RETURN();
+}
+
+void OPPROTO op_evabs (void)
+{
+    do_evabs();
+    RETURN();
+}
+
+void OPPROTO op_evextsh (void)
+{
+    T0_64 = ((uint64_t)((int32_t)(int16_t)(T0_64 >> 32)) << 32) |
+        (uint64_t)((int32_t)(int16_t)T0_64);
+    RETURN();
+}
+
+void OPPROTO op_evextsb (void)
+{
+    T0_64 = ((uint64_t)((int32_t)(int8_t)(T0_64 >> 32)) << 32) |
+        (uint64_t)((int32_t)(int8_t)T0_64);
+    RETURN();
+}
+
+void OPPROTO op_evcntlzw (void)
+{
+    do_evcntlzw();
+    RETURN();
+}
+
+void OPPROTO op_evrndw (void)
+{
+    do_evrndw();
+    RETURN();
+}
+
+void OPPROTO op_brinc (void)
+{
+    do_brinc();
+    RETURN();
+}
+
+void OPPROTO op_evcntlsw (void)
+{
+    do_evcntlsw();
+    RETURN();
+}
+
+void OPPROTO op_evand (void)
+{
+    T0_64 &= T1_64;
+    RETURN();
+}
+
+void OPPROTO op_evandc (void)
+{
+    T0_64 &= ~T1_64;
+    RETURN();
+}
+
+void OPPROTO op_evor (void)
+{
+    T0_64 |= T1_64;
+    RETURN();
+}
+
+void OPPROTO op_evxor (void)
+{
+    T0_64 ^= T1_64;
+    RETURN();
+}
+
+void OPPROTO op_eveqv (void)
+{
+    T0_64 = ~(T0_64 ^ T1_64);
+    RETURN();
+}
+
+void OPPROTO op_evnor (void)
+{
+    T0_64 = ~(T0_64 | T1_64);
+    RETURN();
+}
+
+void OPPROTO op_evorc (void)
+{
+    T0_64 |= ~T1_64;
+    RETURN();
+}
+
+void OPPROTO op_evnand (void)
+{
+    T0_64 = ~(T0_64 & T1_64);
+    RETURN();
+}
+
+void OPPROTO op_evsrws (void)
+{
+    do_evsrws();
+    RETURN();
+}
+
+void OPPROTO op_evsrwu (void)
+{
+    do_evsrwu();
+    RETURN();
+}
+
+void OPPROTO op_evslw (void)
+{
+    do_evslw();
+    RETURN();
+}
+
+void OPPROTO op_evrlw (void)
+{
+    do_evrlw();
+    RETURN();
+}
+
+void OPPROTO op_evmergelo (void)
+{
+    T0_64 = (T0_64 << 32) | (T1_64 & 0x00000000FFFFFFFFULL);
+    RETURN();
+}
+
+void OPPROTO op_evmergehi (void)
+{
+    T0_64 = (T0_64 & 0xFFFFFFFF00000000ULL) | (T1_64 >> 32);
+    RETURN();
+}
+
+void OPPROTO op_evmergelohi (void)
+{
+    T0_64 = (T0_64 << 32) | (T1_64 >> 32);
+    RETURN();
+}
+
+void OPPROTO op_evmergehilo (void)
+{
+    T0_64 = (T0_64 & 0xFFFFFFFF00000000ULL) | (T1_64 & 0x00000000FFFFFFFFULL);
+    RETURN();
+}
+
+void OPPROTO op_evcmpgts (void)
+{
+    do_evcmpgts();
+    RETURN();
+}
+
+void OPPROTO op_evcmpgtu (void)
+{
+    do_evcmpgtu();
+    RETURN();
+}
+
+void OPPROTO op_evcmplts (void)
+{
+    do_evcmplts();
+    RETURN();
+}
+
+void OPPROTO op_evcmpltu (void)
+{
+    do_evcmpltu();
+    RETURN();
+}
+
+void OPPROTO op_evcmpeq (void)
+{
+    do_evcmpeq();
+    RETURN();
+}
+
+void OPPROTO op_evfssub (void)
+{
+    do_evfssub();
+    RETURN();
+}
+
+void OPPROTO op_evfsadd (void)
+{
+    do_evfsadd();
+    RETURN();
+}
+
+void OPPROTO op_evfsnabs (void)
+{
+    do_evfsnabs();
+    RETURN();
+}
+
+void OPPROTO op_evfsabs (void)
+{
+    do_evfsabs();
+    RETURN();
+}
+
+void OPPROTO op_evfsneg (void)
+{
+    do_evfsneg();
+    RETURN();
+}
+
+void OPPROTO op_evfsdiv (void)
+{
+    do_evfsdiv();
+    RETURN();
+}
+
+void OPPROTO op_evfsmul (void)
+{
+    do_evfsmul();
+    RETURN();
+}
+
+void OPPROTO op_evfscmplt (void)
+{
+    do_evfscmplt();
+    RETURN();
+}
+
+void OPPROTO op_evfscmpgt (void)
+{
+    do_evfscmpgt();
+    RETURN();
+}
+
+void OPPROTO op_evfscmpeq (void)
+{
+    do_evfscmpeq();
+    RETURN();
+}
+
+void OPPROTO op_evfscfsi (void)
+{
+    do_evfscfsi();
+    RETURN();
+}
+
+void OPPROTO op_evfscfui (void)
+{
+    do_evfscfui();
+    RETURN();
+}
+
+void OPPROTO op_evfscfsf (void)
+{
+    do_evfscfsf();
+    RETURN();
+}
+
+void OPPROTO op_evfscfuf (void)
+{
+    do_evfscfuf();
+    RETURN();
+}
+
+void OPPROTO op_evfsctsi (void)
+{
+    do_evfsctsi();
+    RETURN();
+}
+
+void OPPROTO op_evfsctui (void)
+{
+    do_evfsctui();
+    RETURN();
+}
+
+void OPPROTO op_evfsctsf (void)
+{
+    do_evfsctsf();
+    RETURN();
+}
+
+void OPPROTO op_evfsctuf (void)
+{
+    do_evfsctuf();
+    RETURN();
+}
+
+void OPPROTO op_evfsctuiz (void)
+{
+    do_evfsctuiz();
+    RETURN();
+}
+
+void OPPROTO op_evfsctsiz (void)
+{
+    do_evfsctsiz();
+    RETURN();
+}
+
+void OPPROTO op_evfststlt (void)
+{
+    do_evfststlt();
+    RETURN();
+}
+
+void OPPROTO op_evfststgt (void)
+{
+    do_evfststgt();
+    RETURN();
+}
+
+void OPPROTO op_evfststeq (void)
+{
+    do_evfststeq();
+    RETURN();
+}
+
+void OPPROTO op_efssub (void)
+{
+    T0_64 = _do_efssub(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efsadd (void)
+{
+    T0_64 = _do_efsadd(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efsnabs (void)
+{
+    T0_64 = _do_efsnabs(T0_64);
+    RETURN();
+}
+
+void OPPROTO op_efsabs (void)
+{
+    T0_64 = _do_efsabs(T0_64);
+    RETURN();
+}
+
+void OPPROTO op_efsneg (void)
+{
+    T0_64 = _do_efsneg(T0_64);
+    RETURN();
+}
+
+void OPPROTO op_efsdiv (void)
+{
+    T0_64 = _do_efsdiv(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efsmul (void)
+{
+    T0_64 = _do_efsmul(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efscmplt (void)
+{
+    do_efscmplt();
+    RETURN();
+}
+
+void OPPROTO op_efscmpgt (void)
+{
+    do_efscmpgt();
+    RETURN();
+}
+
+void OPPROTO op_efscfd (void)
+{
+    do_efscfd();
+    RETURN();
+}
+
+void OPPROTO op_efscmpeq (void)
+{
+    do_efscmpeq();
+    RETURN();
+}
+
+void OPPROTO op_efscfsi (void)
+{
+    do_efscfsi();
+    RETURN();
+}
+
+void OPPROTO op_efscfui (void)
+{
+    do_efscfui();
+    RETURN();
+}
+
+void OPPROTO op_efscfsf (void)
+{
+    do_efscfsf();
+    RETURN();
+}
+
+void OPPROTO op_efscfuf (void)
+{
+    do_efscfuf();
+    RETURN();
+}
+
+void OPPROTO op_efsctsi (void)
+{
+    do_efsctsi();
+    RETURN();
+}
+
+void OPPROTO op_efsctui (void)
+{
+    do_efsctui();
+    RETURN();
+}
+
+void OPPROTO op_efsctsf (void)
+{
+    do_efsctsf();
+    RETURN();
+}
+
+void OPPROTO op_efsctuf (void)
+{
+    do_efsctuf();
+    RETURN();
+}
+
+void OPPROTO op_efsctsiz (void)
+{
+    do_efsctsiz();
+    RETURN();
+}
+
+void OPPROTO op_efsctuiz (void)
+{
+    do_efsctuiz();
+    RETURN();
+}
+
+void OPPROTO op_efststlt (void)
+{
+    T0 = _do_efststlt(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efststgt (void)
+{
+    T0 = _do_efststgt(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efststeq (void)
+{
+    T0 = _do_efststeq(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efdsub (void)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = T0_64;
+    u2.u = T1_64;
+    u1.f = float64_sub(u1.f, u2.f, &env->spe_status);
+    T0_64 = u1.u;
+    RETURN();
+}
+
+void OPPROTO op_efdadd (void)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = T0_64;
+    u2.u = T1_64;
+    u1.f = float64_add(u1.f, u2.f, &env->spe_status);
+    T0_64 = u1.u;
+    RETURN();
+}
+
+void OPPROTO op_efdcfsid (void)
+{
+    do_efdcfsi();
+    RETURN();
+}
+
+void OPPROTO op_efdcfuid (void)
+{
+    do_efdcfui();
+    RETURN();
+}
+
+void OPPROTO op_efdnabs (void)
+{
+    T0_64 |= 0x8000000000000000ULL;
+    RETURN();
+}
+
+void OPPROTO op_efdabs (void)
+{
+    T0_64 &= ~0x8000000000000000ULL;
+    RETURN();
+}
+
+void OPPROTO op_efdneg (void)
+{
+    T0_64 ^= 0x8000000000000000ULL;
+    RETURN();
+}
+
+void OPPROTO op_efddiv (void)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = T0_64;
+    u2.u = T1_64;
+    u1.f = float64_div(u1.f, u2.f, &env->spe_status);
+    T0_64 = u1.u;
+    RETURN();
+}
+
+void OPPROTO op_efdmul (void)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = T0_64;
+    u2.u = T1_64;
+    u1.f = float64_mul(u1.f, u2.f, &env->spe_status);
+    T0_64 = u1.u;
+    RETURN();
+}
+
+void OPPROTO op_efdctsidz (void)
+{
+    do_efdctsiz();
+    RETURN();
+}
+
+void OPPROTO op_efdctuidz (void)
+{
+    do_efdctuiz();
+    RETURN();
+}
+
+void OPPROTO op_efdcmplt (void)
+{
+    do_efdcmplt();
+    RETURN();
+}
+
+void OPPROTO op_efdcmpgt (void)
+{
+    do_efdcmpgt();
+    RETURN();
+}
+
+void OPPROTO op_efdcfs (void)
+{
+    do_efdcfs();
+    RETURN();
+}
+
+void OPPROTO op_efdcmpeq (void)
+{
+    do_efdcmpeq();
+    RETURN();
+}
+
+void OPPROTO op_efdcfsi (void)
+{
+    do_efdcfsi();
+    RETURN();
+}
+
+void OPPROTO op_efdcfui (void)
+{
+    do_efdcfui();
+    RETURN();
+}
+
+void OPPROTO op_efdcfsf (void)
+{
+    do_efdcfsf();
+    RETURN();
+}
+
+void OPPROTO op_efdcfuf (void)
+{
+    do_efdcfuf();
+    RETURN();
+}
+
+void OPPROTO op_efdctsi (void)
+{
+    do_efdctsi();
+    RETURN();
+}
+
+void OPPROTO op_efdctui (void)
+{
+    do_efdctui();
+    RETURN();
+}
+
+void OPPROTO op_efdctsf (void)
+{
+    do_efdctsf();
+    RETURN();
+}
+
+void OPPROTO op_efdctuf (void)
+{
+    do_efdctuf();
+    RETURN();
+}
+
+void OPPROTO op_efdctuiz (void)
+{
+    do_efdctuiz();
+    RETURN();
+}
+
+void OPPROTO op_efdctsiz (void)
+{
+    do_efdctsiz();
+    RETURN();
+}
+
+void OPPROTO op_efdtstlt (void)
+{
+    T0 = _do_efdtstlt(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efdtstgt (void)
+{
+    T0 = _do_efdtstgt(T0_64, T1_64);
+    RETURN();
+}
+
+void OPPROTO op_efdtsteq (void)
+{
+    T0 = _do_efdtsteq(T0_64, T1_64);
+    RETURN();
+}
+#endif /* defined(TARGET_PPCEMB) */

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation helpers for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -19,26 +19,28 @@
  */
 #include "exec.h"
 
+#include "op_helper.h"
+
 #define MEMSUFFIX _raw
+#include "op_helper.h"
 #include "op_helper_mem.h"
 #if !defined(CONFIG_USER_ONLY)
 #define MEMSUFFIX _user
+#include "op_helper.h"
 #include "op_helper_mem.h"
 #define MEMSUFFIX _kernel
+#include "op_helper.h"
 #include "op_helper_mem.h"
 #endif
 
 //#define DEBUG_OP
 //#define DEBUG_EXCEPTIONS
+//#define DEBUG_SOFTWARE_TLB
 //#define FLUSH_ALL_TLBS
 
-#define Ts0 (long)((target_long)T0)
-#define Ts1 (long)((target_long)T1)
-#define Ts2 (long)((target_long)T2)
-
 /*****************************************************************************/
 /* Exceptions processing helpers */
-void cpu_loop_exit(void)
+void cpu_loop_exit (void)
 {
     longjmp(env->jmp_env, 1);
 }
@@ -50,86 +52,266 @@
 #endif
     switch (exception) {
     case EXCP_PROGRAM:
-	if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
-	    return;
-	break;
+        if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
+            return;
+        break;
     default:
-	break;
-}
+        break;
+    }
     env->exception_index = exception;
     env->error_code = error_code;
-        cpu_loop_exit();
-    }
+    cpu_loop_exit();
+}
 
 void do_raise_exception (uint32_t exception)
 {
     do_raise_exception_err(exception, 0);
 }
 
+void cpu_dump_EA (target_ulong EA);
+void do_print_mem_EA (target_ulong EA)
+{
+    cpu_dump_EA(EA);
+}
+
 /*****************************************************************************/
-/* Fixed point operations helpers */
-void do_addo (void)
+/* Registers load and stores */
+void do_load_cr (void)
 {
-    T2 = T0;
-    T0 += T1;
-    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_so = 1;
-        xer_ov = 1;
+    T0 = (env->crf[0] << 28) |
+        (env->crf[1] << 24) |
+        (env->crf[2] << 20) |
+        (env->crf[3] << 16) |
+        (env->crf[4] << 12) |
+        (env->crf[5] << 8) |
+        (env->crf[6] << 4) |
+        (env->crf[7] << 0);
+}
+
+void do_store_cr (uint32_t mask)
+{
+    int i, sh;
+
+    for (i = 0, sh = 7; i < 8; i++, sh --) {
+        if (mask & (1 << sh))
+            env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
     }
 }
 
-void do_addco (void)
+void do_load_xer (void)
 {
-    T2 = T0;
-    T0 += T1;
-    if (likely(T0 >= T2)) {
-        xer_ca = 0;
-    } else {
-        xer_ca = 1;
+    T0 = (xer_so << XER_SO) |
+        (xer_ov << XER_OV) |
+        (xer_ca << XER_CA) |
+        (xer_bc << XER_BC) |
+        (xer_cmp << XER_CMP);
+}
+
+void do_store_xer (void)
+{
+    xer_so = (T0 >> XER_SO) & 0x01;
+    xer_ov = (T0 >> XER_OV) & 0x01;
+    xer_ca = (T0 >> XER_CA) & 0x01;
+    xer_cmp = (T0 >> XER_CMP) & 0xFF;
+    xer_bc = (T0 >> XER_BC) & 0x7F;
+}
+
+void do_load_fpscr (void)
+{
+    /* The 32 MSB of the target fpr are undefined.
+     * They'll be zero...
+     */
+    union {
+        float64 d;
+        struct {
+            uint32_t u[2];
+        } s;
+    } u;
+    int i;
+
+#if defined(WORDS_BIGENDIAN)
+#define WORD0 0
+#define WORD1 1
+#else
+#define WORD0 1
+#define WORD1 0
+#endif
+    u.s.u[WORD0] = 0;
+    u.s.u[WORD1] = 0;
+    for (i = 0; i < 8; i++)
+        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
+    FT0 = u.d;
+}
+
+void do_store_fpscr (uint32_t mask)
+{
+    /*
+     * We use only the 32 LSB of the incoming fpr
+     */
+    union {
+        double d;
+        struct {
+            uint32_t u[2];
+        } s;
+    } u;
+    int i, rnd_type;
+
+    u.d = FT0;
+    if (mask & 0x80)
+        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
+    for (i = 1; i < 7; i++) {
+        if (mask & (1 << (7 - i)))
+            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
     }
-    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_so = 1;
-        xer_ov = 1;
+    /* TODO: update FEX & VX */
+    /* Set rounding mode */
+    switch (env->fpscr[0] & 0x3) {
+    case 0:
+        /* Best approximation (round to nearest) */
+        rnd_type = float_round_nearest_even;
+        break;
+    case 1:
+        /* Smaller magnitude (round toward zero) */
+        rnd_type = float_round_to_zero;
+        break;
+    case 2:
+        /* Round toward +infinite */
+        rnd_type = float_round_up;
+        break;
+    default:
+    case 3:
+        /* Round toward -infinite */
+        rnd_type = float_round_down;
+        break;
     }
+    set_float_rounding_mode(rnd_type, &env->fp_status);
 }
 
+target_ulong ppc_load_dump_spr (int sprn)
+{
+    if (loglevel != 0) {
+        fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
+                sprn, sprn, env->spr[sprn]);
+    }
+
+    return env->spr[sprn];
+}
+
+void ppc_store_dump_spr (int sprn, target_ulong val)
+{
+    if (loglevel != 0) {
+        fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
+                sprn, sprn, env->spr[sprn], val);
+    }
+    env->spr[sprn] = val;
+}
+
+/*****************************************************************************/
+/* Fixed point operations helpers */
+#if defined(TARGET_PPC64)
+static void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+    *plow += a;
+    /* carry test */
+    if (*plow < a)
+        (*phigh)++;
+    *phigh += b;
+}
+
+static void neg128 (uint64_t *plow, uint64_t *phigh)
+{
+    *plow = ~ *plow;
+    *phigh = ~ *phigh;
+    add128(plow, phigh, 1, 0);
+}
+
+static void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+    uint32_t a0, a1, b0, b1;
+    uint64_t v;
+
+    a0 = a;
+    a1 = a >> 32;
+
+    b0 = b;
+    b1 = b >> 32;
+    
+    v = (uint64_t)a0 * (uint64_t)b0;
+    *plow = v;
+    *phigh = 0;
+
+    v = (uint64_t)a0 * (uint64_t)b1;
+    add128(plow, phigh, v << 32, v >> 32);
+
+    v = (uint64_t)a1 * (uint64_t)b0;
+    add128(plow, phigh, v << 32, v >> 32);
+
+    v = (uint64_t)a1 * (uint64_t)b1;
+    *phigh += v;
+#if defined(DEBUG_MULDIV)
+    printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
+           a, b, *phigh, *plow);
+#endif
+}
+
+void do_mul64 (uint64_t *plow, uint64_t *phigh)
+{
+    mul64(plow, phigh, T0, T1);
+}
+
+static void imul64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
+{
+    int sa, sb;
+    sa = (a < 0);
+    if (sa)
+        a = -a;
+    sb = (b < 0);
+    if (sb)
+        b = -b;
+    mul64(plow, phigh, a, b);
+    if (sa ^ sb) {
+        neg128(plow, phigh);
+    }
+}
+
+void do_imul64 (uint64_t *plow, uint64_t *phigh)
+{
+    imul64(plow, phigh, T0, T1);
+}
+#endif
+
 void do_adde (void)
 {
     T2 = T0;
     T0 += T1 + xer_ca;
-    if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
+    if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
+                 (xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
         xer_ca = 0;
     } else {
         xer_ca = 1;
     }
 }
 
-void do_addeo (void)
+#if defined(TARGET_PPC64)
+void do_adde_64 (void)
 {
     T2 = T0;
     T0 += T1 + xer_ca;
-    if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
+    if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
+                 (xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
         xer_ca = 0;
     } else {
         xer_ca = 1;
     }
-    if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
-        xer_ov = 0;
-    } else {
-        xer_so = 1;
-        xer_ov = 1;
-    }
 }
+#endif
 
 void do_addmeo (void)
 {
     T1 = T0;
     T0 += xer_ca + (-1);
-    if (likely(!(T1 & (T1 ^ T0) & (1 << 31)))) {
+    if (likely(!((uint32_t)T1 &
+                 ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) {
         xer_ov = 0;
     } else {
         xer_so = 1;
@@ -139,28 +321,29 @@
         xer_ca = 1;
 }
 
-void do_addzeo (void)
+#if defined(TARGET_PPC64)
+void do_addmeo_64 (void)
 {
     T1 = T0;
-    T0 += xer_ca;
-    if (likely(!((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)))) {
+    T0 += xer_ca + (-1);
+    if (likely(!((uint64_t)T1 &
+                 ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) {
         xer_ov = 0;
     } else {
         xer_so = 1;
         xer_ov = 1;
     }
-    if (likely(T0 >= T1)) {
-        xer_ca = 0;
-    } else {
+    if (likely(T1 != 0))
         xer_ca = 1;
-    }
 }
+#endif
 
 void do_divwo (void)
 {
-    if (likely(!((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0))) {
+    if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) ||
+                 (int32_t)T1 == 0))) {
         xer_ov = 0;
-        T0 = (Ts0 / Ts1);
+        T0 = (int32_t)T0 / (int32_t)T1;
     } else {
         xer_so = 1;
         xer_ov = 1;
@@ -168,6 +351,21 @@
     }
 }
 
+#if defined(TARGET_PPC64)
+void do_divdo (void)
+{
+    if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == -1ULL) ||
+                 (int64_t)T1 == 0))) {
+        xer_ov = 0;
+        T0 = (int64_t)T0 / (int64_t)T1;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+        T0 = (-1ULL) * ((uint64_t)T0 >> 63);
+    }
+}
+#endif
+
 void do_divwuo (void)
 {
     if (likely((uint32_t)T1 != 0)) {
@@ -180,9 +378,23 @@
     }
 }
 
+#if defined(TARGET_PPC64)
+void do_divduo (void)
+{
+    if (likely((uint64_t)T1 != 0)) {
+        xer_ov = 0;
+        T0 = (uint64_t)T0 / (uint64_t)T1;
+    } else {
+        xer_so = 1;
+        xer_ov = 1;
+        T0 = 0;
+    }
+}
+#endif
+
 void do_mullwo (void)
 {
-    int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
+    int64_t res = (int64_t)T0 * (int64_t)T1;
 
     if (likely((int32_t)res == res)) {
         xer_ov = 0;
@@ -193,133 +405,232 @@
     T0 = (int32_t)res;
 }
 
-void do_nego (void)
+#if defined(TARGET_PPC64)
+void do_mulldo (void)
 {
-    if (likely(T0 != INT32_MIN)) {
+    int64_t th;
+    uint64_t tl;
+
+    do_imul64(&tl, &th);
+    if (likely(th == 0)) {
         xer_ov = 0;
-        T0 = -Ts0;
     } else {
         xer_ov = 1;
         xer_so = 1;
     }
+    T0 = (int64_t)tl;
 }
+#endif
 
-void do_subfo (void)
+void do_nego (void)
 {
-    T2 = T0;
-    T0 = T1 - T0;
-    if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
+    if (likely((int32_t)T0 != INT32_MIN)) {
         xer_ov = 0;
+        T0 = -(int32_t)T0;
     } else {
+        xer_ov = 1;
         xer_so = 1;
-        xer_ov = 1;
     }
-    RETURN();
 }
 
-void do_subfco (void)
+#if defined(TARGET_PPC64)
+void do_nego_64 (void)
 {
-    T2 = T0;
-    T0 = T1 - T0;
-    if (likely(T0 > T1)) {
-        xer_ca = 0;
-    } else {
-        xer_ca = 1;
-    }
-    if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
+    if (likely((int64_t)T0 != INT64_MIN)) {
         xer_ov = 0;
+        T0 = -(int64_t)T0;
     } else {
+        xer_ov = 1;
         xer_so = 1;
-        xer_ov = 1;
     }
 }
+#endif
 
 void do_subfe (void)
 {
     T0 = T1 + ~T0 + xer_ca;
-    if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
+    if (likely((uint32_t)T0 >= (uint32_t)T1 &&
+               (xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
         xer_ca = 0;
     } else {
         xer_ca = 1;
     }
 }
 
-void do_subfeo (void)
+#if defined(TARGET_PPC64)
+void do_subfe_64 (void)
 {
-    T2 = T0;
     T0 = T1 + ~T0 + xer_ca;
-    if (likely(!((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)))) {
+    if (likely((uint64_t)T0 >= (uint64_t)T1 &&
+               (xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
+        xer_ca = 0;
+    } else {
+        xer_ca = 1;
+    }
+}
+#endif
+
+void do_subfmeo (void)
+{
+    T1 = T0;
+    T0 = ~T0 + xer_ca - 1;
+    if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) &
+                 (1UL << 31)))) {
         xer_ov = 0;
     } else {
         xer_so = 1;
         xer_ov = 1;
     }
-    if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
-        xer_ca = 0;
-    } else {
+    if (likely((uint32_t)T1 != UINT32_MAX))
         xer_ca = 1;
-    }
 }
 
-void do_subfmeo (void)
+#if defined(TARGET_PPC64)
+void do_subfmeo_64 (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca - 1;
-    if (likely(!(~T1 & (~T1 ^ T0) & (1 << 31)))) {
+    if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) &
+                 (1ULL << 63)))) {
         xer_ov = 0;
     } else {
         xer_so = 1;
         xer_ov = 1;
     }
-    if (likely(T1 != -1))
+    if (likely((uint64_t)T1 != UINT64_MAX))
         xer_ca = 1;
 }
+#endif
 
 void do_subfzeo (void)
 {
     T1 = T0;
     T0 = ~T0 + xer_ca;
-    if (likely(!((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)))) {
+    if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) &
+                 ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) {
         xer_ov = 0;
     } else {
         xer_ov = 1;
         xer_so = 1;
     }
-    if (likely(T0 >= ~T1)) {
+    if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
         xer_ca = 0;
     } else {
         xer_ca = 1;
     }
 }
 
+#if defined(TARGET_PPC64)
+void do_subfzeo_64 (void)
+{
+    T1 = T0;
+    T0 = ~T0 + xer_ca;
+    if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) &
+                 ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) {
+        xer_ov = 0;
+    } else {
+        xer_ov = 1;
+        xer_so = 1;
+    }
+    if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
+        xer_ca = 0;
+    } else {
+        xer_ca = 1;
+    }
+}
+#endif
+
 /* shift right arithmetic helper */
 void do_sraw (void)
 {
     int32_t ret;
 
     if (likely(!(T1 & 0x20UL))) {
-        if (likely(T1 != 0)) {
+        if (likely((uint32_t)T1 != 0)) {
             ret = (int32_t)T0 >> (T1 & 0x1fUL);
             if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
-    xer_ca = 0;
+                xer_ca = 0;
             } else {
-            xer_ca = 1;
+                xer_ca = 1;
             }
         } else {
-        ret = T0;
+            ret = T0;
             xer_ca = 0;
         }
     } else {
         ret = (-1) * ((uint32_t)T0 >> 31);
         if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
             xer_ca = 0;
+        } else {
+            xer_ca = 1;
+        }
+    }
+    T0 = ret;
+}
+
+#if defined(TARGET_PPC64)
+void do_srad (void)
+{
+    int64_t ret;
+
+    if (likely(!(T1 & 0x40UL))) {
+        if (likely((uint64_t)T1 != 0)) {
+            ret = (int64_t)T0 >> (T1 & 0x3FUL);
+            if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
+                xer_ca = 0;
+            } else {
+                xer_ca = 1;
+            }
+        } else {
+            ret = T0;
+            xer_ca = 0;
+        }
     } else {
+        ret = (-1) * ((uint64_t)T0 >> 63);
+        if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
+            xer_ca = 0;
+        } else {
             xer_ca = 1;
+        }
     }
-    }
     T0 = ret;
 }
+#endif
 
+static inline int popcnt (uint32_t val)
+{
+    int i;
+
+    for (i = 0; val != 0;)
+        val = val ^ (val - 1);
+
+    return i;
+}
+
+void do_popcntb (void)
+{
+    uint32_t ret;
+    int i;
+
+    ret = 0;
+    for (i = 0; i < 32; i += 8)
+        ret |= popcnt((T0 >> i) & 0xFF) << i;
+    T0 = ret;
+}
+
+#if defined(TARGET_PPC64)
+void do_popcntb_64 (void)
+{
+    uint64_t ret;
+    int i;
+
+    ret = 0;
+    for (i = 0; i < 64; i += 8)
+        ret |= popcnt((T0 >> i) & 0xFF) << i;
+    T0 = ret;
+}
+#endif
+
 /*****************************************************************************/
 /* Floating point operations helpers */
 void do_fctiw (void)
@@ -329,11 +640,13 @@
         uint64_t i;
     } p;
 
+    p.i = float64_to_int32(FT0, &env->fp_status);
+#if USE_PRECISE_EMULATION
     /* XXX: higher bits are not supposed to be significant.
-     *      to make tests easier, return the same as a real PowerPC 750 (aka G3)
+     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
      */
-    p.i = float64_to_int32(FT0, &env->fp_status);
     p.i |= 0xFFF80000ULL << 32;
+#endif
     FT0 = p.d;
 }
 
@@ -344,26 +657,132 @@
         uint64_t i;
     } p;
 
+    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
+#if USE_PRECISE_EMULATION
     /* XXX: higher bits are not supposed to be significant.
-     *      to make tests easier, return the same as a real PowerPC 750 (aka G3)
+     *     to make tests easier, return the same as a real PowerPC 750 (aka G3)
      */
-    p.i = float64_to_int32_round_to_zero(FT0, &env->fp_status);
     p.i |= 0xFFF80000ULL << 32;
+#endif
     FT0 = p.d;
 }
 
+#if defined(TARGET_PPC64)
+void do_fcfid (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.d = FT0;
+    FT0 = int64_to_float64(p.i, &env->fp_status);
+}
+
+void do_fctid (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = float64_to_int64(FT0, &env->fp_status);
+    FT0 = p.d;
+}
+
+void do_fctidz (void)
+{
+    union {
+        double d;
+        uint64_t i;
+    } p;
+
+    p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status);
+    FT0 = p.d;
+}
+
+#endif
+
+#if USE_PRECISE_EMULATION
+void do_fmadd (void)
+{
+#ifdef FLOAT128
+    float128 ft0_128, ft1_128;
+
+    ft0_128 = float64_to_float128(FT0, &env->fp_status);
+    ft1_128 = float64_to_float128(FT1, &env->fp_status);
+    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
+    ft1_128 = float64_to_float128(FT2, &env->fp_status);
+    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
+    FT0 = float128_to_float64(ft0_128, &env->fp_status);
+#else
+    /* This is OK on x86 hosts */
+    FT0 = (FT0 * FT1) + FT2;
+#endif
+}
+
+void do_fmsub (void)
+{
+#ifdef FLOAT128
+    float128 ft0_128, ft1_128;
+
+    ft0_128 = float64_to_float128(FT0, &env->fp_status);
+    ft1_128 = float64_to_float128(FT1, &env->fp_status);
+    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
+    ft1_128 = float64_to_float128(FT2, &env->fp_status);
+    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
+    FT0 = float128_to_float64(ft0_128, &env->fp_status);
+#else
+    /* This is OK on x86 hosts */
+    FT0 = (FT0 * FT1) - FT2;
+#endif
+}
+#endif /* USE_PRECISE_EMULATION */
+
 void do_fnmadd (void)
 {
+#if USE_PRECISE_EMULATION
+#ifdef FLOAT128
+    float128 ft0_128, ft1_128;
+
+    ft0_128 = float64_to_float128(FT0, &env->fp_status);
+    ft1_128 = float64_to_float128(FT1, &env->fp_status);
+    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
+    ft1_128 = float64_to_float128(FT2, &env->fp_status);
+    ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
+    FT0 = float128_to_float64(ft0_128, &env->fp_status);
+#else
+    /* This is OK on x86 hosts */
+    FT0 = (FT0 * FT1) + FT2;
+#endif
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
     FT0 = float64_add(FT0, FT2, &env->fp_status);
+#endif
     if (likely(!isnan(FT0)))
         FT0 = float64_chs(FT0);
 }
 
 void do_fnmsub (void)
 {
+#if USE_PRECISE_EMULATION
+#ifdef FLOAT128
+    float128 ft0_128, ft1_128;
+
+    ft0_128 = float64_to_float128(FT0, &env->fp_status);
+    ft1_128 = float64_to_float128(FT1, &env->fp_status);
+    ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
+    ft1_128 = float64_to_float128(FT2, &env->fp_status);
+    ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
+    FT0 = float128_to_float64(ft0_128, &env->fp_status);
+#else
+    /* This is OK on x86 hosts */
+    FT0 = (FT0 * FT1) - FT2;
+#endif
+#else
     FT0 = float64_mul(FT0, FT1, &env->fp_status);
     FT0 = float64_sub(FT0, FT2, &env->fp_status);
+#endif
     if (likely(!isnan(FT0)))
         FT0 = float64_chs(FT0);
 }
@@ -381,7 +800,12 @@
     } p;
 
     if (likely(isnormal(FT0))) {
-        FT0 = (float)(1.0 / FT0);
+#if USE_PRECISE_EMULATION
+        FT0 = float64_div(1.0, FT0, &env->fp_status);
+        FT0 = float64_to_float32(FT0, &env->fp_status);
+#else
+        FT0 = float32_div(1.0, FT0, &env->fp_status);
+#endif
     } else {
         p.d = FT0;
         if (p.i == 0x8000000000000000ULL) {
@@ -467,8 +891,8 @@
     } else {
         T0 = 0x01UL;
         env->fpscr[4] |= 0x1;
-        /* I don't know how to test "quiet" nan... */
-        if (0 /* || ! quiet_nan(...) */) {
+        if (!float64_is_signaling_nan(FT0) || !float64_is_signaling_nan(FT1)) {
+            /* Quiet NaN case */
             env->fpscr[6] |= 0x1;
             if (!(env->fpscr[1] & 0x8))
                 env->fpscr[4] |= 0x8;
@@ -479,63 +903,1307 @@
     env->fpscr[3] = T0;
 }
 
+#if !defined (CONFIG_USER_ONLY)
+void cpu_dump_rfi (target_ulong RA, target_ulong msr);
 void do_rfi (void)
 {
-    env->nip = env->spr[SPR_SRR0] & ~0x00000003;
-    T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
-    do_store_msr(env, T0);
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
+        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    } else {
+        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    }
+#else
+    env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+    do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+#endif
 #if defined (DEBUG_OP)
-    dump_rfi();
+    cpu_dump_rfi(env->nip, do_load_msr(env));
 #endif
     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
-void do_tw (uint32_t cmp, int flags)
+#if defined(TARGET_PPC64)
+void do_rfid (void)
 {
-    if (!likely(!((Ts0 < (int32_t)cmp && (flags & 0x10)) ||
-                  (Ts0 > (int32_t)cmp && (flags & 0x08)) ||
-                  (Ts0 == (int32_t)cmp && (flags & 0x04)) ||
-                  (T0 < cmp && (flags & 0x02)) ||
-                  (T0 > cmp && (flags & 0x01)))))
+    if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) {
+        env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    } else {
+        env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003);
+        do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL));
+    }
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
+#endif
+#endif
+
+void do_tw (int flags)
+{
+    if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) ||
+                  ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) ||
+                  ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
+                  ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
+                  ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
         do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
+    }
 }
 
-/* Instruction cache invalidation helper */
-void do_icbi (void)
+#if defined(TARGET_PPC64)
+void do_td (int flags)
 {
-    uint32_t tmp;
-    /* Invalidate one cache line :
-     * PowerPC specification says this is to be treated like a load
-     * (not a fetch) by the MMU. To be sure it will be so,
-     * do the load "by hand".
+    if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) ||
+                  ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) ||
+                  ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
+                  ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
+                  ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
+        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
+}
+#endif
+
+/*****************************************************************************/
+/* PowerPC 601 specific instructions (POWER bridge) */
+void do_POWER_abso (void)
+{
+    if ((uint32_t)T0 == INT32_MIN) {
+        T0 = INT32_MAX;
+        xer_ov = 1;
+        xer_so = 1;
+    } else {
+        T0 = -T0;
+        xer_ov = 0;
+    }
+}
+
+void do_POWER_clcs (void)
+{
+    switch (T0) {
+    case 0x0CUL:
+        /* Instruction cache line size */
+        T0 = ICACHE_LINE_SIZE;
+        break;
+    case 0x0DUL:
+        /* Data cache line size */
+        T0 = DCACHE_LINE_SIZE;
+        break;
+    case 0x0EUL:
+        /* Minimum cache line size */
+        T0 = ICACHE_LINE_SIZE < DCACHE_LINE_SIZE ?
+            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
+        break;
+    case 0x0FUL:
+        /* Maximum cache line size */
+        T0 = ICACHE_LINE_SIZE > DCACHE_LINE_SIZE ?
+            ICACHE_LINE_SIZE : DCACHE_LINE_SIZE;
+        break;
+    default:
+        /* Undefined */
+        break;
+    }
+}
+
+void do_POWER_div (void)
+{
+    uint64_t tmp;
+
+    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
+        T0 = (long)((-1) * (T0 >> 31));
+        env->spr[SPR_MQ] = 0;
+    } else {
+        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
+        env->spr[SPR_MQ] = tmp % T1;
+        T0 = tmp / (int32_t)T1;
+    }
+}
+
+void do_POWER_divo (void)
+{
+    int64_t tmp;
+
+    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
+        T0 = (long)((-1) * (T0 >> 31));
+        env->spr[SPR_MQ] = 0;
+        xer_ov = 1;
+        xer_so = 1;
+    } else {
+        tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ];
+        env->spr[SPR_MQ] = tmp % T1;
+        tmp /= (int32_t)T1;
+        if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) {
+            xer_ov = 1;
+            xer_so = 1;
+        } else {
+            xer_ov = 0;
+        }
+        T0 = tmp;
+    }
+}
+
+void do_POWER_divs (void)
+{
+    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
+        T0 = (long)((-1) * (T0 >> 31));
+        env->spr[SPR_MQ] = 0;
+    } else {
+        env->spr[SPR_MQ] = T0 % T1;
+        T0 = (int32_t)T0 / (int32_t)T1;
+    }
+}
+
+void do_POWER_divso (void)
+{
+    if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == -1) || (int32_t)T1 == 0) {
+        T0 = (long)((-1) * (T0 >> 31));
+        env->spr[SPR_MQ] = 0;
+        xer_ov = 1;
+        xer_so = 1;
+    } else {
+        T0 = (int32_t)T0 / (int32_t)T1;
+        env->spr[SPR_MQ] = (int32_t)T0 % (int32_t)T1;
+        xer_ov = 0;
+    }
+}
+
+void do_POWER_dozo (void)
+{
+    if ((int32_t)T1 > (int32_t)T0) {
+        T2 = T0;
+        T0 = T1 - T0;
+        if (((uint32_t)(~T2) ^ (uint32_t)T1 ^ UINT32_MAX) &
+            ((uint32_t)(~T2) ^ (uint32_t)T0) & (1UL << 31)) {
+            xer_so = 1;
+            xer_ov = 1;
+        } else {
+            xer_ov = 0;
+        }
+    } else {
+        T0 = 0;
+        xer_ov = 0;
+    }
+}
+
+void do_POWER_maskg (void)
+{
+    uint32_t ret;
+
+    if ((uint32_t)T0 == (uint32_t)(T1 + 1)) {
+        ret = -1;
+    } else {
+        ret = (((uint32_t)(-1)) >> ((uint32_t)T0)) ^
+            (((uint32_t)(-1) >> ((uint32_t)T1)) >> 1);
+        if ((uint32_t)T0 > (uint32_t)T1)
+            ret = ~ret;
+    }
+    T0 = ret;
+}
+
+void do_POWER_mulo (void)
+{
+    uint64_t tmp;
+
+    tmp = (uint64_t)T0 * (uint64_t)T1;
+    env->spr[SPR_MQ] = tmp >> 32;
+    T0 = tmp;
+    if (tmp >> 32 != ((uint64_t)T0 >> 16) * ((uint64_t)T1 >> 16)) {
+        xer_ov = 1;
+        xer_so = 1;
+    } else {
+        xer_ov = 0;
+    }
+}
+
+#if !defined (CONFIG_USER_ONLY)
+void do_POWER_rac (void)
+{
+#if 0
+    mmu_ctx_t ctx;
+
+    /* We don't have to generate many instances of this instruction,
+     * as rac is supervisor only.
      */
-#if defined(TARGET_PPC64)
-    if (!msr_sf)
-        T0 &= 0xFFFFFFFFULL;
+    if (get_physical_address(env, &ctx, T0, 0, ACCESS_INT, 1) == 0)
+        T0 = ctx.raddr;
 #endif
-    tmp = ldl_kernel(T0);
-    T0 &= ~(ICACHE_LINE_SIZE - 1);
-    tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);
 }
 
-/*****************************************************************************/
-/* MMU related helpers */
-/* TLB invalidation helpers */
-void do_tlbia (void)
+void do_POWER_rfsvc (void)
 {
-    tlb_flush(env, 1);
+    env->nip = env->lr & ~0x00000003UL;
+    T0 = env->ctr & 0x0000FFFFUL;
+    do_store_msr(env, T0);
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
 }
 
-void do_tlbie (void)
+/* PowerPC 601 BAT management helper */
+void do_store_601_batu (int nr)
 {
-#if !defined(FLUSH_ALL_TLBS)
-    tlb_flush_page(env, T0);
+    do_store_ibatu(env, nr, (uint32_t)T0);
+    env->DBAT[0][nr] = env->IBAT[0][nr];
+    env->DBAT[1][nr] = env->IBAT[1][nr];
+}
+#endif
+
+/*****************************************************************************/
+/* 602 specific instructions */
+/* mfrom is the most crazy instruction ever seen, imho ! */
+/* Real implementation uses a ROM table. Do the same */
+#define USE_MFROM_ROM_TABLE
+void do_op_602_mfrom (void)
+{
+    if (likely(T0 < 602)) {
+#if defined(USE_MFROM_ROM_TABLE)
+#include "mfrom_table.c"
+        T0 = mfrom_ROM_table[T0];
 #else
-    do_tlbia();
+        double d;
+        /* Extremly decomposed:
+         *                    -T0 / 256
+         * T0 = 256 * log10(10          + 1.0) + 0.5
+         */
+        d = T0;
+        d = float64_div(d, 256, &env->fp_status);
+        d = float64_chs(d);
+        d = exp10(d); // XXX: use float emulation function
+        d = float64_add(d, 1.0, &env->fp_status);
+        d = log10(d); // XXX: use float emulation function
+        d = float64_mul(d, 256, &env->fp_status);
+        d = float64_add(d, 0.5, &env->fp_status);
+        T0 = float64_round_to_int(d, &env->fp_status);
 #endif
+    } else {
+        T0 = 0;
+    }
 }
 
 /*****************************************************************************/
+/* Embedded PowerPC specific helpers */
+void do_405_check_ov (void)
+{
+    if (likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
+               !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
+        xer_ov = 0;
+    } else {
+        xer_ov = 1;
+        xer_so = 1;
+    }
+}
+
+void do_405_check_sat (void)
+{
+    if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
+                !(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
+        /* Saturate result */
+        if (T2 >> 31) {
+            T0 = INT32_MIN;
+        } else {
+            T0 = INT32_MAX;
+        }
+    }
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void do_40x_rfci (void)
+{
+    env->nip = env->spr[SPR_40x_SRR2];
+    do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000);
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfci (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000);
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfdi (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000);
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_rfmci (void)
+{
+#if defined(TARGET_PPC64)
+    if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) {
+        env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0];
+    } else
+#endif
+    {
+        env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0];
+    }
+    do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000);
+#if defined (DEBUG_OP)
+    cpu_dump_rfi(env->nip, do_load_msr(env));
+#endif
+    env->interrupt_request = CPU_INTERRUPT_EXITTB;
+}
+
+void do_load_dcr (void)
+{
+    target_ulong val;
+    
+    if (unlikely(env->dcr_env == NULL)) {
+        if (loglevel != 0) {
+            fprintf(logfile, "No DCR environment\n");
+        }
+        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+    } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
+        if (loglevel != 0) {
+            fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
+        }
+        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
+    } else {
+        T0 = val;
+    }
+}
+
+void do_store_dcr (void)
+{
+    if (unlikely(env->dcr_env == NULL)) {
+        if (loglevel != 0) {
+            fprintf(logfile, "No DCR environment\n");
+        }
+        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+    } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
+        if (loglevel != 0) {
+            fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
+        }
+        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
+    }
+}
+
+void do_load_403_pb (int num)
+{
+    T0 = env->pb[num];
+}
+
+void do_store_403_pb (int num)
+{
+    if (likely(env->pb[num] != T0)) {
+        env->pb[num] = T0;
+        /* Should be optimized */
+        tlb_flush(env, 1);
+    }
+}
+#endif
+
+/* 440 specific */
+void do_440_dlmzb (void)
+{
+    target_ulong mask;
+    int i;
+
+    i = 1;
+    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
+        if ((T0 & mask) == 0)
+            goto done;
+        i++;
+    }
+    for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
+        if ((T1 & mask) == 0)
+            break;
+        i++;
+    }
+ done:
+    T0 = i;
+}
+
+#if defined(TARGET_PPCEMB)
+/* SPE extension helpers */
+/* Use a table to make this quicker */
+static uint8_t hbrev[16] = {
+    0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
+    0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
+};
+
+static inline uint8_t byte_reverse (uint8_t val)
+{
+    return hbrev[val >> 4] | (hbrev[val & 0xF] << 4);
+}
+
+static inline uint32_t word_reverse (uint32_t val)
+{
+    return byte_reverse(val >> 24) | (byte_reverse(val >> 16) << 8) |
+        (byte_reverse(val >> 8) << 16) | (byte_reverse(val) << 24);
+}
+
+#define MASKBITS 16 // Random value - to be fixed
+void do_brinc (void)
+{
+    uint32_t a, b, d, mask;
+
+    mask = (uint32_t)(-1UL) >> MASKBITS;
+    b = T1_64 & mask;
+    a = T0_64 & mask;
+    d = word_reverse(1 + word_reverse(a | ~mask));
+    T0_64 = (T0_64 & ~mask) | (d & mask);
+}
+
+#define DO_SPE_OP2(name)                                                      \
+void do_ev##name (void)                                                       \
+{                                                                             \
+    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32, T1_64 >> 32) << 32) |         \
+        (uint64_t)_do_e##name(T0_64, T1_64);                                  \
+}
+
+#define DO_SPE_OP1(name)                                                      \
+void do_ev##name (void)                                                       \
+{                                                                             \
+    T0_64 = ((uint64_t)_do_e##name(T0_64 >> 32) << 32) |                      \
+        (uint64_t)_do_e##name(T0_64);                                         \
+}
+
+/* Fixed-point vector arithmetic */
+static inline uint32_t _do_eabs (uint32_t val)
+{
+    if (val != 0x80000000)
+        val &= ~0x80000000;
+
+    return val;
+}
+
+static inline uint32_t _do_eaddw (uint32_t op1, uint32_t op2)
+{
+    return op1 + op2;
+}
+
+static inline int _do_ecntlsw (uint32_t val)
+{
+    if (val & 0x80000000)
+        return _do_cntlzw(~val);
+    else
+        return _do_cntlzw(val);
+}
+
+static inline int _do_ecntlzw (uint32_t val)
+{
+    return _do_cntlzw(val);
+}
+
+static inline uint32_t _do_eneg (uint32_t val)
+{
+    if (val != 0x80000000)
+        val ^= 0x80000000;
+
+    return val;
+}
+
+static inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
+{
+    return rotl32(op1, op2);
+}
+
+static inline uint32_t _do_erndw (uint32_t val)
+{
+    return (val + 0x000080000000) & 0xFFFF0000;
+}
+
+static inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
+{
+    /* No error here: 6 bits are used */
+    return op1 << (op2 & 0x3F);
+}
+
+static inline int32_t _do_esrws (int32_t op1, uint32_t op2)
+{
+    /* No error here: 6 bits are used */
+    return op1 >> (op2 & 0x3F);
+}
+
+static inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
+{
+    /* No error here: 6 bits are used */
+    return op1 >> (op2 & 0x3F);
+}
+
+static inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
+{
+    return op2 - op1;
+}
+
+/* evabs */
+DO_SPE_OP1(abs);
+/* evaddw */
+DO_SPE_OP2(addw);
+/* evcntlsw */
+DO_SPE_OP1(cntlsw);
+/* evcntlzw */
+DO_SPE_OP1(cntlzw);
+/* evneg */
+DO_SPE_OP1(neg);
+/* evrlw */
+DO_SPE_OP2(rlw);
+/* evrnd */
+DO_SPE_OP1(rndw);
+/* evslw */
+DO_SPE_OP2(slw);
+/* evsrws */
+DO_SPE_OP2(srws);
+/* evsrwu */
+DO_SPE_OP2(srwu);
+/* evsubfw */
+DO_SPE_OP2(subfw);
+
+/* evsel is a little bit more complicated... */
+static inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
+{
+    if (n)
+        return op1;
+    else
+        return op2;
+}
+
+void do_evsel (void)
+{
+    T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
+        (uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
+}
+
+/* Fixed-point vector comparisons */
+#define DO_SPE_CMP(name)                                                      \
+void do_ev##name (void)                                                       \
+{                                                                             \
+    T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32,                   \
+                                               T1_64 >> 32) << 32,            \
+                         _do_e##name(T0_64, T1_64));                          \
+}
+
+static inline uint32_t _do_evcmp_merge (int t0, int t1)
+{
+    return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
+}
+static inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
+{
+    return op1 == op2 ? 1 : 0;
+}
+
+static inline int _do_ecmpgts (int32_t op1, int32_t op2)
+{
+    return op1 > op2 ? 1 : 0;
+}
+
+static inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
+{
+    return op1 > op2 ? 1 : 0;
+}
+
+static inline int _do_ecmplts (int32_t op1, int32_t op2)
+{
+    return op1 < op2 ? 1 : 0;
+}
+
+static inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
+{
+    return op1 < op2 ? 1 : 0;
+}
+
+/* evcmpeq */
+DO_SPE_CMP(cmpeq);
+/* evcmpgts */
+DO_SPE_CMP(cmpgts);
+/* evcmpgtu */
+DO_SPE_CMP(cmpgtu);
+/* evcmplts */
+DO_SPE_CMP(cmplts);
+/* evcmpltu */
+DO_SPE_CMP(cmpltu);
+
+/* Single precision floating-point conversions from/to integer */
+static inline uint32_t _do_efscfsi (int32_t val)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u;
+
+    u.f = int32_to_float32(val, &env->spe_status);
+
+    return u.u;
+}
+
+static inline uint32_t _do_efscfui (uint32_t val)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u;
+
+    u.f = uint32_to_float32(val, &env->spe_status);
+
+    return u.u;
+}
+
+static inline int32_t _do_efsctsi (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float32_to_int32(u.f, &env->spe_status);
+}
+
+static inline uint32_t _do_efsctui (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float32_to_uint32(u.f, &env->spe_status);
+}
+
+static inline int32_t _do_efsctsiz (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
+}
+
+static inline uint32_t _do_efsctuiz (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
+}
+
+void do_efscfsi (void)
+{
+    T0_64 = _do_efscfsi(T0_64);
+}
+
+void do_efscfui (void)
+{
+    T0_64 = _do_efscfui(T0_64);
+}
+
+void do_efsctsi (void)
+{
+    T0_64 = _do_efsctsi(T0_64);
+}
+
+void do_efsctui (void)
+{
+    T0_64 = _do_efsctui(T0_64);
+}
+
+void do_efsctsiz (void)
+{
+    T0_64 = _do_efsctsiz(T0_64);
+}
+
+void do_efsctuiz (void)
+{
+    T0_64 = _do_efsctuiz(T0_64);
+}
+
+/* Single precision floating-point conversion to/from fractional */
+static inline uint32_t _do_efscfsf (uint32_t val)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.f = int32_to_float32(val, &env->spe_status);
+    tmp = int64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_div(u.f, tmp, &env->spe_status);
+
+    return u.u;
+}
+
+static inline uint32_t _do_efscfuf (uint32_t val)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.f = uint32_to_float32(val, &env->spe_status);
+    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_div(u.f, tmp, &env->spe_status);
+
+    return u.u;
+}
+
+static inline int32_t _do_efsctsf (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_mul(u.f, tmp, &env->spe_status);
+
+    return float32_to_int32(u.f, &env->spe_status);
+}
+
+static inline uint32_t _do_efsctuf (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_mul(u.f, tmp, &env->spe_status);
+
+    return float32_to_uint32(u.f, &env->spe_status);
+}
+
+static inline int32_t _do_efsctsfz (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_mul(u.f, tmp, &env->spe_status);
+
+    return float32_to_int32_round_to_zero(u.f, &env->spe_status);
+}
+
+static inline uint32_t _do_efsctufz (uint32_t val)
+{
+    union {
+        int32_t u;
+        float32 f;
+    } u;
+    float32 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
+    u.f = float32_mul(u.f, tmp, &env->spe_status);
+
+    return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
+}
+
+void do_efscfsf (void)
+{
+    T0_64 = _do_efscfsf(T0_64);
+}
+
+void do_efscfuf (void)
+{
+    T0_64 = _do_efscfuf(T0_64);
+}
+
+void do_efsctsf (void)
+{
+    T0_64 = _do_efsctsf(T0_64);
+}
+
+void do_efsctuf (void)
+{
+    T0_64 = _do_efsctuf(T0_64);
+}
+
+void do_efsctsfz (void)
+{
+    T0_64 = _do_efsctsfz(T0_64);
+}
+
+void do_efsctufz (void)
+{
+    T0_64 = _do_efsctufz(T0_64);
+}
+
+/* Double precision floating point helpers */
+static inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efdtstlt(op1, op2);
+}
+
+static inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efdtstgt(op1, op2);
+}
+
+static inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efdtsteq(op1, op2);
+}
+
+void do_efdcmplt (void)
+{
+    T0 = _do_efdcmplt(T0_64, T1_64);
+}
+
+void do_efdcmpgt (void)
+{
+    T0 = _do_efdcmpgt(T0_64, T1_64);
+}
+
+void do_efdcmpeq (void)
+{
+    T0 = _do_efdcmpeq(T0_64, T1_64);
+}
+
+/* Double precision floating-point conversion to/from integer */
+static inline uint64_t _do_efdcfsi (int64_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u;
+
+    u.f = int64_to_float64(val, &env->spe_status);
+
+    return u.u;
+}
+
+static inline uint64_t _do_efdcfui (uint64_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u;
+
+    u.f = uint64_to_float64(val, &env->spe_status);
+
+    return u.u;
+}
+
+static inline int64_t _do_efdctsi (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float64_to_int64(u.f, &env->spe_status);
+}
+
+static inline uint64_t _do_efdctui (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float64_to_uint64(u.f, &env->spe_status);
+}
+
+static inline int64_t _do_efdctsiz (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float64_to_int64_round_to_zero(u.f, &env->spe_status);
+}
+
+static inline uint64_t _do_efdctuiz (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+
+    return float64_to_uint64_round_to_zero(u.f, &env->spe_status);
+}
+
+void do_efdcfsi (void)
+{
+    T0_64 = _do_efdcfsi(T0_64);
+}
+
+void do_efdcfui (void)
+{
+    T0_64 = _do_efdcfui(T0_64);
+}
+
+void do_efdctsi (void)
+{
+    T0_64 = _do_efdctsi(T0_64);
+}
+
+void do_efdctui (void)
+{
+    T0_64 = _do_efdctui(T0_64);
+}
+
+void do_efdctsiz (void)
+{
+    T0_64 = _do_efdctsiz(T0_64);
+}
+
+void do_efdctuiz (void)
+{
+    T0_64 = _do_efdctuiz(T0_64);
+}
+
+/* Double precision floating-point conversion to/from fractional */
+static inline uint64_t _do_efdcfsf (int64_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.f = int32_to_float64(val, &env->spe_status);
+    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_div(u.f, tmp, &env->spe_status);
+
+    return u.u;
+}
+
+static inline uint64_t _do_efdcfuf (uint64_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.f = uint32_to_float64(val, &env->spe_status);
+    tmp = int64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_div(u.f, tmp, &env->spe_status);
+
+    return u.u;
+}
+
+static inline int64_t _do_efdctsf (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_mul(u.f, tmp, &env->spe_status);
+
+    return float64_to_int32(u.f, &env->spe_status);
+}
+
+static inline uint64_t _do_efdctuf (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_mul(u.f, tmp, &env->spe_status);
+
+    return float64_to_uint32(u.f, &env->spe_status);
+}
+
+static inline int64_t _do_efdctsfz (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_mul(u.f, tmp, &env->spe_status);
+
+    return float64_to_int32_round_to_zero(u.f, &env->spe_status);
+}
+
+static inline uint64_t _do_efdctufz (uint64_t val)
+{
+    union {
+        int64_t u;
+        float64 f;
+    } u;
+    float64 tmp;
+
+    u.u = val;
+    /* NaN are not treated the same way IEEE 754 does */
+    if (unlikely(isnan(u.f)))
+        return 0;
+    tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
+    u.f = float64_mul(u.f, tmp, &env->spe_status);
+
+    return float64_to_uint32_round_to_zero(u.f, &env->spe_status);
+}
+
+void do_efdcfsf (void)
+{
+    T0_64 = _do_efdcfsf(T0_64);
+}
+
+void do_efdcfuf (void)
+{
+    T0_64 = _do_efdcfuf(T0_64);
+}
+
+void do_efdctsf (void)
+{
+    T0_64 = _do_efdctsf(T0_64);
+}
+
+void do_efdctuf (void)
+{
+    T0_64 = _do_efdctuf(T0_64);
+}
+
+void do_efdctsfz (void)
+{
+    T0_64 = _do_efdctsfz(T0_64);
+}
+
+void do_efdctufz (void)
+{
+    T0_64 = _do_efdctufz(T0_64);
+}
+
+/* Floating point conversion between single and double precision */
+static inline uint32_t _do_efscfd (uint64_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1;
+    union {
+        uint32_t u;
+        float32 f;
+    } u2;
+
+    u1.u = val;
+    u2.f = float64_to_float32(u1.f, &env->spe_status);
+
+    return u2.u;
+}
+
+static inline uint64_t _do_efdcfs (uint32_t val)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u2;
+    union {
+        uint32_t u;
+        float32 f;
+    } u1;
+
+    u1.u = val;
+    u2.f = float32_to_float64(u1.f, &env->spe_status);
+
+    return u2.u;
+}
+
+void do_efscfd (void)
+{
+    T0_64 = _do_efscfd(T0_64);
+}
+
+void do_efdcfs (void)
+{
+    T0_64 = _do_efdcfs(T0_64);
+}
+
+/* Single precision fixed-point vector arithmetic */
+/* evfsabs */
+DO_SPE_OP1(fsabs);
+/* evfsnabs */
+DO_SPE_OP1(fsnabs);
+/* evfsneg */
+DO_SPE_OP1(fsneg);
+/* evfsadd */
+DO_SPE_OP2(fsadd);
+/* evfssub */
+DO_SPE_OP2(fssub);
+/* evfsmul */
+DO_SPE_OP2(fsmul);
+/* evfsdiv */
+DO_SPE_OP2(fsdiv);
+
+/* Single-precision floating-point comparisons */
+static inline int _do_efscmplt (uint32_t op1, uint32_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efststlt(op1, op2);
+}
+
+static inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efststgt(op1, op2);
+}
+
+static inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
+{
+    /* XXX: TODO: test special values (NaN, infinites, ...) */
+    return _do_efststeq(op1, op2);
+}
+
+void do_efscmplt (void)
+{
+    T0 = _do_efscmplt(T0_64, T1_64);
+}
+
+void do_efscmpgt (void)
+{
+    T0 = _do_efscmpgt(T0_64, T1_64);
+}
+
+void do_efscmpeq (void)
+{
+    T0 = _do_efscmpeq(T0_64, T1_64);
+}
+
+/* Single-precision floating-point vector comparisons */
+/* evfscmplt */
+DO_SPE_CMP(fscmplt);
+/* evfscmpgt */
+DO_SPE_CMP(fscmpgt);
+/* evfscmpeq */
+DO_SPE_CMP(fscmpeq);
+/* evfststlt */
+DO_SPE_CMP(fststlt);
+/* evfststgt */
+DO_SPE_CMP(fststgt);
+/* evfststeq */
+DO_SPE_CMP(fststeq);
+
+/* Single-precision floating-point vector conversions */
+/* evfscfsi */
+DO_SPE_OP1(fscfsi);
+/* evfscfui */
+DO_SPE_OP1(fscfui);
+/* evfscfuf */
+DO_SPE_OP1(fscfuf);
+/* evfscfsf */
+DO_SPE_OP1(fscfsf);
+/* evfsctsi */
+DO_SPE_OP1(fsctsi);
+/* evfsctui */
+DO_SPE_OP1(fsctui);
+/* evfsctsiz */
+DO_SPE_OP1(fsctsiz);
+/* evfsctuiz */
+DO_SPE_OP1(fsctuiz);
+/* evfsctsf */
+DO_SPE_OP1(fsctsf);
+/* evfsctuf */
+DO_SPE_OP1(fsctuf);
+#endif /* defined(TARGET_PPCEMB) */
+
+/*****************************************************************************/
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
 
@@ -570,7 +2238,7 @@
     saved_env = env;
     env = cpu_single_env;
     ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
-    if (!likely(ret == 0)) {
+    if (unlikely(ret != 0)) {
         if (likely(retaddr)) {
             /* now we have a real cpu fault */
             pc = (target_phys_addr_t)retaddr;
@@ -579,11 +2247,365 @@
                 /* the PC is inside the translated code. It means that we have
                    a virtual CPU fault */
                 cpu_restore_state(tb, env, pc, NULL);
-}
+            }
         }
         do_raise_exception_err(env->exception_index, env->error_code);
     }
     env = saved_env;
 }
+
+/* TLB invalidation helpers */
+void do_tlbia (void)
+{
+    ppc_tlb_invalidate_all(env);
+}
+
+void do_tlbie (void)
+{
+    T0 = (uint32_t)T0;
+#if !defined(FLUSH_ALL_TLBS)
+    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
+        if (env->id_tlbs == 1)
+            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
+    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+        /* XXX: TODO */
+#if 0
+        ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
+                                     env->spr[SPR_BOOKE_PID]);
+#endif
+    } else {
+        /* tlbie invalidate TLBs for all segments */
+        T0 &= TARGET_PAGE_MASK;
+        T0 &= ~((target_ulong)-1 << 28);
+        /* XXX: this case should be optimized,
+         * giving a mask to tlb_flush_page
+         */
+        tlb_flush_page(env, T0 | (0x0 << 28));
+        tlb_flush_page(env, T0 | (0x1 << 28));
+        tlb_flush_page(env, T0 | (0x2 << 28));
+        tlb_flush_page(env, T0 | (0x3 << 28));
+        tlb_flush_page(env, T0 | (0x4 << 28));
+        tlb_flush_page(env, T0 | (0x5 << 28));
+        tlb_flush_page(env, T0 | (0x6 << 28));
+        tlb_flush_page(env, T0 | (0x7 << 28));
+        tlb_flush_page(env, T0 | (0x8 << 28));
+        tlb_flush_page(env, T0 | (0x9 << 28));
+        tlb_flush_page(env, T0 | (0xA << 28));
+        tlb_flush_page(env, T0 | (0xB << 28));
+        tlb_flush_page(env, T0 | (0xC << 28));
+        tlb_flush_page(env, T0 | (0xD << 28));
+        tlb_flush_page(env, T0 | (0xE << 28));
+        tlb_flush_page(env, T0 | (0xF << 28));
+    }
+#else
+    do_tlbia();
+#endif
+}
+
+#if defined(TARGET_PPC64)
+void do_tlbie_64 (void)
+{
+    T0 = (uint64_t)T0;
+#if !defined(FLUSH_ALL_TLBS)
+    if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
+        ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 0);
+        if (env->id_tlbs == 1)
+            ppc6xx_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK, 1);
+    } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
+        /* XXX: TODO */
+#if 0
+        ppcbooke_tlb_invalidate_virt(env, T0 & TARGET_PAGE_MASK,
+                                     env->spr[SPR_BOOKE_PID]);
+#endif
+    } else {
+        /* tlbie invalidate TLBs for all segments
+         * As we have 2^36 segments, invalidate all qemu TLBs
+         */
+#if 0
+        T0 &= TARGET_PAGE_MASK;
+        T0 &= ~((target_ulong)-1 << 28);
+        /* XXX: this case should be optimized,
+         * giving a mask to tlb_flush_page
+         */
+        tlb_flush_page(env, T0 | (0x0 << 28));
+        tlb_flush_page(env, T0 | (0x1 << 28));
+        tlb_flush_page(env, T0 | (0x2 << 28));
+        tlb_flush_page(env, T0 | (0x3 << 28));
+        tlb_flush_page(env, T0 | (0x4 << 28));
+        tlb_flush_page(env, T0 | (0x5 << 28));
+        tlb_flush_page(env, T0 | (0x6 << 28));
+        tlb_flush_page(env, T0 | (0x7 << 28));
+        tlb_flush_page(env, T0 | (0x8 << 28));
+        tlb_flush_page(env, T0 | (0x9 << 28));
+        tlb_flush_page(env, T0 | (0xA << 28));
+        tlb_flush_page(env, T0 | (0xB << 28));
+        tlb_flush_page(env, T0 | (0xC << 28));
+        tlb_flush_page(env, T0 | (0xD << 28));
+        tlb_flush_page(env, T0 | (0xE << 28));
+        tlb_flush_page(env, T0 | (0xF << 28));
+#else
+        tlb_flush(env, 1);
+#endif
+    }
+#else
+    do_tlbia();
+#endif
+}
+#endif
+
+#if defined(TARGET_PPC64)
+void do_slbia (void)
+{
+    /* XXX: TODO */
+    tlb_flush(env, 1);
+}
+
+void do_slbie (void)
+{
+    /* XXX: TODO */
+    tlb_flush(env, 1);
+}
+#endif
+
+/* Software driven TLBs management */
+/* PowerPC 602/603 software TLB load instructions helpers */
+void do_load_6xx_tlb (int is_code)
+{
+    target_ulong RPN, CMP, EPN;
+    int way;
+
+    RPN = env->spr[SPR_RPA];
+    if (is_code) {
+        CMP = env->spr[SPR_ICMP];
+        EPN = env->spr[SPR_IMISS];
+    } else {
+        CMP = env->spr[SPR_DCMP];
+        EPN = env->spr[SPR_DMISS];
+    }
+    way = (env->spr[SPR_SRR1] >> 17) & 1;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: EPN %08lx %08lx PTE0 %08lx PTE1 %08lx way %d\n",
+                __func__, (unsigned long)T0, (unsigned long)EPN,
+                (unsigned long)CMP, (unsigned long)RPN, way);
+    }
+#endif
+    /* Store this TLB */
+    ppc6xx_tlb_store(env, (uint32_t)(T0 & TARGET_PAGE_MASK),
+                     way, is_code, CMP, RPN);
+}
+
+static target_ulong booke_tlb_to_page_size (int size)
+{
+    return 1024 << (2 * size);
+}
+
+static int booke_page_size_to_tlb (target_ulong page_size)
+{
+    int size;
+
+    switch (page_size) {
+    case 0x00000400UL:
+        size = 0x0;
+        break;
+    case 0x00001000UL:
+        size = 0x1;
+        break;
+    case 0x00004000UL:
+        size = 0x2;
+        break;
+    case 0x00010000UL:
+        size = 0x3;
+        break;
+    case 0x00040000UL:
+        size = 0x4;
+        break;
+    case 0x00100000UL:
+        size = 0x5;
+        break;
+    case 0x00400000UL:
+        size = 0x6;
+        break;
+    case 0x01000000UL:
+        size = 0x7;
+        break;
+    case 0x04000000UL:
+        size = 0x8;
+        break;
+    case 0x10000000UL:
+        size = 0x9;
+        break;
+    case 0x40000000UL:
+        size = 0xA;
+        break;
+#if defined (TARGET_PPC64)
+    case 0x000100000000ULL:
+        size = 0xB;
+        break;
+    case 0x000400000000ULL:
+        size = 0xC;
+        break;
+    case 0x001000000000ULL:
+        size = 0xD;
+        break;
+    case 0x004000000000ULL:
+        size = 0xE;
+        break;
+    case 0x010000000000ULL:
+        size = 0xF;
+        break;
+#endif
+    default:
+        size = -1;
+        break;
+    }
+
+    return size;
+}
+
+/* Helpers for 4xx TLB management */
+void do_4xx_tlbre_lo (void)
+{
+    ppcemb_tlb_t *tlb;
+    int size;
+
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    T0 = tlb->EPN;
+    if (tlb->prot & PAGE_VALID)
+        T0 |= 0x400;
+    size = booke_page_size_to_tlb(tlb->size);
+    if (size < 0 || size > 0x7)
+        size = 1;
+    T0 |= size << 7;
+    env->spr[SPR_40x_PID] = tlb->PID;
+}
+
+void do_4xx_tlbre_hi (void)
+{
+    ppcemb_tlb_t *tlb;
+
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    T0 = tlb->RPN;
+    if (tlb->prot & PAGE_EXEC)
+        T0 |= 0x200;
+    if (tlb->prot & PAGE_WRITE)
+        T0 |= 0x100;
+}
+
+void do_4xx_tlbsx (void)
+{
+    T0 = ppcemb_tlb_search(env, T0);
+}
+
+void do_4xx_tlbsx_ (void)
+{
+    int tmp = xer_ov;
+
+    T0 = ppcemb_tlb_search(env, T0);
+    if (T0 != -1)
+        tmp |= 0x02;
+    env->crf[0] = tmp;
+}
+
+void do_4xx_tlbwe_hi (void)
+{
+    ppcemb_tlb_t *tlb;
+    target_ulong page, end;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    /* Invalidate previous TLB (if it's valid) */
+    if (tlb->prot & PAGE_VALID) {
+        end = tlb->EPN + tlb->size;
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
+                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
+        }
+#endif
+        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
+            tlb_flush_page(env, page);
+    }
+    tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
+    /* We cannot handle TLB size < TARGET_PAGE_SIZE.
+     * If this ever occurs, one should use the ppcemb target instead
+     * of the ppc or ppc64 one
+     */
+    if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
+        cpu_abort(env, "TLB size %u < %u are not supported (%d)\n",
+                  tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
+    }
+    tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
+    if (T1 & 0x40)
+        tlb->prot |= PAGE_VALID;
+    else
+        tlb->prot &= ~PAGE_VALID;
+    if (T1 & 0x20) {
+        /* XXX: TO BE FIXED */
+        cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
+    }
+    tlb->PID = env->spr[SPR_40x_PID]; /* PID */
+    tlb->attr = T1 & 0xFF;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
+                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
+                (int)T0, tlb->RPN, tlb->EPN, tlb->size, 
+                tlb->prot & PAGE_READ ? 'r' : '-',
+                tlb->prot & PAGE_WRITE ? 'w' : '-',
+                tlb->prot & PAGE_EXEC ? 'x' : '-',
+                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
+    }
+#endif
+    /* Invalidate new TLB (if valid) */
+    if (tlb->prot & PAGE_VALID) {
+        end = tlb->EPN + tlb->size;
+#if defined (DEBUG_SOFTWARE_TLB)
+        if (loglevel != 0) {
+            fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
+                    " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
+        }
+#endif
+        for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
+            tlb_flush_page(env, page);
+    }
+}
+
+void do_4xx_tlbwe_lo (void)
+{
+    ppcemb_tlb_t *tlb;
+
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
+    }
+#endif
+    T0 &= 0x3F;
+    tlb = &env->tlb[T0].tlbe;
+    tlb->RPN = T1 & 0xFFFFFC00;
+    tlb->prot = PAGE_READ;
+    if (T1 & 0x200)
+        tlb->prot |= PAGE_EXEC;
+    if (T1 & 0x100)
+        tlb->prot |= PAGE_WRITE;
+#if defined (DEBUG_SOFTWARE_TLB)
+    if (loglevel != 0) {
+        fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
+                " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
+                (int)T0, tlb->RPN, tlb->EPN, tlb->size, 
+                tlb->prot & PAGE_READ ? 'r' : '-',
+                tlb->prot & PAGE_WRITE ? 'w' : '-',
+                tlb->prot & PAGE_EXEC ? 'x' : '-',
+                tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
+    }
+#endif
+}
 #endif /* !CONFIG_USER_ONLY */
-

Added: trunk/src/host/qemu-neo1973/target-ppc/op_helper.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,463 @@
+/*
+ *  PowerPC emulation helpers header 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if defined(MEMSUFFIX)
+
+/* Memory load/store helpers */
+void glue(do_lsw, MEMSUFFIX) (int dst);
+void glue(do_lsw_le, MEMSUFFIX) (int dst);
+void glue(do_stsw, MEMSUFFIX) (int src);
+void glue(do_stsw_le, MEMSUFFIX) (int src);
+void glue(do_lmw, MEMSUFFIX) (int dst);
+void glue(do_lmw_le, MEMSUFFIX) (int dst);
+void glue(do_stmw, MEMSUFFIX) (int src);
+void glue(do_stmw_le, MEMSUFFIX) (int src);
+void glue(do_icbi, MEMSUFFIX) (void);
+void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb);
+void glue(do_POWER2_lfq, MEMSUFFIX) (void);
+void glue(do_POWER2_lfq_le, MEMSUFFIX) (void);
+void glue(do_POWER2_stfq, MEMSUFFIX) (void);
+void glue(do_POWER2_stfq_le, MEMSUFFIX) (void);
+
+#if defined(TARGET_PPC64)
+void glue(do_lsw_64, MEMSUFFIX) (int dst);
+void glue(do_lsw_le_64, MEMSUFFIX) (int dst);
+void glue(do_stsw_64, MEMSUFFIX) (int src);
+void glue(do_stsw_le_64, MEMSUFFIX) (int src);
+void glue(do_lmw_64, MEMSUFFIX) (int dst);
+void glue(do_lmw_le_64, MEMSUFFIX) (int dst);
+void glue(do_stmw_64, MEMSUFFIX) (int src);
+void glue(do_stmw_le_64, MEMSUFFIX) (int src);
+void glue(do_icbi_64, MEMSUFFIX) (void);
+#endif
+
+#else
+
+void do_print_mem_EA (target_ulong EA);
+
+/* Registers load and stores */
+void do_load_cr (void);
+void do_store_cr (uint32_t mask);
+void do_load_xer (void);
+void do_store_xer (void);
+void do_load_fpscr (void);
+void do_store_fpscr (uint32_t mask);
+target_ulong ppc_load_dump_spr (int sprn);
+void ppc_store_dump_spr (int sprn, target_ulong val);
+
+/* Integer arithmetic helpers */
+void do_adde (void);
+void do_addmeo (void);
+void do_divwo (void);
+void do_divwuo (void);
+void do_mullwo (void);
+void do_nego (void);
+void do_subfe (void);
+void do_subfmeo (void);
+void do_subfzeo (void);
+void do_sraw (void);
+#if defined(TARGET_PPC64)
+void do_adde_64 (void);
+void do_addmeo_64 (void);
+void do_imul64 (uint64_t *tl, uint64_t *th);
+void do_mul64 (uint64_t *tl, uint64_t *th);
+void do_divdo (void);
+void do_divduo (void);
+void do_mulldo (void);
+void do_nego_64 (void);
+void do_subfe_64 (void);
+void do_subfmeo_64 (void);
+void do_subfzeo_64 (void);
+void do_srad (void);
+#endif
+void do_popcntb (void);
+#if defined(TARGET_PPC64)
+void do_popcntb_64 (void);
+#endif
+
+/* Floating-point arithmetic helpers */
+void do_fsqrt (void);
+void do_fres (void);
+void do_frsqrte (void);
+void do_fsel (void);
+#if USE_PRECISE_EMULATION
+void do_fmadd (void);
+void do_fmsub (void);
+#endif
+void do_fnmadd (void);
+void do_fnmsub (void);
+void do_fctiw (void);
+void do_fctiwz (void);
+#if defined(TARGET_PPC64)
+void do_fcfid (void);
+void do_fctid (void);
+void do_fctidz (void);
+#endif
+void do_fcmpu (void);
+void do_fcmpo (void);
+
+/* Misc */
+void do_tw (int flags);
+#if defined(TARGET_PPC64)
+void do_td (int flags);
+#endif
+#if !defined(CONFIG_USER_ONLY)
+void do_rfi (void);
+#if defined(TARGET_PPC64)
+void do_rfid (void);
+#endif
+void do_tlbia (void);
+void do_tlbie (void);
+#if defined(TARGET_PPC64)
+void do_tlbie_64 (void);
+#endif
+void do_load_6xx_tlb (int is_code);
+#if defined(TARGET_PPC64)
+void do_slbia (void);
+void do_slbie (void);
+#endif
+#endif
+
+/* POWER / PowerPC 601 specific helpers */
+void do_store_601_batu (int nr);
+void do_POWER_abso (void);
+void do_POWER_clcs (void);
+void do_POWER_div (void);
+void do_POWER_divo (void);
+void do_POWER_divs (void);
+void do_POWER_divso (void);
+void do_POWER_dozo (void);
+void do_POWER_maskg (void);
+void do_POWER_mulo (void);
+#if !defined(CONFIG_USER_ONLY)
+void do_POWER_rac (void);
+void do_POWER_rfsvc (void);
+#endif
+
+/* PowerPC 602 specific helper */
+#if !defined(CONFIG_USER_ONLY)
+void do_op_602_mfrom (void);
+#endif
+
+/* PowerPC 4xx specific helpers */
+void do_405_check_ov (void);
+void do_405_check_sat (void);
+#if !defined(CONFIG_USER_ONLY)
+void do_load_dcr (void);
+void do_store_dcr (void);
+void do_40x_rfci (void);
+void do_rfci (void);
+void do_rfdi (void);
+void do_rfmci (void);
+void do_4xx_tlbre_lo (void);
+void do_4xx_tlbre_hi (void);
+void do_4xx_tlbsx (void);
+void do_4xx_tlbsx_ (void);
+void do_4xx_tlbwe_lo (void);
+void do_4xx_tlbwe_hi (void);
+#endif
+
+/* PowerPC 440 specific helpers */
+void do_440_dlmzb (void);
+
+/* PowerPC 403 specific helpers */
+#if !defined(CONFIG_USER_ONLY)
+void do_load_403_pb (int num);
+void do_store_403_pb (int num);
+#endif
+
+#if defined(TARGET_PPCEMB)
+/* SPE extension helpers */
+void do_brinc (void);
+/* Fixed-point vector helpers */
+void do_evabs (void);
+void do_evaddw (void);
+void do_evcntlsw (void);
+void do_evcntlzw (void);
+void do_evneg (void);
+void do_evrlw (void);
+void do_evsel (void);
+void do_evrndw (void);
+void do_evslw (void);
+void do_evsrws (void);
+void do_evsrwu (void);
+void do_evsubfw (void);
+void do_evcmpeq (void);
+void do_evcmpgts (void);
+void do_evcmpgtu (void);
+void do_evcmplts (void);
+void do_evcmpltu (void);
+
+/* Single precision floating-point helpers */
+void do_efscmplt (void);
+void do_efscmpgt (void);
+void do_efscmpeq (void);
+void do_efscfsf (void);
+void do_efscfuf (void);
+void do_efsctsf (void);
+void do_efsctuf (void);
+
+void do_efscfsi (void);
+void do_efscfui (void);
+void do_efsctsi (void);
+void do_efsctui (void);
+void do_efsctsiz (void);
+void do_efsctuiz (void);
+
+/* Double precision floating-point helpers */
+void do_efdcmplt (void);
+void do_efdcmpgt (void);
+void do_efdcmpeq (void);
+void do_efdcfsf (void);
+void do_efdcfuf (void);
+void do_efdctsf (void);
+void do_efdctuf (void);
+
+void do_efdcfsi (void);
+void do_efdcfui (void);
+void do_efdctsi (void);
+void do_efdctui (void);
+void do_efdctsiz (void);
+void do_efdctuiz (void);
+
+void do_efdcfs (void);
+void do_efscfd (void);
+
+/* Floating-point vector helpers */
+void do_evfsabs (void);
+void do_evfsnabs (void);
+void do_evfsneg (void);
+void do_evfsadd (void);
+void do_evfssub (void);
+void do_evfsmul (void);
+void do_evfsdiv (void);
+void do_evfscmplt (void);
+void do_evfscmpgt (void);
+void do_evfscmpeq (void);
+void do_evfststlt (void);
+void do_evfststgt (void);
+void do_evfststeq (void);
+void do_evfscfsi (void);
+void do_evfscfui (void);
+void do_evfscfsf (void);
+void do_evfscfuf (void);
+void do_evfsctsf (void);
+void do_evfsctuf (void);
+void do_evfsctsi (void);
+void do_evfsctui (void);
+void do_evfsctsiz (void);
+void do_evfsctuiz (void);
+#endif /* defined(TARGET_PPCEMB) */
+
+/* Inlined helpers: used in micro-operation as well as helpers */
+/* Generic fixed-point helpers */
+static inline int _do_cntlzw (uint32_t val)
+{
+    int cnt = 0;
+    if (!(val & 0xFFFF0000UL)) {
+        cnt += 16;
+        val <<= 16;
+    }
+    if (!(val & 0xFF000000UL)) {
+        cnt += 8;
+        val <<= 8;
+    }
+    if (!(val & 0xF0000000UL)) {
+        cnt += 4;
+        val <<= 4;
+    }
+    if (!(val & 0xC0000000UL)) {
+        cnt += 2;
+        val <<= 2;
+    }
+    if (!(val & 0x80000000UL)) {
+        cnt++;
+        val <<= 1;
+    }
+    if (!(val & 0x80000000UL)) {
+        cnt++;
+    }
+    return cnt;
+}
+
+static inline int _do_cntlzd (uint64_t val)
+{
+    int cnt = 0;
+#if HOST_LONG_BITS == 64
+    if (!(val & 0xFFFFFFFF00000000ULL)) {
+        cnt += 32;
+        val <<= 32;
+    }
+    if (!(val & 0xFFFF000000000000ULL)) {
+        cnt += 16;
+        val <<= 16;
+    }
+    if (!(val & 0xFF00000000000000ULL)) {
+        cnt += 8;
+        val <<= 8;
+    }
+    if (!(val & 0xF000000000000000ULL)) {
+        cnt += 4;
+        val <<= 4;
+    }
+    if (!(val & 0xC000000000000000ULL)) {
+        cnt += 2;
+        val <<= 2;
+    }
+    if (!(val & 0x8000000000000000ULL)) {
+        cnt++;
+        val <<= 1;
+    }
+    if (!(val & 0x8000000000000000ULL)) {
+        cnt++;
+    }
+#else
+    /* Make it easier on 32 bits host machines */
+    if (!(val >> 32))
+        cnt = _do_cntlzw(val) + 32;
+    else
+        cnt = _do_cntlzw(val >> 32);
+#endif
+    return cnt;
+}
+
+#if defined(TARGET_PPCEMB)
+/* SPE extension */
+/* Single precision floating-point helpers */
+static inline uint32_t _do_efsabs (uint32_t val)
+{
+    return val & ~0x80000000;
+}
+static inline uint32_t _do_efsnabs (uint32_t val)
+{
+    return val | 0x80000000;
+}
+static inline uint32_t _do_efsneg (uint32_t val)
+{
+    return val ^ 0x80000000;
+}
+static inline uint32_t _do_efsadd (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    u1.f = float32_add(u1.f, u2.f, &env->spe_status);
+    return u1.u;
+}
+static inline uint32_t _do_efssub (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
+    return u1.u;
+}
+static inline uint32_t _do_efsmul (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
+    return u1.u;
+}
+static inline uint32_t _do_efsdiv (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    u1.f = float32_div(u1.f, u2.f, &env->spe_status);
+    return u1.u;
+}
+
+static inline int _do_efststlt (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float32_lt(u1.f, u2.f, &env->spe_status) ? 1 : 0;
+}
+static inline int _do_efststgt (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 1;
+}
+static inline int _do_efststeq (uint32_t op1, uint32_t op2)
+{
+    union {
+        uint32_t u;
+        float32 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float32_eq(u1.f, u2.f, &env->spe_status) ? 1 : 0;
+}
+/* Double precision floating-point helpers */
+static inline int _do_efdtstlt (uint64_t op1, uint64_t op2)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float64_lt(u1.f, u2.f, &env->spe_status) ? 1 : 0;
+}
+static inline int _do_efdtstgt (uint64_t op1, uint64_t op2)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float64_le(u1.f, u2.f, &env->spe_status) ? 0 : 1;
+}
+static inline int _do_efdtsteq (uint64_t op1, uint64_t op2)
+{
+    union {
+        uint64_t u;
+        float64 f;
+    } u1, u2;
+    u1.u = op1;
+    u2.u = op2;
+    return float64_eq(u1.f, u2.f, &env->spe_status) ? 1 : 0;
+}
+#endif /* defined(TARGET_PPCEMB) */
+#endif

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_helper_mem.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,3 +1,103 @@
+/*
+ *  PowerPC emulation micro-operations 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Multiple word / string load and store */
+static inline target_ulong glue(ld32r, MEMSUFFIX) (target_ulong EA)
+{
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(EA);
+    return ((tmp & 0xFF000000UL) >> 24) | ((tmp & 0x00FF0000UL) >> 8) |
+        ((tmp & 0x0000FF00UL) << 8) | ((tmp & 0x000000FFUL) << 24);
+}
+
+static inline void glue(st32r, MEMSUFFIX) (target_ulong EA, target_ulong data)
+{
+    uint32_t tmp =
+        ((data & 0xFF000000UL) >> 24) | ((data & 0x00FF0000UL) >> 8) |
+        ((data & 0x0000FF00UL) << 8) | ((data & 0x000000FFUL) << 24);
+    glue(stl, MEMSUFFIX)(EA, tmp);
+}
+
+void glue(do_lmw, MEMSUFFIX) (int dst)
+{
+    for (; dst < 32; dst++, T0 += 4) {
+        ugpr(dst) = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_lmw_64, MEMSUFFIX) (int dst)
+{
+    for (; dst < 32; dst++, T0 += 4) {
+        ugpr(dst) = glue(ldl, MEMSUFFIX)((uint64_t)T0);
+    }
+}
+#endif
+
+void glue(do_stmw, MEMSUFFIX) (int src)
+{
+    for (; src < 32; src++, T0 += 4) {
+        glue(stl, MEMSUFFIX)((uint32_t)T0, ugpr(src));
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_stmw_64, MEMSUFFIX) (int src)
+{
+    for (; src < 32; src++, T0 += 4) {
+        glue(stl, MEMSUFFIX)((uint64_t)T0, ugpr(src));
+    }
+}
+#endif
+
+void glue(do_lmw_le, MEMSUFFIX) (int dst)
+{
+    for (; dst < 32; dst++, T0 += 4) {
+        ugpr(dst) = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_lmw_le_64, MEMSUFFIX) (int dst)
+{
+    for (; dst < 32; dst++, T0 += 4) {
+        ugpr(dst) = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+    }
+}
+#endif
+
+void glue(do_stmw_le, MEMSUFFIX) (int src)
+{
+    for (; src < 32; src++, T0 += 4) {
+        glue(st32r, MEMSUFFIX)((uint32_t)T0, ugpr(src));
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_stmw_le_64, MEMSUFFIX) (int src)
+{
+    for (; src < 32; src++, T0 += 4) {
+        glue(st32r, MEMSUFFIX)((uint64_t)T0, ugpr(src));
+    }
+}
+#endif
+
 void glue(do_lsw, MEMSUFFIX) (int dst)
 {
     uint32_t tmp;
@@ -3,44 +103,70 @@
     int sh;
 
-#if 0
-    if (loglevel > 0) {
-        fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
-                __func__, T0, T1, dst);
+    for (; T1 > 3; T1 -= 4, T0 += 4) {
+        ugpr(dst++) = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+        if (unlikely(dst == 32))
+            dst = 0;
     }
-#endif
+    if (unlikely(T1 != 0)) {
+        tmp = 0;
+        for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
+            tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
+        }
+        ugpr(dst) = tmp;
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_lsw_64, MEMSUFFIX) (int dst)
+{
+    uint32_t tmp;
+    int sh;
+
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        ugpr(dst++) = glue(ldl, MEMSUFFIX)(T0);
-        if (dst == 32)
+        ugpr(dst++) = glue(ldl, MEMSUFFIX)((uint64_t)T0);
+        if (unlikely(dst == 32))
             dst = 0;
     }
-    if (T1 > 0) {
+    if (unlikely(T1 != 0)) {
         tmp = 0;
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
-            tmp |= glue(ldub, MEMSUFFIX)(T0) << sh;
+            tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
         }
         ugpr(dst) = tmp;
     }
 }
+#endif
 
 void glue(do_stsw, MEMSUFFIX) (int src)
 {
     int sh;
 
-#if 0
-    if (loglevel > 0) {
-        fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
-                __func__, T0, T1, src);
+    for (; T1 > 3; T1 -= 4, T0 += 4) {
+        glue(stl, MEMSUFFIX)((uint32_t)T0, ugpr(src++));
+        if (unlikely(src == 32))
+            src = 0;
     }
-#endif
+    if (unlikely(T1 != 0)) {
+        for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
+            glue(stb, MEMSUFFIX)((uint32_t)T0, (ugpr(src) >> sh) & 0xFF);
+    }
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_stsw_64, MEMSUFFIX) (int src)
+{
+    int sh;
+
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        glue(stl, MEMSUFFIX)(T0, ugpr(src++));
-        if (src == 32)
+        glue(stl, MEMSUFFIX)((uint64_t)T0, ugpr(src++));
+        if (unlikely(src == 32))
             src = 0;
     }
-    if (T1 > 0) {
+    if (unlikely(T1 != 0)) {
         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
-            glue(stb, MEMSUFFIX)(T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint64_t)T0, (ugpr(src) >> sh) & 0xFF);
     }
 }
+#endif
 
 void glue(do_lsw_le, MEMSUFFIX) (int dst)
@@ -49,52 +175,191 @@
     uint32_t tmp;
     int sh;
 
-#if 0
-    if (loglevel > 0) {
-        fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
-                __func__, T0, T1, dst);
-    }
-#endif
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        tmp = glue(ldl, MEMSUFFIX)(T0);
-        ugpr(dst++) = ((tmp & 0xFF000000) >> 24) | ((tmp & 0x00FF0000) >> 8) |
-            ((tmp & 0x0000FF00) << 8) | ((tmp & 0x000000FF) << 24);
-        if (dst == 32)
+        ugpr(dst++) = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+        if (unlikely(dst == 32))
             dst = 0;
     }
-    if (T1 > 0) {
+    if (unlikely(T1 != 0)) {
         tmp = 0;
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
-            tmp |= glue(ldub, MEMSUFFIX)(T0) << sh;
+            tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
         }
         ugpr(dst) = tmp;
     }
 }
 
-void glue(do_stsw_le, MEMSUFFIX) (int src)
+#if defined(TARGET_PPC64)
+void glue(do_lsw_le_64, MEMSUFFIX) (int dst)
 {
     uint32_t tmp;
     int sh;
 
-#if 0
-    if (loglevel > 0) {
-        fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
-                __func__, T0, T1, src);
+    for (; T1 > 3; T1 -= 4, T0 += 4) {
+        ugpr(dst++) = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+        if (unlikely(dst == 32))
+            dst = 0;
     }
+    if (unlikely(T1 != 0)) {
+        tmp = 0;
+        for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
+            tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
+        }
+        ugpr(dst) = tmp;
+    }
+}
 #endif
+
+void glue(do_stsw_le, MEMSUFFIX) (int src)
+{
+    int sh;
+
     for (; T1 > 3; T1 -= 4, T0 += 4) {
-        tmp = ((ugpr(src++) & 0xFF000000) >> 24);
-        tmp |= ((ugpr(src++) & 0x00FF0000) >> 8);
-        tmp |= ((ugpr(src++) & 0x0000FF00) << 8);
-        tmp |= ((ugpr(src++) & 0x000000FF) << 24);
-        glue(stl, MEMSUFFIX)(T0, tmp);
-        if (src == 32)
+        glue(st32r, MEMSUFFIX)((uint32_t)T0, ugpr(src++));
+        if (unlikely(src == 32))
             src = 0;
     }
-    if (T1 > 0) {
+    if (unlikely(T1 != 0)) {
         for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
-            glue(stb, MEMSUFFIX)(T0, (ugpr(src) >> sh) & 0xFF);
+            glue(stb, MEMSUFFIX)((uint32_t)T0, (ugpr(src) >> sh) & 0xFF);
     }
 }
 
+#if defined(TARGET_PPC64)
+void glue(do_stsw_le_64, MEMSUFFIX) (int src)
+{
+    int sh;
+
+    for (; T1 > 3; T1 -= 4, T0 += 4) {
+        glue(st32r, MEMSUFFIX)((uint64_t)T0, ugpr(src++));
+        if (unlikely(src == 32))
+            src = 0;
+    }
+    if (unlikely(T1 != 0)) {
+        for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
+            glue(stb, MEMSUFFIX)((uint64_t)T0, (ugpr(src) >> sh) & 0xFF);
+    }
+}
+#endif
+
+/* Instruction cache invalidation helper */
+void glue(do_icbi, MEMSUFFIX) (void)
+{
+    uint32_t tmp;
+    /* Invalidate one cache line :
+     * PowerPC specification says this is to be treated like a load
+     * (not a fetch) by the MMU. To be sure it will be so,
+     * do the load "by hand".
+     */
+    tmp = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+    T0 &= ~(ICACHE_LINE_SIZE - 1);
+    tb_invalidate_page_range((uint32_t)T0, (uint32_t)(T0 + ICACHE_LINE_SIZE));
+}
+
+#if defined(TARGET_PPC64)
+void glue(do_icbi_64, MEMSUFFIX) (void)
+{
+    uint64_t tmp;
+    /* Invalidate one cache line :
+     * PowerPC specification says this is to be treated like a load
+     * (not a fetch) by the MMU. To be sure it will be so,
+     * do the load "by hand".
+     */
+    tmp = glue(ldq, MEMSUFFIX)((uint64_t)T0);
+    T0 &= ~(ICACHE_LINE_SIZE - 1);
+    tb_invalidate_page_range((uint64_t)T0, (uint64_t)(T0 + ICACHE_LINE_SIZE));
+}
+#endif
+
+/* PPC 601 specific instructions (POWER bridge) */
+// XXX: to be tested
+void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb)
+{
+    int i, c, d, reg;
+
+    d = 24;
+    reg = dest;
+    for (i = 0; i < T1; i++) {
+        c = glue(ldub, MEMSUFFIX)((uint32_t)T0++);
+        /* ra (if not 0) and rb are never modified */
+        if (likely(reg != rb && (ra == 0 || reg != ra))) {
+            ugpr(reg) = (ugpr(reg) & ~(0xFF << d)) | (c << d);
+        }
+        if (unlikely(c == T2))
+            break;
+        if (likely(d != 0)) {
+            d -= 8;
+        } else {
+            d = 24;
+            reg++;
+            reg = reg & 0x1F;
+        }
+    }
+    T0 = i;
+}
+
+/* XXX: TAGs are not managed */
+void glue(do_POWER2_lfq, MEMSUFFIX) (void)
+{
+    FT0 = glue(ldfq, MEMSUFFIX)((uint32_t)T0);
+    FT1 = glue(ldfq, MEMSUFFIX)((uint32_t)(T0 + 4));
+}
+
+static inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
+{
+    union {
+        double d;
+        uint64_t u;
+    } u;
+
+    u.d = glue(ldfq, MEMSUFFIX)(EA);
+    u.u = ((u.u & 0xFF00000000000000ULL) >> 56) |
+        ((u.u & 0x00FF000000000000ULL) >> 40) |
+        ((u.u & 0x0000FF0000000000ULL) >> 24) |
+        ((u.u & 0x000000FF00000000ULL) >> 8) |
+        ((u.u & 0x00000000FF000000ULL) << 8) |
+        ((u.u & 0x0000000000FF0000ULL) << 24) |
+        ((u.u & 0x000000000000FF00ULL) << 40) |
+        ((u.u & 0x00000000000000FFULL) << 56);
+
+    return u.d;
+}
+
+void glue(do_POWER2_lfq_le, MEMSUFFIX) (void)
+{
+    FT0 = glue(ldfqr, MEMSUFFIX)((uint32_t)(T0 + 4));
+    FT1 = glue(ldfqr, MEMSUFFIX)((uint32_t)T0);
+}
+
+void glue(do_POWER2_stfq, MEMSUFFIX) (void)
+{
+    glue(stfq, MEMSUFFIX)((uint32_t)T0, FT0);
+    glue(stfq, MEMSUFFIX)((uint32_t)(T0 + 4), FT1);
+}
+
+static inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
+{
+    union {
+        double d;
+        uint64_t u;
+    } u;
+
+    u.d = d;
+    u.u = ((u.u & 0xFF00000000000000ULL) >> 56) |
+        ((u.u & 0x00FF000000000000ULL) >> 40) |
+        ((u.u & 0x0000FF0000000000ULL) >> 24) |
+        ((u.u & 0x000000FF00000000ULL) >> 8) |
+        ((u.u & 0x00000000FF000000ULL) << 8) |
+        ((u.u & 0x0000000000FF0000ULL) << 24) |
+        ((u.u & 0x000000000000FF00ULL) << 40) |
+        ((u.u & 0x00000000000000FFULL) << 56);
+    glue(stfq, MEMSUFFIX)(EA, u.d);
+}
+
+void glue(do_POWER2_stfq_le, MEMSUFFIX) (void)
+{
+    glue(stfqr, MEMSUFFIX)((uint32_t)(T0 + 4), FT0);
+    glue(stfqr, MEMSUFFIX)((uint32_t)T0, FT1);
+}
+
 #undef MEMSUFFIX

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_mem.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_mem.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_mem.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,6 +1,22 @@
-/* External helpers */
-void glue(do_lsw, MEMSUFFIX) (int dst);
-void glue(do_stsw, MEMSUFFIX) (int src);
+/*
+ *  PowerPC emulation micro-operations 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
 
 static inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA)
 {
@@ -11,7 +27,7 @@
 static inline int32_t glue(ld16rs, MEMSUFFIX) (target_ulong EA)
 {
     int16_t tmp = glue(lduw, MEMSUFFIX)(EA);
-    return ((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
+    return (int16_t)((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
 }
 
 static inline uint32_t glue(ld32r, MEMSUFFIX) (target_ulong EA)
@@ -21,6 +37,35 @@
         ((tmp & 0x0000FF00) << 8) | ((tmp & 0x000000FF) << 24);
 }
 
+#if defined(TARGET_PPC64) || defined(TARGET_PPCEMB)
+static inline uint64_t glue(ld64r, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t tmp = glue(ldq, MEMSUFFIX)(EA);
+    return ((tmp & 0xFF00000000000000ULL) >> 56) |
+        ((tmp & 0x00FF000000000000ULL) >> 40) |
+        ((tmp & 0x0000FF0000000000ULL) >> 24) |
+        ((tmp & 0x000000FF00000000ULL) >> 8) |
+        ((tmp & 0x00000000FF000000ULL) << 8) |
+        ((tmp & 0x0000000000FF0000ULL) << 24) |
+        ((tmp & 0x000000000000FF00ULL) << 40) |
+        ((tmp & 0x00000000000000FFULL) << 54);
+}
+#endif
+
+#if defined(TARGET_PPC64)
+static inline int64_t glue(ldsl, MEMSUFFIX) (target_ulong EA)
+{
+    return (int32_t)glue(ldl, MEMSUFFIX)(EA);
+}
+
+static inline int64_t glue(ld32rs, MEMSUFFIX) (target_ulong EA)
+{
+    uint32_t tmp = glue(ldl, MEMSUFFIX)(EA);
+    return (int32_t)((tmp & 0xFF000000) >> 24) | ((tmp & 0x00FF0000) >> 8) |
+        ((tmp & 0x0000FF00) << 8) | ((tmp & 0x000000FF) << 24);
+}
+#endif
+
 static inline void glue(st16r, MEMSUFFIX) (target_ulong EA, uint16_t data)
 {
     uint16_t tmp = ((data & 0xFF00) >> 8) | ((data & 0x00FF) << 8);
@@ -34,158 +79,328 @@
     glue(stl, MEMSUFFIX)(EA, tmp);
 }
 
+#if defined(TARGET_PPC64) || defined(TARGET_PPCEMB)
+static inline void glue(st64r, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    uint64_t tmp = ((data & 0xFF00000000000000ULL) >> 56) |
+        ((data & 0x00FF000000000000ULL) >> 40) |
+        ((data & 0x0000FF0000000000ULL) >> 24) |
+        ((data & 0x000000FF00000000ULL) >> 8) |
+        ((data & 0x00000000FF000000ULL) << 8) |
+        ((data & 0x0000000000FF0000ULL) << 24) |
+        ((data & 0x000000000000FF00ULL) << 40) |
+        ((data & 0x00000000000000FFULL) << 56);
+    glue(stq, MEMSUFFIX)(EA, tmp);
+}
+#endif
+
 /***                             Integer load                              ***/
 #define PPC_LD_OP(name, op)                                                   \
-PPC_OP(glue(glue(l, name), MEMSUFFIX))                                        \
+void OPPROTO glue(glue(op_l, name), MEMSUFFIX) (void)                         \
 {                                                                             \
-    T1 = glue(op, MEMSUFFIX)(T0);                                             \
+    T1 = glue(op, MEMSUFFIX)((uint32_t)T0);                                   \
     RETURN();                                                                 \
 }
 
+#if defined(TARGET_PPC64)
+#define PPC_LD_OP_64(name, op)                                                \
+void OPPROTO glue(glue(glue(op_l, name), _64), MEMSUFFIX) (void)              \
+{                                                                             \
+    T1 = glue(op, MEMSUFFIX)((uint64_t)T0);                                   \
+    RETURN();                                                                 \
+}
+#endif
+
 #define PPC_ST_OP(name, op)                                                   \
-PPC_OP(glue(glue(st, name), MEMSUFFIX))                                       \
+void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void)                        \
 {                                                                             \
-    glue(op, MEMSUFFIX)(T0, T1);                                              \
+    glue(op, MEMSUFFIX)((uint32_t)T0, T1);                                    \
     RETURN();                                                                 \
 }
 
+#if defined(TARGET_PPC64)
+#define PPC_ST_OP_64(name, op)                                                \
+void OPPROTO glue(glue(glue(op_st, name), _64), MEMSUFFIX) (void)             \
+{                                                                             \
+    glue(op, MEMSUFFIX)((uint64_t)T0, T1);                                    \
+    RETURN();                                                                 \
+}
+#endif
+
 PPC_LD_OP(bz, ldub);
 PPC_LD_OP(ha, ldsw);
 PPC_LD_OP(hz, lduw);
 PPC_LD_OP(wz, ldl);
+#if defined(TARGET_PPC64)
+PPC_LD_OP(d, ldq);
+PPC_LD_OP(wa, ldsl);
+PPC_LD_OP_64(d, ldq);
+PPC_LD_OP_64(wa, ldsl);
+PPC_LD_OP_64(bz, ldub);
+PPC_LD_OP_64(ha, ldsw);
+PPC_LD_OP_64(hz, lduw);
+PPC_LD_OP_64(wz, ldl);
+#endif
 
 PPC_LD_OP(ha_le, ld16rs);
 PPC_LD_OP(hz_le, ld16r);
 PPC_LD_OP(wz_le, ld32r);
+#if defined(TARGET_PPC64)
+PPC_LD_OP(d_le, ld64r);
+PPC_LD_OP(wa_le, ld32rs);
+PPC_LD_OP_64(d_le, ld64r);
+PPC_LD_OP_64(wa_le, ld32rs);
+PPC_LD_OP_64(ha_le, ld16rs);
+PPC_LD_OP_64(hz_le, ld16r);
+PPC_LD_OP_64(wz_le, ld32r);
+#endif
 
 /***                              Integer store                            ***/
 PPC_ST_OP(b, stb);
 PPC_ST_OP(h, stw);
 PPC_ST_OP(w, stl);
+#if defined(TARGET_PPC64)
+PPC_ST_OP(d, stq);
+PPC_ST_OP_64(d, stq);
+PPC_ST_OP_64(b, stb);
+PPC_ST_OP_64(h, stw);
+PPC_ST_OP_64(w, stl);
+#endif
 
 PPC_ST_OP(h_le, st16r);
 PPC_ST_OP(w_le, st32r);
+#if defined(TARGET_PPC64)
+PPC_ST_OP(d_le, st64r);
+PPC_ST_OP_64(d_le, st64r);
+PPC_ST_OP_64(h_le, st16r);
+PPC_ST_OP_64(w_le, st32r);
+#endif
 
 /***                Integer load and store with byte reverse               ***/
 PPC_LD_OP(hbr, ld16r);
 PPC_LD_OP(wbr, ld32r);
 PPC_ST_OP(hbr, st16r);
 PPC_ST_OP(wbr, st32r);
+#if defined(TARGET_PPC64)
+PPC_LD_OP_64(hbr, ld16r);
+PPC_LD_OP_64(wbr, ld32r);
+PPC_ST_OP_64(hbr, st16r);
+PPC_ST_OP_64(wbr, st32r);
+#endif
 
 PPC_LD_OP(hbr_le, lduw);
 PPC_LD_OP(wbr_le, ldl);
 PPC_ST_OP(hbr_le, stw);
 PPC_ST_OP(wbr_le, stl);
+#if defined(TARGET_PPC64)
+PPC_LD_OP_64(hbr_le, lduw);
+PPC_LD_OP_64(wbr_le, ldl);
+PPC_ST_OP_64(hbr_le, stw);
+PPC_ST_OP_64(wbr_le, stl);
+#endif
 
 /***                    Integer load and store multiple                    ***/
-PPC_OP(glue(lmw, MEMSUFFIX))
+void OPPROTO glue(op_lmw, MEMSUFFIX) (void)
 {
-    int dst = PARAM(1);
+    glue(do_lmw, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
 
-    for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ldl, MEMSUFFIX)(T0);
-    }
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lmw_64, MEMSUFFIX) (void)
+{
+    glue(do_lmw_64, MEMSUFFIX)(PARAM1);
     RETURN();
 }
+#endif
 
-PPC_OP(glue(stmw, MEMSUFFIX))
+void OPPROTO glue(op_lmw_le, MEMSUFFIX) (void)
 {
-    int src = PARAM(1);
+    glue(do_lmw_le, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
 
-    for (; src < 32; src++, T0 += 4) {
-        glue(stl, MEMSUFFIX)(T0, ugpr(src));
-    }
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lmw_le_64, MEMSUFFIX) (void)
+{
+    glue(do_lmw_le_64, MEMSUFFIX)(PARAM1);
     RETURN();
 }
+#endif
 
-PPC_OP(glue(lmw_le, MEMSUFFIX))
+void OPPROTO glue(op_stmw, MEMSUFFIX) (void)
 {
-    int dst = PARAM(1);
+    glue(do_stmw, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
 
-    for (; dst < 32; dst++, T0 += 4) {
-        ugpr(dst) = glue(ld32r, MEMSUFFIX)(T0);
-    }
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stmw_64, MEMSUFFIX) (void)
+{
+    glue(do_stmw_64, MEMSUFFIX)(PARAM1);
     RETURN();
 }
+#endif
 
-PPC_OP(glue(stmw_le, MEMSUFFIX))
+void OPPROTO glue(op_stmw_le, MEMSUFFIX) (void)
 {
-    int src = PARAM(1);
+    glue(do_stmw_le, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
 
-    for (; src < 32; src++, T0 += 4) {
-        glue(st32r, MEMSUFFIX)(T0, ugpr(src));
-    }
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stmw_le_64, MEMSUFFIX) (void)
+{
+    glue(do_stmw_le_64, MEMSUFFIX)(PARAM1);
     RETURN();
 }
+#endif
 
 /***                    Integer load and store strings                     ***/
-PPC_OP(glue(lswi, MEMSUFFIX))
+void OPPROTO glue(op_lswi, MEMSUFFIX) (void)
 {
-    glue(do_lsw, MEMSUFFIX)(PARAM(1));
+    glue(do_lsw, MEMSUFFIX)(PARAM1);
     RETURN();
 }
 
-void glue(do_lsw_le, MEMSUFFIX) (int dst);
-PPC_OP(glue(lswi_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lswi_64, MEMSUFFIX) (void)
 {
-    glue(do_lsw_le, MEMSUFFIX)(PARAM(1));
+    glue(do_lsw_64, MEMSUFFIX)(PARAM1);
     RETURN();
 }
+#endif
 
+void OPPROTO glue(op_lswi_le, MEMSUFFIX) (void)
+{
+    glue(do_lsw_le, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lswi_le_64, MEMSUFFIX) (void)
+{
+    glue(do_lsw_le_64, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+#endif
+
 /* PPC32 specification says we must generate an exception if
  * rA is in the range of registers to be loaded.
  * In an other hand, IBM says this is valid, but rA won't be loaded.
  * For now, I'll follow the spec...
  */
-PPC_OP(glue(lswx, MEMSUFFIX))
+void OPPROTO glue(op_lswx, MEMSUFFIX) (void)
 {
-    if (T1 > 0) {
-        if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
-            (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
+    /* Note: T1 comes from xer_bc then no cast is needed */
+    if (likely(T1 != 0)) {
+        if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+                     (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
             do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
         } else {
-            glue(do_lsw, MEMSUFFIX)(PARAM(1));
+            glue(do_lsw, MEMSUFFIX)(PARAM1);
         }
     }
     RETURN();
 }
 
-PPC_OP(glue(lswx_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lswx_64, MEMSUFFIX) (void)
 {
-    if (T1 > 0) {
-        if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
-            (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
+    /* Note: T1 comes from xer_bc then no cast is needed */
+    if (likely(T1 != 0)) {
+        if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+                     (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
             do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
         } else {
-            glue(do_lsw_le, MEMSUFFIX)(PARAM(1));
+            glue(do_lsw_64, MEMSUFFIX)(PARAM1);
         }
     }
     RETURN();
 }
+#endif
 
-PPC_OP(glue(stsw, MEMSUFFIX))
+void OPPROTO glue(op_lswx_le, MEMSUFFIX) (void)
 {
-    glue(do_stsw, MEMSUFFIX)(PARAM(1));
+    /* Note: T1 comes from xer_bc then no cast is needed */
+    if (likely(T1 != 0)) {
+        if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+                     (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
+            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+        } else {
+            glue(do_lsw_le, MEMSUFFIX)(PARAM1);
+        }
+    }
     RETURN();
 }
 
-void glue(do_stsw_le, MEMSUFFIX) (int src);
-PPC_OP(glue(stsw_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lswx_le_64, MEMSUFFIX) (void)
 {
-    glue(do_stsw_le, MEMSUFFIX)(PARAM(1));
+    /* Note: T1 comes from xer_bc then no cast is needed */
+    if (likely(T1 != 0)) {
+        if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+                     (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
+            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+        } else {
+            glue(do_lsw_le_64, MEMSUFFIX)(PARAM1);
+        }
+    }
     RETURN();
 }
+#endif
 
+void OPPROTO glue(op_stsw, MEMSUFFIX) (void)
+{
+    glue(do_stsw, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stsw_64, MEMSUFFIX) (void)
+{
+    glue(do_stsw_64, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_stsw_le, MEMSUFFIX) (void)
+{
+    glue(do_stsw_le, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stsw_le_64, MEMSUFFIX) (void)
+{
+    glue(do_stsw_le_64, MEMSUFFIX)(PARAM1);
+    RETURN();
+}
+#endif
+
 /***                         Floating-point store                          ***/
 #define PPC_STF_OP(name, op)                                                  \
-PPC_OP(glue(glue(st, name), MEMSUFFIX))                                       \
+void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void)                        \
 {                                                                             \
-    glue(op, MEMSUFFIX)(T0, FT1);                                     \
+    glue(op, MEMSUFFIX)((uint32_t)T0, FT0);                                   \
     RETURN();                                                                 \
 }
 
+#if defined(TARGET_PPC64)
+#define PPC_STF_OP_64(name, op)                                               \
+void OPPROTO glue(glue(glue(op_st, name), _64), MEMSUFFIX) (void)             \
+{                                                                             \
+    glue(op, MEMSUFFIX)((uint64_t)T0, FT0);                                   \
+    RETURN();                                                                 \
+}
+#endif
+
 PPC_STF_OP(fd, stfq);
 PPC_STF_OP(fs, stfl);
+#if defined(TARGET_PPC64)
+PPC_STF_OP_64(fd, stfq);
+PPC_STF_OP_64(fs, stfl);
+#endif
 
 static inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
 {
@@ -223,17 +438,34 @@
 
 PPC_STF_OP(fd_le, stfqr);
 PPC_STF_OP(fs_le, stflr);
+#if defined(TARGET_PPC64)
+PPC_STF_OP_64(fd_le, stfqr);
+PPC_STF_OP_64(fs_le, stflr);
+#endif
 
 /***                         Floating-point load                           ***/
 #define PPC_LDF_OP(name, op)                                                  \
-PPC_OP(glue(glue(l, name), MEMSUFFIX))                                        \
+void OPPROTO glue(glue(op_l, name), MEMSUFFIX) (void)                         \
 {                                                                             \
-    FT1 = glue(op, MEMSUFFIX)(T0);                                    \
+    FT0 = glue(op, MEMSUFFIX)((uint32_t)T0);                                  \
     RETURN();                                                                 \
 }
 
+#if defined(TARGET_PPC64)
+#define PPC_LDF_OP_64(name, op)                                               \
+void OPPROTO glue(glue(glue(op_l, name), _64), MEMSUFFIX) (void)              \
+{                                                                             \
+    FT0 = glue(op, MEMSUFFIX)((uint64_t)T0);                                  \
+    RETURN();                                                                 \
+}
+#endif
+
 PPC_LDF_OP(fd, ldfq);
 PPC_LDF_OP(fs, ldfl);
+#if defined(TARGET_PPC64)
+PPC_LDF_OP_64(fd, ldfq);
+PPC_LDF_OP_64(fs, ldfl);
+#endif
 
 static inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
 {
@@ -273,99 +505,652 @@
 
 PPC_LDF_OP(fd_le, ldfqr);
 PPC_LDF_OP(fs_le, ldflr);
+#if defined(TARGET_PPC64)
+PPC_LDF_OP_64(fd_le, ldfqr);
+PPC_LDF_OP_64(fs_le, ldflr);
+#endif
 
 /* Load and set reservation */
-PPC_OP(glue(lwarx, MEMSUFFIX))
+void OPPROTO glue(op_lwarx, MEMSUFFIX) (void)
 {
-    if (T0 & 0x03) {
+    if (unlikely(T0 & 0x03)) {
         do_raise_exception(EXCP_ALIGN);
     } else {
-       T1 = glue(ldl, MEMSUFFIX)(T0);
-       regs->reserve = T0;
+        T1 = glue(ldl, MEMSUFFIX)((uint32_t)T0);
+        regs->reserve = (uint32_t)T0;
     }
     RETURN();
 }
 
-PPC_OP(glue(lwarx_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void)
 {
-    if (T0 & 0x03) {
+    if (unlikely(T0 & 0x03)) {
         do_raise_exception(EXCP_ALIGN);
     } else {
-       T1 = glue(ld32r, MEMSUFFIX)(T0);
-       regs->reserve = T0;
+        T1 = glue(ldl, MEMSUFFIX)((uint64_t)T0);
+        regs->reserve = (uint64_t)T0;
     }
     RETURN();
 }
 
+void OPPROTO glue(op_ldarx, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ldq, MEMSUFFIX)((uint32_t)T0);
+        regs->reserve = (uint32_t)T0;
+    }
+    RETURN();
+}
+
+void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ldq, MEMSUFFIX)((uint64_t)T0);
+        regs->reserve = (uint64_t)T0;
+    }
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+        regs->reserve = (uint32_t)T0;
+    }
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+        regs->reserve = (uint64_t)T0;
+    }
+    RETURN();
+}
+
+void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ld64r, MEMSUFFIX)((uint32_t)T0);
+        regs->reserve = (uint32_t)T0;
+    }
+    RETURN();
+}
+
+void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        T1 = glue(ld64r, MEMSUFFIX)((uint64_t)T0);
+        regs->reserve = (uint64_t)T0;
+    }
+    RETURN();
+}
+#endif
+
 /* Store with reservation */
-PPC_OP(glue(stwcx, MEMSUFFIX))
+void OPPROTO glue(op_stwcx, MEMSUFFIX) (void)
 {
-    if (T0 & 0x03) {
+    if (unlikely(T0 & 0x03)) {
         do_raise_exception(EXCP_ALIGN);
     } else {
-        if (regs->reserve != T0) {
+        if (unlikely(regs->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_ov;
         } else {
-            glue(stl, MEMSUFFIX)(T0, T1);
+            glue(stl, MEMSUFFIX)((uint32_t)T0, T1);
             env->crf[0] = xer_ov | 0x02;
         }
     }
-    regs->reserve = 0;
+    regs->reserve = -1;
     RETURN();
 }
 
-PPC_OP(glue(stwcx_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void)
 {
-    if (T0 & 0x03) {
+    if (unlikely(T0 & 0x03)) {
         do_raise_exception(EXCP_ALIGN);
     } else {
-        if (regs->reserve != T0) {
+        if (unlikely(regs->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_ov;
         } else {
-            glue(st32r, MEMSUFFIX)(T0, T1);
+            glue(stl, MEMSUFFIX)((uint64_t)T0, T1);
             env->crf[0] = xer_ov | 0x02;
         }
     }
-    regs->reserve = 0;
+    regs->reserve = -1;
     RETURN();
 }
 
-PPC_OP(glue(dcbz, MEMSUFFIX))
+void OPPROTO glue(op_stdcx, MEMSUFFIX) (void)
 {
-    glue(stl, MEMSUFFIX)(T0 + 0x00, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x04, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x08, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x0C, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x10, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x14, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x18, 0);
-    glue(stl, MEMSUFFIX)(T0 + 0x1C, 0);
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint32_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(stq, MEMSUFFIX)((uint32_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
     RETURN();
 }
 
+void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint64_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(stq, MEMSUFFIX)((uint64_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint32_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(st32r, MEMSUFFIX)((uint32_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint64_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(st32r, MEMSUFFIX)((uint64_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
+    RETURN();
+}
+
+void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint32_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(st64r, MEMSUFFIX)((uint32_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
+    RETURN();
+}
+
+void OPPROTO glue(op_stdcx_le_64, MEMSUFFIX) (void)
+{
+    if (unlikely(T0 & 0x03)) {
+        do_raise_exception(EXCP_ALIGN);
+    } else {
+        if (unlikely(regs->reserve != (uint64_t)T0)) {
+            env->crf[0] = xer_ov;
+        } else {
+            glue(st64r, MEMSUFFIX)((uint64_t)T0, T1);
+            env->crf[0] = xer_ov | 0x02;
+        }
+    }
+    regs->reserve = -1;
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_dcbz, MEMSUFFIX) (void)
+{
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x00), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x04), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x08), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x0C), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x10), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x14), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x18), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x1C), 0);
+#if DCACHE_LINE_SIZE == 64
+    /* XXX: cache line size should be 64 for POWER & PowerPC 601 */
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x20UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x24UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x28UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x2CUL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x30UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x34UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x38UL), 0);
+    glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x3CUL), 0);
+#endif
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_dcbz_64, MEMSUFFIX) (void)
+{
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x00), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x04), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x08), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x0C), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x10), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x14), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x18), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x1C), 0);
+#if DCACHE_LINE_SIZE == 64
+    /* XXX: cache line size should be 64 for POWER & PowerPC 601 */
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x20UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x24UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x28UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x2CUL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x30UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x34UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x38UL), 0);
+    glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x3CUL), 0);
+#endif
+    RETURN();
+}
+#endif
+
+/* Instruction cache block invalidate */
+void OPPROTO glue(op_icbi, MEMSUFFIX) (void)
+{
+    glue(do_icbi, MEMSUFFIX)();
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_icbi_64, MEMSUFFIX) (void)
+{
+    glue(do_icbi_64, MEMSUFFIX)();
+    RETURN();
+}
+#endif
+
 /* External access */
-PPC_OP(glue(eciwx, MEMSUFFIX))
+void OPPROTO glue(op_eciwx, MEMSUFFIX) (void)
 {
-    T1 = glue(ldl, MEMSUFFIX)(T0);
+    T1 = glue(ldl, MEMSUFFIX)((uint32_t)T0);
     RETURN();
 }
 
-PPC_OP(glue(ecowx, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_eciwx_64, MEMSUFFIX) (void)
 {
-    glue(stl, MEMSUFFIX)(T0, T1);
+    T1 = glue(ldl, MEMSUFFIX)((uint64_t)T0);
     RETURN();
 }
+#endif
 
-PPC_OP(glue(eciwx_le, MEMSUFFIX))
+void OPPROTO glue(op_ecowx, MEMSUFFIX) (void)
 {
-    T1 = glue(ld32r, MEMSUFFIX)(T0);
+    glue(stl, MEMSUFFIX)((uint32_t)T0, T1);
     RETURN();
 }
 
-PPC_OP(glue(ecowx_le, MEMSUFFIX))
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_ecowx_64, MEMSUFFIX) (void)
 {
-    glue(st32r, MEMSUFFIX)(T0, T1);
+    glue(stl, MEMSUFFIX)((uint64_t)T0, T1);
     RETURN();
 }
+#endif
 
+void OPPROTO glue(op_eciwx_le, MEMSUFFIX) (void)
+{
+    T1 = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_eciwx_le_64, MEMSUFFIX) (void)
+{
+    T1 = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_ecowx_le, MEMSUFFIX) (void)
+{
+    glue(st32r, MEMSUFFIX)((uint32_t)T0, T1);
+    RETURN();
+}
+
+#if defined(TARGET_PPC64)
+void OPPROTO glue(op_ecowx_le_64, MEMSUFFIX) (void)
+{
+    glue(st32r, MEMSUFFIX)((uint64_t)T0, T1);
+    RETURN();
+}
+#endif
+
+/* XXX: those micro-ops need tests ! */
+/* PowerPC 601 specific instructions (POWER bridge) */
+void OPPROTO glue(op_POWER_lscbx, MEMSUFFIX) (void)
+{
+    /* When byte count is 0, do nothing */
+    if (likely(T1 != 0)) {
+        glue(do_POWER_lscbx, MEMSUFFIX)(PARAM1, PARAM2, PARAM3);
+    }
+    RETURN();
+}
+
+/* POWER2 quad load and store */
+/* XXX: TAGs are not managed */
+void OPPROTO glue(op_POWER2_lfq, MEMSUFFIX) (void)
+{
+    glue(do_POWER2_lfq, MEMSUFFIX)();
+    RETURN();
+}
+
+void glue(op_POWER2_lfq_le, MEMSUFFIX) (void)
+{
+    glue(do_POWER2_lfq_le, MEMSUFFIX)();
+    RETURN();
+}
+
+void OPPROTO glue(op_POWER2_stfq, MEMSUFFIX) (void)
+{
+    glue(do_POWER2_stfq, MEMSUFFIX)();
+    RETURN();
+}
+
+void OPPROTO glue(op_POWER2_stfq_le, MEMSUFFIX) (void)
+{
+    glue(do_POWER2_stfq_le, MEMSUFFIX)();
+    RETURN();
+}
+
+#if defined(TARGET_PPCEMB)
+/* SPE extension */
+#define _PPC_SPE_LD_OP(name, op)                                              \
+void OPPROTO glue(glue(op_spe_l, name), MEMSUFFIX) (void)                     \
+{                                                                             \
+    T1_64 = glue(op, MEMSUFFIX)((uint32_t)T0);                                \
+    RETURN();                                                                 \
+}
+
+#if defined(TARGET_PPC64)
+#define _PPC_SPE_LD_OP_64(name, op)                                           \
+void OPPROTO glue(glue(glue(op_spe_l, name), _64), MEMSUFFIX) (void)          \
+{                                                                             \
+    T1_64 = glue(op, MEMSUFFIX)((uint64_t)T0);                                \
+    RETURN();                                                                 \
+}
+#define PPC_SPE_LD_OP(name, op)                                               \
+_PPC_SPE_LD_OP(name, op);                                                     \
+_PPC_SPE_LD_OP_64(name, op)
+#else
+#define PPC_SPE_LD_OP(name, op)                                               \
+_PPC_SPE_LD_OP(name, op)
+#endif
+
+
+#define _PPC_SPE_ST_OP(name, op)                                              \
+void OPPROTO glue(glue(op_spe_st, name), MEMSUFFIX) (void)                    \
+{                                                                             \
+    glue(op, MEMSUFFIX)((uint32_t)T0, T1_64);                                 \
+    RETURN();                                                                 \
+}
+
+#if defined(TARGET_PPC64)
+#define _PPC_SPE_ST_OP_64(name, op)                                           \
+void OPPROTO glue(glue(glue(op_spe_st, name), _64), MEMSUFFIX) (void)         \
+{                                                                             \
+    glue(op, MEMSUFFIX)((uint64_t)T0, T1_64);                                 \
+    RETURN();                                                                 \
+}
+#define PPC_SPE_ST_OP(name, op)                                               \
+_PPC_SPE_ST_OP(name, op);                                                     \
+_PPC_SPE_ST_OP_64(name, op)
+#else
+#define PPC_SPE_ST_OP(name, op)                                               \
+_PPC_SPE_ST_OP(name, op)
+#endif
+
+#if !defined(TARGET_PPC64)
+PPC_SPE_LD_OP(dd, ldq);
+PPC_SPE_ST_OP(dd, stq);
+PPC_SPE_LD_OP(dd_le, ld64r);
+PPC_SPE_ST_OP(dd_le, st64r);
+#endif
+static inline uint64_t glue(spe_ldw, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(ldl, MEMSUFFIX)(EA) << 32;
+    ret |= (uint64_t)glue(ldl, MEMSUFFIX)(EA + 4);
+    return ret;
+}
+PPC_SPE_LD_OP(dw, spe_ldw);
+static inline void glue(spe_stdw, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    glue(stl, MEMSUFFIX)(EA, data >> 32);
+    glue(stl, MEMSUFFIX)(EA + 4, data);
+}
+PPC_SPE_ST_OP(dw, spe_stdw);
+static inline uint64_t glue(spe_ldw_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(ld32r, MEMSUFFIX)(EA) << 32;
+    ret |= (uint64_t)glue(ld32r, MEMSUFFIX)(EA + 4);
+    return ret;
+}
+PPC_SPE_LD_OP(dw_le, spe_ldw_le);
+static inline void glue(spe_stdw_le, MEMSUFFIX) (target_ulong EA,
+                                                 uint64_t data)
+{
+    glue(st32r, MEMSUFFIX)(EA, data >> 32);
+    glue(st32r, MEMSUFFIX)(EA + 4, data);
+}
+PPC_SPE_ST_OP(dw_le, spe_stdw_le);
+static inline uint64_t glue(spe_ldh, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 48;
+    ret |= (uint64_t)glue(lduw, MEMSUFFIX)(EA + 2) << 32;
+    ret |= (uint64_t)glue(lduw, MEMSUFFIX)(EA + 4) << 16;
+    ret |= (uint64_t)glue(lduw, MEMSUFFIX)(EA + 6);
+    return ret;
+}
+PPC_SPE_LD_OP(dh, spe_ldh);
+static inline void glue(spe_stdh, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    glue(stw, MEMSUFFIX)(EA, data >> 48);
+    glue(stw, MEMSUFFIX)(EA + 2, data >> 32);
+    glue(stw, MEMSUFFIX)(EA + 4, data >> 16);
+    glue(stw, MEMSUFFIX)(EA + 6, data);
+}
+PPC_SPE_ST_OP(dh, spe_stdh);
+static inline uint64_t glue(spe_ldh_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 48;
+    ret |= (uint64_t)glue(ld16r, MEMSUFFIX)(EA + 2) << 32;
+    ret |= (uint64_t)glue(ld16r, MEMSUFFIX)(EA + 4) << 16;
+    ret |= (uint64_t)glue(ld16r, MEMSUFFIX)(EA + 6);
+    return ret;
+}
+PPC_SPE_LD_OP(dh_le, spe_ldh_le);
+static inline void glue(spe_stdh_le, MEMSUFFIX) (target_ulong EA,
+                                                 uint64_t data)
+{
+    glue(st16r, MEMSUFFIX)(EA, data >> 48);
+    glue(st16r, MEMSUFFIX)(EA + 2, data >> 32);
+    glue(st16r, MEMSUFFIX)(EA + 4, data >> 16);
+    glue(st16r, MEMSUFFIX)(EA + 6, data);
+}
+PPC_SPE_ST_OP(dh_le, spe_stdh_le);
+static inline uint64_t glue(spe_lwhe, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 48;
+    ret |= (uint64_t)glue(lduw, MEMSUFFIX)(EA + 2) << 16;
+    return ret;
+}
+PPC_SPE_LD_OP(whe, spe_lwhe);
+static inline void glue(spe_stwhe, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    glue(stw, MEMSUFFIX)(EA, data >> 48);
+    glue(stw, MEMSUFFIX)(EA + 2, data >> 16);
+}
+PPC_SPE_ST_OP(whe, spe_stwhe);
+static inline uint64_t glue(spe_lwhe_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 48;
+    ret |= (uint64_t)glue(ld16r, MEMSUFFIX)(EA + 2) << 16;
+    return ret;
+}
+PPC_SPE_LD_OP(whe_le, spe_lwhe_le);
+static inline void glue(spe_stwhe_le, MEMSUFFIX) (target_ulong EA,
+                                                  uint64_t data)
+{
+    glue(st16r, MEMSUFFIX)(EA, data >> 48);
+    glue(st16r, MEMSUFFIX)(EA + 2, data >> 16);
+}
+PPC_SPE_ST_OP(whe_le, spe_stwhe_le);
+static inline uint64_t glue(spe_lwhou, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(lduw, MEMSUFFIX)(EA) << 32;
+    ret |= (uint64_t)glue(lduw, MEMSUFFIX)(EA + 2);
+    return ret;
+}
+PPC_SPE_LD_OP(whou, spe_lwhou);
+static inline uint64_t glue(spe_lwhos, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = ((uint64_t)((int32_t)glue(ldsw, MEMSUFFIX)(EA))) << 32;
+    ret |= (uint64_t)((int32_t)glue(ldsw, MEMSUFFIX)(EA + 2));
+    return ret;
+}
+PPC_SPE_LD_OP(whos, spe_lwhos);
+static inline void glue(spe_stwho, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    glue(stw, MEMSUFFIX)(EA, data >> 32);
+    glue(stw, MEMSUFFIX)(EA + 2, data);
+}
+PPC_SPE_ST_OP(who, spe_stwho);
+static inline uint64_t glue(spe_lwhou_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = (uint64_t)glue(ld16r, MEMSUFFIX)(EA) << 32;
+    ret |= (uint64_t)glue(ld16r, MEMSUFFIX)(EA + 2);
+    return ret;
+}
+PPC_SPE_LD_OP(whou_le, spe_lwhou_le);
+static inline uint64_t glue(spe_lwhos_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    ret = ((uint64_t)((int32_t)glue(ld16rs, MEMSUFFIX)(EA))) << 32;
+    ret |= (uint64_t)((int32_t)glue(ld16rs, MEMSUFFIX)(EA + 2));
+    return ret;
+}
+PPC_SPE_LD_OP(whos_le, spe_lwhos_le);
+static inline void glue(spe_stwho_le, MEMSUFFIX) (target_ulong EA,
+                                                  uint64_t data)
+{
+    glue(st16r, MEMSUFFIX)(EA, data >> 32);
+    glue(st16r, MEMSUFFIX)(EA + 2, data);
+}
+PPC_SPE_ST_OP(who_le, spe_stwho_le);
+#if !defined(TARGET_PPC64)
+static inline void glue(spe_stwwo, MEMSUFFIX) (target_ulong EA, uint64_t data)
+{
+    glue(stl, MEMSUFFIX)(EA, data);
+}
+PPC_SPE_ST_OP(wwo, spe_stwwo);
+static inline void glue(spe_stwwo_le, MEMSUFFIX) (target_ulong EA,
+                                                 uint64_t data)
+{
+    glue(st32r, MEMSUFFIX)(EA, data);
+}
+PPC_SPE_ST_OP(wwo_le, spe_stwwo_le);
+#endif
+static inline uint64_t glue(spe_lh, MEMSUFFIX) (target_ulong EA)
+{
+    uint16_t tmp;
+    tmp = glue(lduw, MEMSUFFIX)(EA);
+    return ((uint64_t)tmp << 48) | ((uint64_t)tmp << 16);
+}
+PPC_SPE_LD_OP(h, spe_lh);
+static inline uint64_t glue(spe_lh_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint16_t tmp;
+    tmp = glue(ld16r, MEMSUFFIX)(EA);
+    return ((uint64_t)tmp << 48) | ((uint64_t)tmp << 16);
+}
+PPC_SPE_LD_OP(h_le, spe_lh_le);
+static inline uint64_t glue(spe_lwwsplat, MEMSUFFIX) (target_ulong EA)
+{
+    uint32_t tmp;
+    tmp = glue(ldl, MEMSUFFIX)(EA);
+    return ((uint64_t)tmp << 32) | (uint64_t)tmp;
+}
+PPC_SPE_LD_OP(wwsplat, spe_lwwsplat);
+static inline uint64_t glue(spe_lwwsplat_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint32_t tmp;
+    tmp = glue(ld32r, MEMSUFFIX)(EA);
+    return ((uint64_t)tmp << 32) | (uint64_t)tmp;
+}
+PPC_SPE_LD_OP(wwsplat_le, spe_lwwsplat_le);
+static inline uint64_t glue(spe_lwhsplat, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    uint16_t tmp;
+    tmp = glue(lduw, MEMSUFFIX)(EA);
+    ret = ((uint64_t)tmp << 48) | ((uint64_t)tmp << 32);
+    tmp = glue(lduw, MEMSUFFIX)(EA + 2);
+    ret |= ((uint64_t)tmp << 16) | (uint64_t)tmp;
+    return ret;
+}
+PPC_SPE_LD_OP(whsplat, spe_lwhsplat);
+static inline uint64_t glue(spe_lwhsplat_le, MEMSUFFIX) (target_ulong EA)
+{
+    uint64_t ret;
+    uint16_t tmp;
+    tmp = glue(ld16r, MEMSUFFIX)(EA);
+    ret = ((uint64_t)tmp << 48) | ((uint64_t)tmp << 32);
+    tmp = glue(ld16r, MEMSUFFIX)(EA + 2);
+    ret |= ((uint64_t)tmp << 16) | (uint64_t)tmp;
+    return ret;
+}
+PPC_SPE_LD_OP(whsplat_le, spe_lwhsplat_le);
+#endif /* defined(TARGET_PPCEMB) */
+
 #undef MEMSUFFIX

Modified: trunk/src/host/qemu-neo1973/target-ppc/op_template.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/op_template.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/op_template.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation micro-operations for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -19,108 +19,140 @@
  */
 
 /* General purpose registers moves */
-void OPPROTO glue(op_load_gpr_T0_gpr, REG)(void)
+void OPPROTO glue(op_load_gpr_T0_gpr, REG) (void)
 {
     T0 = regs->gpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_load_gpr_T1_gpr, REG)(void)
+void OPPROTO glue(op_load_gpr_T1_gpr, REG) (void)
 {
     T1 = regs->gpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_load_gpr_T2_gpr, REG)(void)
+void OPPROTO glue(op_load_gpr_T2_gpr, REG) (void)
 {
     T2 = regs->gpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_T0_gpr_gpr, REG)(void)
+void OPPROTO glue(op_store_T0_gpr_gpr, REG) (void)
 {
     regs->gpr[REG] = T0;
     RETURN();
 }
 
-void OPPROTO glue(op_store_T1_gpr_gpr, REG)(void)
+void OPPROTO glue(op_store_T1_gpr_gpr, REG) (void)
 {
     regs->gpr[REG] = T1;
     RETURN();
 }
 
-void OPPROTO glue(op_store_T2_gpr_gpr, REG)(void)
+#if 0 // unused
+void OPPROTO glue(op_store_T2_gpr_gpr, REG) (void)
 {
     regs->gpr[REG] = T2;
     RETURN();
 }
+#endif
 
+#if defined(TARGET_PPCEMB)
+void OPPROTO glue(op_load_gpr64_T0_gpr, REG) (void)
+{
+    T0_64 = regs->gpr[REG];
+    RETURN();
+}
+
+void OPPROTO glue(op_load_gpr64_T1_gpr, REG) (void)
+{
+    T1_64 = regs->gpr[REG];
+    RETURN();
+}
+
+#if 0 // unused
+void OPPROTO glue(op_load_gpr64_T2_gpr, REG) (void)
+{
+    T2_64 = regs->gpr[REG];
+    RETURN();
+}
+#endif
+
+void OPPROTO glue(op_store_T0_gpr64_gpr, REG) (void)
+{
+    regs->gpr[REG] = T0_64;
+    RETURN();
+}
+
+void OPPROTO glue(op_store_T1_gpr64_gpr, REG) (void)
+{
+    regs->gpr[REG] = T1_64;
+    RETURN();
+}
+
+#if 0 // unused
+void OPPROTO glue(op_store_T2_gpr64_gpr, REG) (void)
+{
+    regs->gpr[REG] = T2_64;
+    RETURN();
+}
+#endif
+#endif /* defined(TARGET_PPCEMB) */
+
 #if REG <= 7
 /* Condition register moves */
-void OPPROTO glue(op_load_crf_T0_crf, REG)(void)
+void OPPROTO glue(op_load_crf_T0_crf, REG) (void)
 {
     T0 = regs->crf[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_load_crf_T1_crf, REG)(void)
+void OPPROTO glue(op_load_crf_T1_crf, REG) (void)
 {
     T1 = regs->crf[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_T0_crf_crf, REG)(void)
+void OPPROTO glue(op_store_T0_crf_crf, REG) (void)
 {
     regs->crf[REG] = T0;
     RETURN();
 }
 
-void OPPROTO glue(op_store_T1_crf_crf, REG)(void)
+void OPPROTO glue(op_store_T1_crf_crf, REG) (void)
 {
     regs->crf[REG] = T1;
     RETURN();
 }
 
 /* Floating point condition and status register moves */
-void OPPROTO glue(op_load_fpscr_T0_fpscr, REG)(void)
+void OPPROTO glue(op_load_fpscr_T0_fpscr, REG) (void)
 {
     T0 = regs->fpscr[REG];
     RETURN();
 }
 
 #if REG == 0
-void OPPROTO glue(op_store_T0_fpscr_fpscr, REG)(void)
+void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
 {
     regs->fpscr[REG] = (regs->fpscr[REG] & 0x9) | (T0 & ~0x9);
     RETURN();
 }
 
-void OPPROTO glue(op_store_T0_fpscri_fpscr, REG)(void)
+void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
 {
-    regs->fpscr[REG] = (regs->fpscr[REG] & ~0x9) | (PARAM(1) & 0x9);
-    RETURN();
-}
-
-void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void)
-{
     regs->fpscr[REG] = (regs->fpscr[REG] & 0x9);
     RETURN();
 }
 #else
-void OPPROTO glue(op_store_T0_fpscr_fpscr, REG)(void)
+void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
 {
     regs->fpscr[REG] = T0;
     RETURN();
 }
 
-void OPPROTO glue(op_store_T0_fpscri_fpscr, REG)(void)
+void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
 {
-    regs->fpscr[REG] = PARAM(1);
-    RETURN();
-}
-
-void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void)
-{
     regs->fpscr[REG] = 0x0;
     RETURN();
 }
@@ -129,55 +161,42 @@
 #endif /* REG <= 7 */
 
 /* floating point registers moves */
-void OPPROTO glue(op_load_fpr_FT0_fpr, REG)(void)
+void OPPROTO glue(op_load_fpr_FT0_fpr, REG) (void)
 {
     FT0 = env->fpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_FT0_fpr_fpr, REG)(void)
+void OPPROTO glue(op_store_FT0_fpr_fpr, REG) (void)
 {
     env->fpr[REG] = FT0;
     RETURN();
 }
 
-void OPPROTO glue(op_load_fpr_FT1_fpr, REG)(void)
+void OPPROTO glue(op_load_fpr_FT1_fpr, REG) (void)
 {
     FT1 = env->fpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_FT1_fpr_fpr, REG)(void)
+void OPPROTO glue(op_store_FT1_fpr_fpr, REG) (void)
 {
     env->fpr[REG] = FT1;
     RETURN();
 }
 
-void OPPROTO glue(op_load_fpr_FT2_fpr, REG)(void)
+void OPPROTO glue(op_load_fpr_FT2_fpr, REG) (void)
 {
     FT2 = env->fpr[REG];
     RETURN();
 }
 
-void OPPROTO glue(op_store_FT2_fpr_fpr, REG)(void)
+#if 0 // unused
+void OPPROTO glue(op_store_FT2_fpr_fpr, REG) (void)
 {
     env->fpr[REG] = FT2;
     RETURN();
 }
-
-#if REG <= 15
-/* Segment register moves */
-void OPPROTO glue(op_load_sr, REG)(void)
-{
-    T0 = env->sr[REG];
-    RETURN();
-}
-
-void OPPROTO glue(op_store_sr, REG)(void)
-{
-    do_store_sr(env, REG, T0);
-    RETURN();
-}
 #endif
 
 #undef REG

Modified: trunk/src/host/qemu-neo1973/target-ppc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC emulation for qemu: main translation routines.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -29,8 +29,10 @@
 
 //#define DO_SINGLE_STEP
 //#define PPC_DEBUG_DISAS
+//#define DEBUG_MEMORY_ACCESSES
+//#define DO_PPC_STATISTICS
 
-#ifdef USE_DIRECT_JUMP
+#if defined(USE_DIRECT_JUMP)
 #define TBPARAM(x)
 #else
 #define TBPARAM(x) (long)(x)
@@ -48,7 +50,27 @@
 
 #include "gen-op.h"
 
-#define GEN8(func, NAME) \
+static inline void gen_set_T0 (target_ulong val)
+{
+#if defined(TARGET_PPC64)
+    if (val >> 32)
+        gen_op_set_T0_64(val >> 32, val);
+    else
+#endif
+        gen_op_set_T0(val);
+}
+
+static inline void gen_set_T1 (target_ulong val)
+{
+#if defined(TARGET_PPC64)
+    if (val >> 32)
+        gen_op_set_T1_64(val >> 32, val);
+    else
+#endif
+        gen_op_set_T1(val);
+}
+
+#define GEN8(func, NAME)                                                      \
 static GenOpFunc *NAME ## _table [8] = {                                      \
 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
@@ -70,7 +92,7 @@
     NAME ## _table[n]();                                                      \
 }
 
-#define GEN32(func, NAME) \
+#define GEN32(func, NAME)                                                     \
 static GenOpFunc *NAME ## _table [32] = {                                     \
 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
@@ -96,25 +118,12 @@
 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
 GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr);
 GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr);
-static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = {
-    &gen_op_store_T0_fpscri_fpscr0,
-    &gen_op_store_T0_fpscri_fpscr1,
-    &gen_op_store_T0_fpscri_fpscr2,
-    &gen_op_store_T0_fpscri_fpscr3,
-    &gen_op_store_T0_fpscri_fpscr4,
-    &gen_op_store_T0_fpscri_fpscr5,
-    &gen_op_store_T0_fpscri_fpscr6,
-    &gen_op_store_T0_fpscri_fpscr7,
-};
 static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
 {
-    (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
+    gen_op_set_T0(param);
+    gen_op_store_T0_fpscr(n);
 }
 
-/* Segment register moves */
-GEN16(gen_op_load_sr, gen_op_load_sr);
-GEN16(gen_op_store_sr, gen_op_store_sr);
-
 /* General purpose registers moves */
 GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
 GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
@@ -122,7 +131,9 @@
 
 GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
 GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
+#if 0 // unused
 GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
+#endif
 
 /* floating point registers moves */
 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
@@ -130,10 +141,10 @@
 GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
+#if 0 // unused
 GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
+#endif
 
-static uint8_t  spr_access[1024 / 2];
-
 /* internal defines */
 typedef struct DisasContext {
     struct TranslationBlock *tb;
@@ -146,7 +157,13 @@
 #if !defined(CONFIG_USER_ONLY)
     int supervisor;
 #endif
+#if defined(TARGET_PPC64)
+    int sf_mode;
+#endif
     int fpu_enabled;
+#if defined(TARGET_PPCEMB)
+    int spe_enabled;
+#endif
     ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
     int singlestep_enabled;
 } DisasContext;
@@ -155,15 +172,40 @@
     /* invalid bits */
     uint32_t inval;
     /* instruction type */
-    uint32_t type;
+    uint64_t type;
     /* handler */
     void (*handler)(DisasContext *ctx);
+#if defined(DO_PPC_STATISTICS)
+    const unsigned char *oname;
+    uint64_t count;
+#endif
 };
 
+static inline void gen_set_Rc0 (DisasContext *ctx)
+{
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_cmpi_64(0);
+    else
+#endif
+        gen_op_cmpi(0);
+    gen_op_set_Rc0();
+}
+
+static inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
+{
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_update_nip_64(nip >> 32, nip);
+    else
+#endif
+        gen_op_update_nip(nip);
+}
+
 #define RET_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
     if ((ctx)->exception == EXCP_NONE) {                                      \
-        gen_op_update_nip((ctx)->nip);                                        \
+        gen_update_nip(ctx, (ctx)->nip);                                      \
     }                                                                         \
     gen_op_raise_exception_err((excp), (error));                              \
     ctx->exception = (excp);                                                  \
@@ -181,7 +223,7 @@
 /* Stop translation */
 static inline void RET_STOP (DisasContext *ctx)
 {
-    gen_op_update_nip((ctx)->nip);
+    gen_update_nip(ctx, ctx->nip);
     ctx->exception = EXCP_MTMSR;
 }
 
@@ -278,7 +320,7 @@
 /* Displacement */
 EXTRACT_SHELPER(d, 0, 16);
 /* Immediate address */
-static inline uint32_t LI (uint32_t opcode)
+static inline target_ulong LI (uint32_t opcode)
 {
     return (opcode >> 0) & 0x03FFFFFC;
 }
@@ -296,13 +338,29 @@
 EXTRACT_HELPER(LK, 0, 1);
 
 /* Create a mask between <start> and <end> bits */
-static inline uint32_t MASK (uint32_t start, uint32_t end)
+static inline target_ulong MASK (uint32_t start, uint32_t end)
 {
-    uint32_t ret;
+    target_ulong ret;
 
-    ret = (((uint32_t)(-1)) >> (start)) ^ (((uint32_t)(-1) >> (end)) >> 1);
-    if (start > end)
-        return ~ret;
+#if defined(TARGET_PPC64)
+    if (likely(start == 0)) {
+        ret = (uint64_t)(-1ULL) << (63 - end);
+    } else if (likely(end == 63)) {
+        ret = (uint64_t)(-1ULL) >> start;
+    }
+#else
+    if (likely(start == 0)) {
+        ret = (uint32_t)(-1ULL) << (31  - end);
+    } else if (likely(end == 31)) {
+        ret = (uint32_t)(-1ULL) >> start;
+    }
+#endif
+    else {
+        ret = (((target_ulong)(-1ULL)) >> (start)) ^
+            (((target_ulong)(-1ULL) >> (end)) >> 1);
+        if (unlikely(start > end))
+            return ~ret;
+    }
 
     return ret;
 }
@@ -313,13 +371,14 @@
 #define OPC_ALIGN 4
 #endif
 #if defined(__APPLE__)
-#define OPCODES_SECTION \
+#define OPCODES_SECTION                                                       \
     __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
 #else
-#define OPCODES_SECTION \
+#define OPCODES_SECTION                                                       \
     __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
 #endif
 
+#if defined(DO_PPC_STATISTICS)
 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
 OPCODES_SECTION opcode_t opc_##name = {                                       \
     .opc1 = op1,                                                              \
@@ -330,9 +389,25 @@
         .inval   = invl,                                                      \
         .type = _typ,                                                         \
         .handler = &gen_##name,                                               \
+        .oname = stringify(name),                                             \
     },                                                                        \
     .oname = stringify(name),                                                 \
 }
+#else
+#define GEN_OPCODE(name, op1, op2, op3, invl, _typ)                           \
+OPCODES_SECTION opcode_t opc_##name = {                                       \
+    .opc1 = op1,                                                              \
+    .opc2 = op2,                                                              \
+    .opc3 = op3,                                                              \
+    .pad  = { 0, },                                                           \
+    .handler = {                                                              \
+        .inval   = invl,                                                      \
+        .type = _typ,                                                         \
+        .handler = &gen_##name,                                               \
+    },                                                                        \
+    .oname = stringify(name),                                                 \
+}
+#endif
 
 #define GEN_OPCODE_MARK(name)                                                 \
 OPCODES_SECTION opcode_t opc_##name = {                                       \
@@ -364,131 +439,385 @@
 };
 
 /***                           Integer arithmetic                          ***/
-#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval)                       \
-GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER)                       \
+#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type)                 \
+GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
 
-#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval)                     \
-GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER)                       \
+#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type)               \
+GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
 
-#define __GEN_INT_ARITH1(name, opc1, opc2, opc3)                              \
-GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
+#define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                        \
+GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
-#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3)                            \
-GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER)                  \
+#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type)                      \
+GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
 
 /* Two operands arithmetic functions */
-#define GEN_INT_ARITH2(name, opc1, opc2, opc3)                                \
-__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000)                          \
-__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000)
+#define GEN_INT_ARITH2(name, opc1, opc2, opc3, type)                          \
+__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type)                    \
+__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
 
 /* Two operands arithmetic functions with no overflow allowed */
-#define GEN_INT_ARITHN(name, opc1, opc2, opc3)                                \
-__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400)
+#define GEN_INT_ARITHN(name, opc1, opc2, opc3, type)                          \
+__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
 
 /* One operand arithmetic functions */
-#define GEN_INT_ARITH1(name, opc1, opc2, opc3)                                \
-__GEN_INT_ARITH1(name, opc1, opc2, opc3)                                      \
-__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10)
+#define GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                          \
+__GEN_INT_ARITH1(name, opc1, opc2, opc3, type)                                \
+__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
 
+#if defined(TARGET_PPC64)
+#define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type)              \
+GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
+{                                                                             \
+    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
+    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
+    if (ctx->sf_mode)                                                         \
+        gen_op_##name##_64();                                                 \
+    else                                                                      \
+        gen_op_##name();                                                      \
+    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
+}
+
+#define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type)            \
+GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                              \
+{                                                                             \
+    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
+    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
+    if (ctx->sf_mode)                                                         \
+        gen_op_##name##_64();                                                 \
+    else                                                                      \
+        gen_op_##name();                                                      \
+    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
+}
+
+#define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                     \
+GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
+{                                                                             \
+    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
+    if (ctx->sf_mode)                                                         \
+        gen_op_##name##_64();                                                 \
+    else                                                                      \
+        gen_op_##name();                                                      \
+    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
+}
+#define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type)                   \
+GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type)                         \
+{                                                                             \
+    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
+    if (ctx->sf_mode)                                                         \
+        gen_op_##name##_64();                                                 \
+    else                                                                      \
+        gen_op_##name();                                                      \
+    gen_op_store_T0_gpr(rD(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
+}
+
+/* Two operands arithmetic functions */
+#define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type)                       \
+__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type)                 \
+__GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
+
+/* Two operands arithmetic functions with no overflow allowed */
+#define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type)                       \
+__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
+
+/* One operand arithmetic functions */
+#define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                       \
+__GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type)                             \
+__GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
+#else
+#define GEN_INT_ARITH2_64 GEN_INT_ARITH2
+#define GEN_INT_ARITHN_64 GEN_INT_ARITHN
+#define GEN_INT_ARITH1_64 GEN_INT_ARITH1
+#endif
+
 /* add    add.    addo    addo.    */
-GEN_INT_ARITH2 (add,    0x1F, 0x0A, 0x08);
+static inline void gen_op_addo (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addo();
+}
+#if defined(TARGET_PPC64)
+#define gen_op_add_64 gen_op_add
+static inline void gen_op_addo_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (add,    0x1F, 0x0A, 0x08, PPC_INTEGER);
 /* addc   addc.   addco   addco.   */
-GEN_INT_ARITH2 (addc,   0x1F, 0x0A, 0x00);
+static inline void gen_op_addc (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addc();
+}
+static inline void gen_op_addco (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addc();
+    gen_op_check_addo();
+}
+#if defined(TARGET_PPC64)
+static inline void gen_op_addc_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addc_64();
+}
+static inline void gen_op_addco_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add();
+    gen_op_check_addc_64();
+    gen_op_check_addo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (addc,   0x1F, 0x0A, 0x00, PPC_INTEGER);
 /* adde   adde.   addeo   addeo.   */
-GEN_INT_ARITH2 (adde,   0x1F, 0x0A, 0x04);
+static inline void gen_op_addeo (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_adde();
+    gen_op_check_addo();
+}
+#if defined(TARGET_PPC64)
+static inline void gen_op_addeo_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_adde_64();
+    gen_op_check_addo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (adde,   0x1F, 0x0A, 0x04, PPC_INTEGER);
 /* addme  addme.  addmeo  addmeo.  */
-GEN_INT_ARITH1 (addme,  0x1F, 0x0A, 0x07);
+static inline void gen_op_addme (void)
+{
+    gen_op_move_T1_T0();
+    gen_op_add_me();
+}
+#if defined(TARGET_PPC64)
+static inline void gen_op_addme_64 (void)
+{
+    gen_op_move_T1_T0();
+    gen_op_add_me_64();
+}
+#endif
+GEN_INT_ARITH1_64 (addme,  0x1F, 0x0A, 0x07, PPC_INTEGER);
 /* addze  addze.  addzeo  addzeo.  */
-GEN_INT_ARITH1 (addze,  0x1F, 0x0A, 0x06);
+static inline void gen_op_addze (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add_ze();
+    gen_op_check_addc();
+}
+static inline void gen_op_addzeo (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add_ze();
+    gen_op_check_addc();
+    gen_op_check_addo();
+}
+#if defined(TARGET_PPC64)
+static inline void gen_op_addze_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add_ze();
+    gen_op_check_addc_64();
+}
+static inline void gen_op_addzeo_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_add_ze();
+    gen_op_check_addc_64();
+    gen_op_check_addo_64();
+}
+#endif
+GEN_INT_ARITH1_64 (addze,  0x1F, 0x0A, 0x06, PPC_INTEGER);
 /* divw   divw.   divwo   divwo.   */
-GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F);
+GEN_INT_ARITH2 (divw,   0x1F, 0x0B, 0x0F, PPC_INTEGER);
 /* divwu  divwu.  divwuo  divwuo.  */
-GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E);
+GEN_INT_ARITH2 (divwu,  0x1F, 0x0B, 0x0E, PPC_INTEGER);
 /* mulhw  mulhw.                   */
-GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02);
+GEN_INT_ARITHN (mulhw,  0x1F, 0x0B, 0x02, PPC_INTEGER);
 /* mulhwu mulhwu.                  */
-GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00);
+GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
 /* mullw  mullw.  mullwo  mullwo.  */
-GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07);
+GEN_INT_ARITH2 (mullw,  0x1F, 0x0B, 0x07, PPC_INTEGER);
 /* neg    neg.    nego    nego.    */
-GEN_INT_ARITH1 (neg,    0x1F, 0x08, 0x03);
+GEN_INT_ARITH1_64 (neg,    0x1F, 0x08, 0x03, PPC_INTEGER);
 /* subf   subf.   subfo   subfo.   */
-GEN_INT_ARITH2 (subf,   0x1F, 0x08, 0x01);
+static inline void gen_op_subfo (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subf();
+    gen_op_check_subfo();
+}
+#if defined(TARGET_PPC64)
+#define gen_op_subf_64 gen_op_subf
+static inline void gen_op_subfo_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subf();
+    gen_op_check_subfo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (subf,   0x1F, 0x08, 0x01, PPC_INTEGER);
 /* subfc  subfc.  subfco  subfco.  */
-GEN_INT_ARITH2 (subfc,  0x1F, 0x08, 0x00);
+static inline void gen_op_subfc (void)
+{
+    gen_op_subf();
+    gen_op_check_subfc();
+}
+static inline void gen_op_subfco (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subf();
+    gen_op_check_subfc();
+    gen_op_check_subfo();
+}
+#if defined(TARGET_PPC64)
+static inline void gen_op_subfc_64 (void)
+{
+    gen_op_subf();
+    gen_op_check_subfc_64();
+}
+static inline void gen_op_subfco_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subf();
+    gen_op_check_subfc_64();
+    gen_op_check_subfo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (subfc,  0x1F, 0x08, 0x00, PPC_INTEGER);
 /* subfe  subfe.  subfeo  subfeo.  */
-GEN_INT_ARITH2 (subfe,  0x1F, 0x08, 0x04);
+static inline void gen_op_subfeo (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subfe();
+    gen_op_check_subfo();
+}
+#if defined(TARGET_PPC64)
+#define gen_op_subfe_64 gen_op_subfe
+static inline void gen_op_subfeo_64 (void)
+{
+    gen_op_move_T2_T0();
+    gen_op_subfe_64();
+    gen_op_check_subfo_64();
+}
+#endif
+GEN_INT_ARITH2_64 (subfe,  0x1F, 0x08, 0x04, PPC_INTEGER);
 /* subfme subfme. subfmeo subfmeo. */
-GEN_INT_ARITH1 (subfme, 0x1F, 0x08, 0x07);
+GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
 /* subfze subfze. subfzeo subfzeo. */
-GEN_INT_ARITH1 (subfze, 0x1F, 0x08, 0x06);
+GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
 /* addi */
 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    int32_t simm = SIMM(ctx->opcode);
+    target_long simm = SIMM(ctx->opcode);
 
     if (rA(ctx->opcode) == 0) {
-        gen_op_set_T0(simm);
+        /* li case */
+        gen_set_T0(simm);
     } else {
         gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_addi(simm);
+        if (likely(simm != 0))
+            gen_op_addi(simm);
     }
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 /* addic */
 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
+    target_long simm = SIMM(ctx->opcode);
+
     gen_op_load_gpr_T0(rA(ctx->opcode));
-    gen_op_addic(SIMM(ctx->opcode));
+    if (likely(simm != 0)) {
+        gen_op_move_T2_T0();
+        gen_op_addi(simm);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_check_addc_64();
+        else
+#endif
+            gen_op_check_addc();
+    } else {
+        gen_op_clear_xer_ca();
+    }
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 /* addic. */
 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
+    target_long simm = SIMM(ctx->opcode);
+
     gen_op_load_gpr_T0(rA(ctx->opcode));
-    gen_op_addic(SIMM(ctx->opcode));
-    gen_op_set_Rc0();
+    if (likely(simm != 0)) {
+        gen_op_move_T2_T0();
+        gen_op_addi(simm);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_check_addc_64();
+        else
+#endif
+            gen_op_check_addc();
+    }
     gen_op_store_T0_gpr(rD(ctx->opcode));
+    gen_set_Rc0(ctx);
 }
 /* addis */
 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    int32_t simm = SIMM(ctx->opcode);
+    target_long simm = SIMM(ctx->opcode);
 
     if (rA(ctx->opcode) == 0) {
-        gen_op_set_T0(simm << 16);
+        /* lis case */
+        gen_set_T0(simm << 16);
     } else {
         gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_addi(simm << 16);
+        if (likely(simm != 0))
+            gen_op_addi(simm << 16);
     }
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
@@ -503,113 +832,184 @@
 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
-    gen_op_subfic(SIMM(ctx->opcode));
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_subfic_64(SIMM(ctx->opcode));
+    else
+#endif
+        gen_op_subfic(SIMM(ctx->opcode));
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 
+#if defined(TARGET_PPC64)
+/* mulhd  mulhd.                   */
+GEN_INT_ARITHN (mulhd,  0x1F, 0x09, 0x02, PPC_INTEGER);
+/* mulhdu mulhdu.                  */
+GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_INTEGER);
+/* mulld  mulld.  mulldo  mulldo.  */
+GEN_INT_ARITH2 (mulld,  0x1F, 0x09, 0x07, PPC_INTEGER);
+/* divd   divd.   divdo   divdo.   */
+GEN_INT_ARITH2 (divd,   0x1F, 0x09, 0x0F, PPC_INTEGER);
+/* divdu  divdu.  divduo  divduo.  */
+GEN_INT_ARITH2 (divdu,  0x1F, 0x09, 0x0E, PPC_INTEGER);
+#endif
+
 /***                           Integer comparison                          ***/
-#define GEN_CMP(name, opc)                                                    \
-GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER)                   \
+#if defined(TARGET_PPC64)
+#define GEN_CMP(name, opc, type)                                              \
+GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
 {                                                                             \
     gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
+    if (ctx->sf_mode)                                                         \
+        gen_op_##name##_64();                                                 \
+    else                                                                      \
+        gen_op_##name();                                                      \
+    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
+}
+#else
+#define GEN_CMP(name, opc, type)                                              \
+GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type)                          \
+{                                                                             \
+    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
+    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
     gen_op_##name();                                                          \
     gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
 }
+#endif
 
 /* cmp */
-GEN_CMP(cmp, 0x00);
+GEN_CMP(cmp, 0x00, PPC_INTEGER);
 /* cmpi */
 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
-    gen_op_cmpi(SIMM(ctx->opcode));
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_cmpi_64(SIMM(ctx->opcode));
+    else
+#endif
+        gen_op_cmpi(SIMM(ctx->opcode));
     gen_op_store_T0_crf(crfD(ctx->opcode));
 }
 /* cmpl */
-GEN_CMP(cmpl, 0x01);
+GEN_CMP(cmpl, 0x01, PPC_INTEGER);
 /* cmpli */
 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
-    gen_op_cmpli(UIMM(ctx->opcode));
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_cmpli_64(UIMM(ctx->opcode));
+    else
+#endif
+        gen_op_cmpli(UIMM(ctx->opcode));
     gen_op_store_T0_crf(crfD(ctx->opcode));
 }
 
+/* isel (PowerPC 2.03 specification) */
+GEN_HANDLER(isel, 0x1F, 0x0F, 0x00, 0x00000001, PPC_203)
+{
+    uint32_t bi = rC(ctx->opcode);
+    uint32_t mask;
+
+    if (rA(ctx->opcode) == 0) {
+        gen_set_T0(0);
+    } else {
+        gen_op_load_gpr_T1(rA(ctx->opcode));
+    }
+    gen_op_load_gpr_T2(rB(ctx->opcode));
+    mask = 1 << (3 - (bi & 0x03));
+    gen_op_load_crf_T0(bi >> 2);
+    gen_op_test_true(mask);
+    gen_op_isel();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+}
+
 /***                            Integer logical                            ***/
-#define __GEN_LOGICAL2(name, opc2, opc3)                                      \
-GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER)                  \
+#define __GEN_LOGICAL2(name, opc2, opc3, type)                                \
+GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type)                         \
 {                                                                             \
     gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
     gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
-#define GEN_LOGICAL2(name, opc)                                               \
-__GEN_LOGICAL2(name, 0x1C, opc)
+#define GEN_LOGICAL2(name, opc, type)                                         \
+__GEN_LOGICAL2(name, 0x1C, opc, type)
 
-#define GEN_LOGICAL1(name, opc)                                               \
-GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER)                   \
+#define GEN_LOGICAL1(name, opc, type)                                         \
+GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type)                          \
 {                                                                             \
     gen_op_load_gpr_T0(rS(ctx->opcode));                                      \
     gen_op_##name();                                                          \
-    if (Rc(ctx->opcode) != 0)                                                 \
-        gen_op_set_Rc0();                                                     \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
+        gen_set_Rc0(ctx);                                                     \
 }
 
 /* and & and. */
-GEN_LOGICAL2(and, 0x00);
+GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
 /* andc & andc. */
-GEN_LOGICAL2(andc, 0x01);
+GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
 /* andi. */
 GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    gen_op_andi_(UIMM(ctx->opcode));
-    gen_op_set_Rc0();
+    gen_op_andi_T0(UIMM(ctx->opcode));
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    gen_set_Rc0(ctx);
 }
 /* andis. */
 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    gen_op_andi_(UIMM(ctx->opcode) << 16);
-    gen_op_set_Rc0();
+    gen_op_andi_T0(UIMM(ctx->opcode) << 16);
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    gen_set_Rc0(ctx);
 }
 
 /* cntlzw */
-GEN_LOGICAL1(cntlzw, 0x00);
+GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
 /* eqv & eqv. */
-GEN_LOGICAL2(eqv, 0x08);
+GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
 /* extsb & extsb. */
-GEN_LOGICAL1(extsb, 0x1D);
+GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
 /* extsh & extsh. */
-GEN_LOGICAL1(extsh, 0x1C);
+GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
 /* nand & nand. */
-GEN_LOGICAL2(nand, 0x0E);
+GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
 /* nor & nor. */
-GEN_LOGICAL2(nor, 0x03);
+GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
 
 /* or & or. */
 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
 {
-    gen_op_load_gpr_T0(rS(ctx->opcode));
-    /* Optimisation for mr case */
-    if (rS(ctx->opcode) != rB(ctx->opcode)) {
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_or();
+    int rs, ra, rb;
+
+    rs = rS(ctx->opcode);
+    ra = rA(ctx->opcode);
+    rb = rB(ctx->opcode);
+    /* Optimisation for mr. ri case */
+    if (rs != ra || rs != rb) {
+        gen_op_load_gpr_T0(rs);
+        if (rs != rb) {
+            gen_op_load_gpr_T1(rb);
+            gen_op_or();
+        }
+        gen_op_store_T0_gpr(ra);
+        if (unlikely(Rc(ctx->opcode) != 0))
+            gen_set_Rc0(ctx);
+    } else if (unlikely(Rc(ctx->opcode) != 0)) {
+        gen_op_load_gpr_T0(rs);
+        gen_set_Rc0(ctx);
     }
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
-    gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 
 /* orc & orc. */
-GEN_LOGICAL2(orc, 0x0C);
+GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
 /* xor & xor. */
 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
 {
@@ -619,84 +1019,129 @@
         gen_op_load_gpr_T1(rB(ctx->opcode));
         gen_op_xor();
     } else {
-        gen_op_set_T0(0);
+        gen_op_reset_T0();
     }
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
 }
 /* ori */
 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    uint32_t uimm = UIMM(ctx->opcode);
+    target_ulong uimm = UIMM(ctx->opcode);
 
     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
         /* NOP */
+        /* XXX: should handle special NOPs for POWER series */
         return;
-        }
-        gen_op_load_gpr_T0(rS(ctx->opcode));
-    if (uimm != 0)
+    }
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    if (likely(uimm != 0))
         gen_op_ori(uimm);
-        gen_op_store_T0_gpr(rA(ctx->opcode));
+    gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 /* oris */
 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    uint32_t uimm = UIMM(ctx->opcode);
+    target_ulong uimm = UIMM(ctx->opcode);
 
     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
         /* NOP */
         return;
-        }
-        gen_op_load_gpr_T0(rS(ctx->opcode));
-    if (uimm != 0)
+    }
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    if (likely(uimm != 0))
         gen_op_ori(uimm << 16);
-        gen_op_store_T0_gpr(rA(ctx->opcode));
+    gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 /* xori */
 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    uint32_t uimm = UIMM(ctx->opcode);
+    target_ulong uimm = UIMM(ctx->opcode);
 
     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
         /* NOP */
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    if (uimm != 0)
-    gen_op_xori(uimm);
+    if (likely(uimm != 0))
+        gen_op_xori(uimm);
     gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 
 /* xoris */
 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    uint32_t uimm = UIMM(ctx->opcode);
+    target_ulong uimm = UIMM(ctx->opcode);
 
     if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
         /* NOP */
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    if (uimm != 0)
-    gen_op_xori(uimm << 16);
+    if (likely(uimm != 0))
+        gen_op_xori(uimm << 16);
     gen_op_store_T0_gpr(rA(ctx->opcode));
 }
 
+/* popcntb : PowerPC 2.03 specification */
+GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_203)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_popcntb_64();
+    else
+#endif
+        gen_op_popcntb();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+}
+
+#if defined(TARGET_PPC64)
+/* extsw & extsw. */
+GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
+/* cntlzd */
+GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
+#endif
+
 /***                             Integer rotate                            ***/
 /* rlwimi & rlwimi. */
 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    uint32_t mb, me;
+    target_ulong mask;
+    uint32_t mb, me, sh;
 
     mb = MB(ctx->opcode);
     me = ME(ctx->opcode);
+    sh = SH(ctx->opcode);
+    if (likely(sh == 0)) {
+        if (likely(mb == 0 && me == 31)) {
+            gen_op_load_gpr_T0(rS(ctx->opcode));
+            goto do_store;
+        } else if (likely(mb == 31 && me == 0)) {
+            gen_op_load_gpr_T0(rA(ctx->opcode));
+            goto do_store;
+        }
+        gen_op_load_gpr_T0(rS(ctx->opcode));
+        gen_op_load_gpr_T1(rA(ctx->opcode));
+        goto do_mask;
+    }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rA(ctx->opcode));
-    gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me));
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
+    gen_op_rotli32_T0(SH(ctx->opcode));
+ do_mask:
+#if defined(TARGET_PPC64)
+    mb += 32;
+    me += 32;
+#endif
+    mask = MASK(mb, me);
+    gen_op_andi_T0(mask);
+    gen_op_andi_T1(~mask);
+    gen_op_or();
+ do_store:
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
 }
 /* rlwinm & rlwinm. */
 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -707,35 +1152,34 @@
     mb = MB(ctx->opcode);
     me = ME(ctx->opcode);
     gen_op_load_gpr_T0(rS(ctx->opcode));
-#if 1 // TRY
-    if (sh == 0) {
-        gen_op_andi_(MASK(mb, me));
-        goto store;
+    if (likely(sh == 0)) {
+        goto do_mask;
     }
-#endif
-    if (mb == 0) {
-        if (me == 31) {
-            gen_op_rotlwi(sh);
-            goto store;
-#if 0
-        } else if (me == (31 - sh)) {
-            gen_op_slwi(sh);
-            goto store;
-#endif
+    if (likely(mb == 0)) {
+        if (likely(me == 31)) {
+            gen_op_rotli32_T0(sh);
+            goto do_store;
+        } else if (likely(me == (31 - sh))) {
+            gen_op_sli_T0(sh);
+            goto do_store;
         }
-    } else if (me == 31) {
-#if 0
-        if (sh == (32 - mb)) {
-            gen_op_srwi(mb);
-            goto store;
+    } else if (likely(me == 31)) {
+        if (likely(sh == (32 - mb))) {
+            gen_op_srli_T0(mb);
+            goto do_store;
         }
+    }
+    gen_op_rotli32_T0(sh);
+ do_mask:
+#if defined(TARGET_PPC64)
+    mb += 32;
+    me += 32;
 #endif
-    }
-    gen_op_rlwinm(sh, MASK(mb, me));
-store:
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
+    gen_op_andi_T0(MASK(mb, me));
+ do_store:
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
 }
 /* rlwnm & rlwnm. */
 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -746,40 +1190,242 @@
     me = ME(ctx->opcode);
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
-    if (mb == 0 && me == 31) {
-        gen_op_rotl();
-    } else
-    {
-        gen_op_rlwnm(MASK(mb, me));
+    gen_op_rotl32_T0_T1();
+    if (unlikely(mb != 0 || me != 31)) {
+#if defined(TARGET_PPC64)
+        mb += 32;
+        me += 32;
+#endif
+        gen_op_andi_T0(MASK(mb, me));
     }
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
 }
 
+#if defined(TARGET_PPC64)
+#define GEN_PPC64_R2(name, opc1, opc2)                                        \
+GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B)                   \
+{                                                                             \
+    gen_##name(ctx, 0);                                                       \
+}                                                                             \
+GEN_HANDLER(name##1, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B)            \
+{                                                                             \
+    gen_##name(ctx, 1);                                                       \
+}
+#define GEN_PPC64_R4(name, opc1, opc2)                                        \
+GEN_HANDLER(name##0, opc1, opc2, 0xFF, 0x00000000, PPC_64B)                   \
+{                                                                             \
+    gen_##name(ctx, 0, 0);                                                    \
+}                                                                             \
+GEN_HANDLER(name##1, opc1, opc2 | 0x01, 0xFF, 0x00000000, PPC_64B)            \
+{                                                                             \
+    gen_##name(ctx, 0, 1);                                                    \
+}                                                                             \
+GEN_HANDLER(name##2, opc1, opc2 | 0x10, 0xFF, 0x00000000, PPC_64B)            \
+{                                                                             \
+    gen_##name(ctx, 1, 0);                                                    \
+}                                                                             \
+GEN_HANDLER(name##3, opc1, opc2 | 0x11, 0xFF, 0x00000000, PPC_64B)            \
+{                                                                             \
+    gen_##name(ctx, 1, 1);                                                    \
+}
+
+static inline void gen_rldinm (DisasContext *ctx, uint32_t mb, uint32_t me,
+                               uint32_t sh)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    if (likely(sh == 0)) {
+        goto do_mask;
+    }
+    if (likely(mb == 0)) {
+        if (likely(me == 63)) {
+            gen_op_rotli32_T0(sh);
+            goto do_store;
+        } else if (likely(me == (63 - sh))) {
+            gen_op_sli_T0(sh);
+            goto do_store;
+        }
+    } else if (likely(me == 63)) {
+        if (likely(sh == (64 - mb))) {
+            gen_op_srli_T0(mb);
+            goto do_store;
+        }
+    }
+    gen_op_rotli64_T0(sh);
+ do_mask:
+    gen_op_andi_T0(MASK(mb, me));
+ do_store:
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+/* rldicl - rldicl. */
+static inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
+{
+    uint32_t sh, mb;
+
+    sh = SH(ctx->opcode) | (shn << 5);
+    mb = MB(ctx->opcode) | (mbn << 5);
+    gen_rldinm(ctx, mb, 63, sh);
+}
+GEN_PPC64_R4(rldicl, 0x1E, 0x00);
+/* rldicr - rldicr. */
+static inline void gen_rldicr (DisasContext *ctx, int men, int shn)
+{
+    uint32_t sh, me;
+
+    sh = SH(ctx->opcode) | (shn << 5);
+    me = MB(ctx->opcode) | (men << 5);
+    gen_rldinm(ctx, 0, me, sh);
+}
+GEN_PPC64_R4(rldicr, 0x1E, 0x02);
+/* rldic - rldic. */
+static inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
+{
+    uint32_t sh, mb;
+
+    sh = SH(ctx->opcode) | (shn << 5);
+    mb = MB(ctx->opcode) | (mbn << 5);
+    gen_rldinm(ctx, mb, 63 - sh, sh);
+}
+GEN_PPC64_R4(rldic, 0x1E, 0x04);
+
+static inline void gen_rldnm (DisasContext *ctx, uint32_t mb, uint32_t me)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_rotl64_T0_T1();
+    if (unlikely(mb != 0 || me != 63)) {
+        gen_op_andi_T0(MASK(mb, me));
+    }
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* rldcl - rldcl. */
+static inline void gen_rldcl (DisasContext *ctx, int mbn)
+{
+    uint32_t mb;
+
+    mb = MB(ctx->opcode) | (mbn << 5);
+    gen_rldnm(ctx, mb, 63);
+}
+GEN_PPC64_R2(rldcl, 0x1E, 0x08)
+/* rldcr - rldcr. */
+static inline void gen_rldcr (DisasContext *ctx, int men)
+{
+    uint32_t me;
+
+    me = MB(ctx->opcode) | (men << 5);
+    gen_rldnm(ctx, 0, me);
+}
+GEN_PPC64_R2(rldcr, 0x1E, 0x09)
+/* rldimi - rldimi. */
+static inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
+{
+    uint64_t mask;
+    uint32_t sh, mb;
+
+    sh = SH(ctx->opcode) | (shn << 5);
+    mb = MB(ctx->opcode) | (mbn << 5);
+    if (likely(sh == 0)) {
+        if (likely(mb == 0)) {
+            gen_op_load_gpr_T0(rS(ctx->opcode));
+            goto do_store;
+        } else if (likely(mb == 63)) {
+            gen_op_load_gpr_T0(rA(ctx->opcode));
+            goto do_store;
+        }
+        gen_op_load_gpr_T0(rS(ctx->opcode));
+        gen_op_load_gpr_T1(rA(ctx->opcode));
+        goto do_mask;
+    }
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rA(ctx->opcode));
+    gen_op_rotli64_T0(SH(ctx->opcode));
+ do_mask:
+    mask = MASK(mb, 63 - sh);
+    gen_op_andi_T0(mask);
+    gen_op_andi_T1(~mask);
+    gen_op_or();
+ do_store:
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+GEN_PPC64_R4(rldimi, 0x1E, 0x06)
+#endif
+
 /***                             Integer shift                             ***/
 /* slw & slw. */
-__GEN_LOGICAL2(slw, 0x18, 0x00);
+__GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
 /* sraw & sraw. */
-__GEN_LOGICAL2(sraw, 0x18, 0x18);
+__GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
 /* srawi & srawi. */
 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
 {
+    int mb, me;
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    if (SH(ctx->opcode) != 0)
-    gen_op_srawi(SH(ctx->opcode), MASK(32 - SH(ctx->opcode), 31));
-    if (Rc(ctx->opcode) != 0)
-        gen_op_set_Rc0();
+    if (SH(ctx->opcode) != 0) {
+        gen_op_move_T1_T0();
+        mb = 32 - SH(ctx->opcode);
+        me = 31;
+#if defined(TARGET_PPC64)
+        mb += 32;
+        me += 32;
+#endif
+        gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
+    }
     gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
 }
 /* srw & srw. */
-__GEN_LOGICAL2(srw, 0x18, 0x10);
+__GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
 
+#if defined(TARGET_PPC64)
+/* sld & sld. */
+__GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
+/* srad & srad. */
+__GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
+/* sradi & sradi. */
+static inline void gen_sradi (DisasContext *ctx, int n)
+{
+    uint64_t mask;
+    int sh, mb, me;
+
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    sh = SH(ctx->opcode) + (n << 5);
+    if (sh != 0) {
+        gen_op_move_T1_T0();
+        mb = 64 - SH(ctx->opcode);
+        me = 63;
+        mask = MASK(mb, me);
+        gen_op_sradi(sh, mask >> 32, mask);
+    }
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+GEN_HANDLER(sradi0, 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
+{
+    gen_sradi(ctx, 0);
+}
+GEN_HANDLER(sradi1, 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
+{
+    gen_sradi(ctx, 1);
+}
+/* srd & srd. */
+__GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
+#endif
+
 /***                       Floating-Point arithmetic                       ***/
 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat)                           \
 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT)                   \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
@@ -792,7 +1438,7 @@
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (Rc(ctx->opcode))                                                      \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
         gen_op_set_Rc1();                                                     \
 }
 
@@ -803,7 +1449,7 @@
 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat)                     \
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
@@ -815,7 +1461,7 @@
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (Rc(ctx->opcode))                                                      \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
         gen_op_set_Rc1();                                                     \
 }
 #define GEN_FLOAT_AB(name, op2, inval)                                        \
@@ -825,7 +1471,7 @@
 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat)                     \
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
@@ -837,7 +1483,7 @@
         gen_op_frsp();                                                        \
     }                                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (Rc(ctx->opcode))                                                      \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
         gen_op_set_Rc1();                                                     \
 }
 #define GEN_FLOAT_AC(name, op2, inval)                                        \
@@ -847,7 +1493,7 @@
 #define GEN_FLOAT_B(name, op2, op3)                                           \
 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT)                   \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
@@ -855,14 +1501,14 @@
     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
     gen_op_f##name();                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (Rc(ctx->opcode))                                                      \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
         gen_op_set_Rc1();                                                     \
 }
 
 #define GEN_FLOAT_BS(name, op1, op2)                                          \
 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, PPC_FLOAT)                   \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
@@ -870,7 +1516,7 @@
     gen_op_load_fpr_FT0(rB(ctx->opcode));                                     \
     gen_op_f##name();                                                         \
     gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
-    if (Rc(ctx->opcode))                                                      \
+    if (unlikely(Rc(ctx->opcode) != 0))                                       \
         gen_op_set_Rc1();                                                     \
 }
 
@@ -881,13 +1527,13 @@
 /* fmul - fmuls */
 GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
 
-/* fres */
+/* fres */ /* XXX: not in 601 */
 GEN_FLOAT_BS(res, 0x3B, 0x18);
 
-/* frsqrte */
+/* frsqrte */ /* XXX: not in 601 */
 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A);
 
-/* fsel */
+/* fsel */ /* XXX: not in 601 */
 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0);
 /* fsub - fsubs */
 GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
@@ -895,7 +1541,7 @@
 /* fsqrt */
 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -903,13 +1549,13 @@
     gen_op_load_fpr_FT0(rB(ctx->opcode));
     gen_op_fsqrt();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -918,7 +1564,7 @@
     gen_op_fsqrt();
     gen_op_frsp();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
@@ -939,12 +1585,20 @@
 GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
 /* frsp */
 GEN_FLOAT_B(rsp, 0x0C, 0x00);
+#if defined(TARGET_PPC64)
+/* fcfid */
+GEN_FLOAT_B(cfid, 0x0E, 0x1A);
+/* fctid */
+GEN_FLOAT_B(ctid, 0x0E, 0x19);
+/* fctidz */
+GEN_FLOAT_B(ctidz, 0x0F, 0x19);
+#endif
 
 /***                         Floating-Point compare                        ***/
 /* fcmpo */
-GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
+GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -956,9 +1610,9 @@
 }
 
 /* fcmpu */
-GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
+GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -976,14 +1630,14 @@
 /* fmr  - fmr. */
 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
     gen_op_reset_scrfx();
     gen_op_load_fpr_FT0(rB(ctx->opcode));
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
@@ -996,7 +1650,7 @@
 /* mcrfs */
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -1008,13 +1662,13 @@
 /* mffs */
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
     gen_op_load_fpscr();
     gen_op_store_FT0_fpr(rD(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
@@ -1023,15 +1677,15 @@
 {
     uint8_t crb;
     
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
     crb = crbD(ctx->opcode) >> 2;
     gen_op_load_fpscr_T0(crb);
-    gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03)));
+    gen_op_andi_T0(~(1 << (crbD(ctx->opcode) & 0x03)));
     gen_op_store_T0_fpscr(crb);
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
@@ -1040,7 +1694,7 @@
 {
     uint8_t crb;
     
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
@@ -1048,58 +1702,129 @@
     gen_op_load_fpscr_T0(crb);
     gen_op_ori(1 << (crbD(ctx->opcode) & 0x03));
     gen_op_store_T0_fpscr(crb);
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
 /* mtfsf */
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
     gen_op_load_fpr_FT0(rB(ctx->opcode));
     gen_op_store_fpscr(FM(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
 /* mtfsfi */
 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
     gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
-    if (Rc(ctx->opcode))
+    if (unlikely(Rc(ctx->opcode) != 0))
         gen_op_set_Rc1();
 }
 
+/***                           Addressing modes                            ***/
+/* Register indirect with immediate index : EA = (rA|0) + SIMM */
+static inline void gen_addr_imm_index (DisasContext *ctx, int maskl)
+{
+    target_long simm = SIMM(ctx->opcode);
+
+    if (maskl)
+        simm &= ~0x03;
+    if (rA(ctx->opcode) == 0) {
+        gen_set_T0(simm);
+    } else {
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        if (likely(simm != 0))
+            gen_op_addi(simm);
+    }
+#ifdef DEBUG_MEMORY_ACCESSES
+    gen_op_print_mem_EA();
+#endif
+}
+
+static inline void gen_addr_reg_index (DisasContext *ctx)
+{
+    if (rA(ctx->opcode) == 0) {
+        gen_op_load_gpr_T0(rB(ctx->opcode));
+    } else {
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rB(ctx->opcode));
+        gen_op_add();
+    }
+#ifdef DEBUG_MEMORY_ACCESSES
+    gen_op_print_mem_EA();
+#endif
+}
+
+static inline void gen_addr_register (DisasContext *ctx)
+{
+    if (rA(ctx->opcode) == 0) {
+        gen_op_reset_T0();
+    } else {
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+    }
+#ifdef DEBUG_MEMORY_ACCESSES
+    gen_op_print_mem_EA();
+#endif
+}
+
 /***                             Integer load                              ***/
 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
 #if defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64)
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
     &gen_op_l##width##_raw,                                                   \
     &gen_op_l##width##_le_raw,                                                \
+    &gen_op_l##width##_64_raw,                                                \
+    &gen_op_l##width##_le_64_raw,                                             \
 };
 #define OP_ST_TABLE(width)                                                    \
 static GenOpFunc *gen_op_st##width[] = {                                      \
     &gen_op_st##width##_raw,                                                  \
     &gen_op_st##width##_le_raw,                                               \
+    &gen_op_st##width##_64_raw,                                               \
+    &gen_op_st##width##_le_64_raw,                                            \
 };
 /* Byte access routine are endian safe */
+#define gen_op_stb_le_64_raw gen_op_stb_64_raw
+#define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
+#else
+#define OP_LD_TABLE(width)                                                    \
+static GenOpFunc *gen_op_l##width[] = {                                       \
+    &gen_op_l##width##_raw,                                                   \
+    &gen_op_l##width##_le_raw,                                                \
+};
+#define OP_ST_TABLE(width)                                                    \
+static GenOpFunc *gen_op_st##width[] = {                                      \
+    &gen_op_st##width##_raw,                                                  \
+    &gen_op_st##width##_le_raw,                                               \
+};
+#endif
+/* Byte access routine are endian safe */
 #define gen_op_stb_le_raw gen_op_stb_raw
 #define gen_op_lbz_le_raw gen_op_lbz_raw
 #else
+#if defined(TARGET_PPC64)
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
     &gen_op_l##width##_user,                                                  \
     &gen_op_l##width##_le_user,                                               \
     &gen_op_l##width##_kernel,                                                \
     &gen_op_l##width##_le_kernel,                                             \
+    &gen_op_l##width##_64_user,                                               \
+    &gen_op_l##width##_le_64_user,                                            \
+    &gen_op_l##width##_64_kernel,                                             \
+    &gen_op_l##width##_le_64_kernel,                                          \
 };
 #define OP_ST_TABLE(width)                                                    \
 static GenOpFunc *gen_op_st##width[] = {                                      \
@@ -1107,189 +1832,270 @@
     &gen_op_st##width##_le_user,                                              \
     &gen_op_st##width##_kernel,                                               \
     &gen_op_st##width##_le_kernel,                                            \
+    &gen_op_st##width##_64_user,                                              \
+    &gen_op_st##width##_le_64_user,                                           \
+    &gen_op_st##width##_64_kernel,                                            \
+    &gen_op_st##width##_le_64_kernel,                                         \
 };
 /* Byte access routine are endian safe */
+#define gen_op_stb_le_64_user gen_op_stb_64_user
+#define gen_op_lbz_le_64_user gen_op_lbz_64_user
+#define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
+#define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
+#else
+#define OP_LD_TABLE(width)                                                    \
+static GenOpFunc *gen_op_l##width[] = {                                       \
+    &gen_op_l##width##_user,                                                  \
+    &gen_op_l##width##_le_user,                                               \
+    &gen_op_l##width##_kernel,                                                \
+    &gen_op_l##width##_le_kernel,                                             \
+};
+#define OP_ST_TABLE(width)                                                    \
+static GenOpFunc *gen_op_st##width[] = {                                      \
+    &gen_op_st##width##_user,                                                 \
+    &gen_op_st##width##_le_user,                                              \
+    &gen_op_st##width##_kernel,                                               \
+    &gen_op_st##width##_le_kernel,                                            \
+};
+#endif
+/* Byte access routine are endian safe */
 #define gen_op_stb_le_user gen_op_stb_user
 #define gen_op_lbz_le_user gen_op_lbz_user
 #define gen_op_stb_le_kernel gen_op_stb_kernel
 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
 #endif
 
-#define GEN_LD(width, opc)                                                    \
-GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)               \
+#define GEN_LD(width, opc, type)                                              \
+GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type)                      \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_set_T0(simm);                                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        if (simm != 0)                                                        \
-            gen_op_addi(simm);                                                \
-    }                                                                         \
+    gen_addr_imm_index(ctx, 0);                                               \
     op_ldst(l##width);                                                        \
     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
 }
 
-#define GEN_LDU(width, opc)                                                   \
-GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)            \
+#define GEN_LDU(width, opc, type)                                             \
+GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (rA(ctx->opcode) == 0 ||                                               \
-        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
+    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
+                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    if (simm != 0)                                                            \
-        gen_op_addi(simm);                                                    \
+    if (type == PPC_64B)                                                      \
+        gen_addr_imm_index(ctx, 1);                                           \
+    else                                                                      \
+        gen_addr_imm_index(ctx, 0);                                           \
     op_ldst(l##width);                                                        \
     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_LDUX(width, opc)                                                  \
-GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)           \
+#define GEN_LDUX(width, opc2, opc3, type)                                     \
+GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
 {                                                                             \
-    if (rA(ctx->opcode) == 0 ||                                               \
-        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
+    if (unlikely(rA(ctx->opcode) == 0 ||                                      \
+                 rA(ctx->opcode) == rD(ctx->opcode))) {                       \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
-    gen_op_add();                                                             \
+    gen_addr_reg_index(ctx);                                                  \
     op_ldst(l##width);                                                        \
     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_LDX(width, opc2, opc3)                                            \
-GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)           \
+#define GEN_LDX(width, opc2, opc3, type)                                      \
+GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type)                  \
 {                                                                             \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
-        gen_op_add();                                                         \
-    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
     op_ldst(l##width);                                                        \
     gen_op_store_T1_gpr(rD(ctx->opcode));                                     \
 }
 
-#define GEN_LDS(width, op)                                                    \
+#define GEN_LDS(width, op, type)                                              \
 OP_LD_TABLE(width);                                                           \
-GEN_LD(width, op | 0x20);                                                     \
-GEN_LDU(width, op | 0x21);                                                    \
-GEN_LDUX(width, op | 0x01);                                                   \
-GEN_LDX(width, 0x17, op | 0x00)
+GEN_LD(width, op | 0x20, type);                                               \
+GEN_LDU(width, op | 0x21, type);                                              \
+GEN_LDUX(width, 0x17, op | 0x01, type);                                       \
+GEN_LDX(width, 0x17, op | 0x00, type)
 
 /* lbz lbzu lbzux lbzx */
-GEN_LDS(bz, 0x02);
+GEN_LDS(bz, 0x02, PPC_INTEGER);
 /* lha lhau lhaux lhax */
-GEN_LDS(ha, 0x0A);
+GEN_LDS(ha, 0x0A, PPC_INTEGER);
 /* lhz lhzu lhzux lhzx */
-GEN_LDS(hz, 0x08);
+GEN_LDS(hz, 0x08, PPC_INTEGER);
 /* lwz lwzu lwzux lwzx */
-GEN_LDS(wz, 0x00);
+GEN_LDS(wz, 0x00, PPC_INTEGER);
+#if defined(TARGET_PPC64)
+OP_LD_TABLE(wa);
+OP_LD_TABLE(d);
+/* lwaux */
+GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
+/* lwax */
+GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
+/* ldux */
+GEN_LDUX(d, 0x15, 0x01, PPC_64B);
+/* ldx */
+GEN_LDX(d, 0x15, 0x00, PPC_64B);
+GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
+{
+    if (Rc(ctx->opcode)) {
+        if (unlikely(rA(ctx->opcode) == 0 ||
+                     rA(ctx->opcode) == rD(ctx->opcode))) {
+            RET_INVAL(ctx);
+            return;
+        }
+    }
+    gen_addr_imm_index(ctx, 1);
+    if (ctx->opcode & 0x02) {
+        /* lwa (lwau is undefined) */
+        op_ldst(lwa);
+    } else {
+        /* ld - ldu */
+        op_ldst(ld);
+    }
+    gen_op_store_T1_gpr(rD(ctx->opcode));
+    if (Rc(ctx->opcode))
+        gen_op_store_T0_gpr(rA(ctx->opcode));
+}
+#endif
 
 /***                              Integer store                            ***/
-#define GEN_ST(width, opc)                                                    \
-GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)              \
+#define GEN_ST(width, opc, type)                                              \
+GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_set_T0(simm);                                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        if (simm != 0)                                                        \
-            gen_op_addi(simm);                                                \
-    }                                                                         \
+    gen_addr_imm_index(ctx, 0);                                               \
     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STU(width, opc)                                                   \
-GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)           \
+#define GEN_STU(width, opc, type)                                             \
+GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (rA(ctx->opcode) == 0) {                                               \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    if (simm != 0)                                                            \
-        gen_op_addi(simm);                                                    \
+    if (type == PPC_64B)                                                      \
+        gen_addr_imm_index(ctx, 1);                                           \
+    else                                                                      \
+        gen_addr_imm_index(ctx, 0);                                           \
     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
     op_ldst(st##width);                                                       \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STUX(width, opc)                                                  \
-GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER)          \
+#define GEN_STUX(width, opc2, opc3, type)                                     \
+GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
 {                                                                             \
-    if (rA(ctx->opcode) == 0) {                                               \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
-    gen_op_add();                                                             \
+    gen_addr_reg_index(ctx);                                                  \
     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
     op_ldst(st##width);                                                       \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
-#define GEN_STX(width, opc2, opc3)                                            \
-GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER)          \
+#define GEN_STX(width, opc2, opc3, type)                                      \
+GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type)                 \
 {                                                                             \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
-        gen_op_add();                                                         \
-    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
     gen_op_load_gpr_T1(rS(ctx->opcode));                                      \
     op_ldst(st##width);                                                       \
 }
 
-#define GEN_STS(width, op)                                                    \
+#define GEN_STS(width, op, type)                                              \
 OP_ST_TABLE(width);                                                           \
-GEN_ST(width, op | 0x20);                                                     \
-GEN_STU(width, op | 0x21);                                                    \
-GEN_STUX(width, op | 0x01);                                                   \
-GEN_STX(width, 0x17, op | 0x00)
+GEN_ST(width, op | 0x20, type);                                               \
+GEN_STU(width, op | 0x21, type);                                              \
+GEN_STUX(width, 0x17, op | 0x01, type);                                       \
+GEN_STX(width, 0x17, op | 0x00, type)
 
 /* stb stbu stbux stbx */
-GEN_STS(b, 0x06);
+GEN_STS(b, 0x06, PPC_INTEGER);
 /* sth sthu sthux sthx */
-GEN_STS(h, 0x0C);
+GEN_STS(h, 0x0C, PPC_INTEGER);
 /* stw stwu stwux stwx */
-GEN_STS(w, 0x04);
-
+GEN_STS(w, 0x04, PPC_INTEGER);
+#if defined(TARGET_PPC64)
+OP_ST_TABLE(d);
+GEN_STUX(d, 0x15, 0x05, PPC_64B);
+GEN_STX(d, 0x15, 0x04, PPC_64B);
+GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B)
+{
+    if (Rc(ctx->opcode)) {
+        if (unlikely(rA(ctx->opcode) == 0)) {
+            RET_INVAL(ctx);
+            return;
+        }
+    }
+    gen_addr_imm_index(ctx, 1);
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    op_ldst(std);
+    if (Rc(ctx->opcode))
+        gen_op_store_T0_gpr(rA(ctx->opcode));
+}
+#endif
 /***                Integer load and store with byte reverse               ***/
 /* lhbrx */
 OP_LD_TABLE(hbr);
-GEN_LDX(hbr, 0x16, 0x18);
+GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
 /* lwbrx */
 OP_LD_TABLE(wbr);
-GEN_LDX(wbr, 0x16, 0x10);
+GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
 /* sthbrx */
 OP_ST_TABLE(hbr);
-GEN_STX(hbr, 0x16, 0x1C);
+GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
 /* stwbrx */
 OP_ST_TABLE(wbr);
-GEN_STX(wbr, 0x16, 0x14);
+GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
 
 /***                    Integer load and store multiple                    ***/
 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
+#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
 static GenOpFunc1 *gen_op_lmw[] = {
     &gen_op_lmw_raw,
     &gen_op_lmw_le_raw,
+    &gen_op_lmw_64_raw,
+    &gen_op_lmw_le_64_raw,
 };
 static GenOpFunc1 *gen_op_stmw[] = {
+    &gen_op_stmw_64_raw,
+    &gen_op_stmw_le_64_raw,
+};
+#else
+static GenOpFunc1 *gen_op_lmw[] = {
+    &gen_op_lmw_user,
+    &gen_op_lmw_le_user,
+    &gen_op_lmw_kernel,
+    &gen_op_lmw_le_kernel,
+    &gen_op_lmw_64_user,
+    &gen_op_lmw_le_64_user,
+    &gen_op_lmw_64_kernel,
+    &gen_op_lmw_le_64_kernel,
+};
+static GenOpFunc1 *gen_op_stmw[] = {
+    &gen_op_stmw_user,
+    &gen_op_stmw_le_user,
+    &gen_op_stmw_kernel,
+    &gen_op_stmw_le_kernel,
+    &gen_op_stmw_64_user,
+    &gen_op_stmw_le_64_user,
+    &gen_op_stmw_64_kernel,
+    &gen_op_stmw_le_64_kernel,
+};
+#endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc1 *gen_op_lmw[] = {
+    &gen_op_lmw_raw,
+    &gen_op_lmw_le_raw,
+};
+static GenOpFunc1 *gen_op_stmw[] = {
     &gen_op_stmw_raw,
     &gen_op_stmw_le_raw,
 };
@@ -1307,52 +2113,48 @@
     &gen_op_stmw_le_kernel,
 };
 #endif
+#endif
 
 /* lmw */
 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    int simm = SIMM(ctx->opcode);
-
-    if (rA(ctx->opcode) == 0) {
-        gen_op_set_T0(simm);
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        if (simm != 0)
-            gen_op_addi(simm);
-    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
     op_ldstm(lmw, rD(ctx->opcode));
 }
 
 /* stmw */
 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
 {
-    int simm = SIMM(ctx->opcode);
-
-    if (rA(ctx->opcode) == 0) {
-        gen_op_set_T0(simm);
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        if (simm != 0)
-            gen_op_addi(simm);
-    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
     op_ldstm(stmw, rS(ctx->opcode));
 }
 
 /***                    Integer load and store strings                     ***/
 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
+#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
 static GenOpFunc1 *gen_op_lswi[] = {
     &gen_op_lswi_raw,
     &gen_op_lswi_le_raw,
+    &gen_op_lswi_64_raw,
+    &gen_op_lswi_le_64_raw,
 };
 static GenOpFunc3 *gen_op_lswx[] = {
     &gen_op_lswx_raw,
     &gen_op_lswx_le_raw,
+    &gen_op_lswx_64_raw,
+    &gen_op_lswx_le_64_raw,
 };
 static GenOpFunc1 *gen_op_stsw[] = {
     &gen_op_stsw_raw,
     &gen_op_stsw_le_raw,
+    &gen_op_stsw_64_raw,
+    &gen_op_stsw_le_64_raw,
 };
 #else
 static GenOpFunc1 *gen_op_lswi[] = {
@@ -1360,20 +2162,67 @@
     &gen_op_lswi_le_user,
     &gen_op_lswi_kernel,
     &gen_op_lswi_le_kernel,
+    &gen_op_lswi_64_user,
+    &gen_op_lswi_le_64_user,
+    &gen_op_lswi_64_kernel,
+    &gen_op_lswi_le_64_kernel,
 };
 static GenOpFunc3 *gen_op_lswx[] = {
     &gen_op_lswx_user,
     &gen_op_lswx_le_user,
     &gen_op_lswx_kernel,
     &gen_op_lswx_le_kernel,
+    &gen_op_lswx_64_user,
+    &gen_op_lswx_le_64_user,
+    &gen_op_lswx_64_kernel,
+    &gen_op_lswx_le_64_kernel,
 };
 static GenOpFunc1 *gen_op_stsw[] = {
     &gen_op_stsw_user,
     &gen_op_stsw_le_user,
     &gen_op_stsw_kernel,
     &gen_op_stsw_le_kernel,
+    &gen_op_stsw_64_user,
+    &gen_op_stsw_le_64_user,
+    &gen_op_stsw_64_kernel,
+    &gen_op_stsw_le_64_kernel,
 };
 #endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc1 *gen_op_lswi[] = {
+    &gen_op_lswi_raw,
+    &gen_op_lswi_le_raw,
+};
+static GenOpFunc3 *gen_op_lswx[] = {
+    &gen_op_lswx_raw,
+    &gen_op_lswx_le_raw,
+};
+static GenOpFunc1 *gen_op_stsw[] = {
+    &gen_op_stsw_raw,
+    &gen_op_stsw_le_raw,
+};
+#else
+static GenOpFunc1 *gen_op_lswi[] = {
+    &gen_op_lswi_user,
+    &gen_op_lswi_le_user,
+    &gen_op_lswi_kernel,
+    &gen_op_lswi_le_kernel,
+};
+static GenOpFunc3 *gen_op_lswx[] = {
+    &gen_op_lswx_user,
+    &gen_op_lswx_le_user,
+    &gen_op_lswx_kernel,
+    &gen_op_lswx_le_kernel,
+};
+static GenOpFunc1 *gen_op_stsw[] = {
+    &gen_op_stsw_user,
+    &gen_op_stsw_le_user,
+    &gen_op_stsw_kernel,
+    &gen_op_stsw_le_kernel,
+};
+#endif
+#endif
 
 /* lswi */
 /* PowerPC32 specification says we must generate an exception if
@@ -1391,19 +2240,16 @@
     if (nb == 0)
         nb = 32;
     nr = nb / 4;
-    if (((start + nr) > 32  && start <= ra && (start + nr - 32) > ra) ||
-        ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
+    if (unlikely(((start + nr) > 32  &&
+                  start <= ra && (start + nr - 32) > ra) ||
+                 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
         RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
         return;
     }
-    if (ra == 0) {
-        gen_op_set_T0(0);
-    } else {
-        gen_op_load_gpr_T0(ra);
-    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_register(ctx);
     gen_op_set_T1(nb);
-    /* NIP cannot be restored if the memory exception comes from an helper */
-    gen_op_update_nip((ctx)->nip - 4); 
     op_ldsts(lswi, start);
 }
 
@@ -1413,17 +2259,13 @@
     int ra = rA(ctx->opcode);
     int rb = rB(ctx->opcode);
 
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
     if (ra == 0) {
-        gen_op_load_gpr_T0(rb);
         ra = rb;
-    } else {
-        gen_op_load_gpr_T0(ra);
-        gen_op_load_gpr_T1(rb);
-        gen_op_add();
     }
     gen_op_load_xer_bc();
-    /* NIP cannot be restored if the memory exception comes from an helper */
-    gen_op_update_nip((ctx)->nip - 4); 
     op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
 }
 
@@ -1432,59 +2274,51 @@
 {
     int nb = NB(ctx->opcode);
 
-    if (rA(ctx->opcode) == 0) {
-        gen_op_set_T0(0);
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_register(ctx);
     if (nb == 0)
         nb = 32;
     gen_op_set_T1(nb);
-    /* NIP cannot be restored if the memory exception comes from an helper */
-    gen_op_update_nip((ctx)->nip - 4); 
     op_ldsts(stsw, rS(ctx->opcode));
 }
 
 /* stswx */
 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
 {
-    int ra = rA(ctx->opcode);
-
-    if (ra == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-        ra = rB(ctx->opcode);
-    } else {
-        gen_op_load_gpr_T0(ra);
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4); 
+    gen_addr_reg_index(ctx);
     gen_op_load_xer_bc();
-    /* NIP cannot be restored if the memory exception comes from an helper */
-    gen_op_update_nip((ctx)->nip - 4); 
     op_ldsts(stsw, rS(ctx->opcode));
 }
 
 /***                        Memory synchronisation                         ***/
 /* eieio */
-GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
+GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO)
 {
 }
 
 /* isync */
-GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
+GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM)
 {
 }
 
 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
+#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
 static GenOpFunc *gen_op_lwarx[] = {
     &gen_op_lwarx_raw,
     &gen_op_lwarx_le_raw,
+    &gen_op_lwarx_64_raw,
+    &gen_op_lwarx_le_64_raw,
 };
 static GenOpFunc *gen_op_stwcx[] = {
     &gen_op_stwcx_raw,
     &gen_op_stwcx_le_raw,
+    &gen_op_stwcx_64_raw,
+    &gen_op_stwcx_le_64_raw,
 };
 #else
 static GenOpFunc *gen_op_lwarx[] = {
@@ -1492,25 +2326,52 @@
     &gen_op_lwarx_le_user,
     &gen_op_lwarx_kernel,
     &gen_op_lwarx_le_kernel,
+    &gen_op_lwarx_64_user,
+    &gen_op_lwarx_le_64_user,
+    &gen_op_lwarx_64_kernel,
+    &gen_op_lwarx_le_64_kernel,
 };
 static GenOpFunc *gen_op_stwcx[] = {
     &gen_op_stwcx_user,
     &gen_op_stwcx_le_user,
     &gen_op_stwcx_kernel,
     &gen_op_stwcx_le_kernel,
+    &gen_op_stwcx_64_user,
+    &gen_op_stwcx_le_64_user,
+    &gen_op_stwcx_64_kernel,
+    &gen_op_stwcx_le_64_kernel,
 };
 #endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_lwarx[] = {
+    &gen_op_lwarx_raw,
+    &gen_op_lwarx_le_raw,
+};
+static GenOpFunc *gen_op_stwcx[] = {
+    &gen_op_stwcx_raw,
+    &gen_op_stwcx_le_raw,
+};
+#else
+static GenOpFunc *gen_op_lwarx[] = {
+    &gen_op_lwarx_user,
+    &gen_op_lwarx_le_user,
+    &gen_op_lwarx_kernel,
+    &gen_op_lwarx_le_kernel,
+};
+static GenOpFunc *gen_op_stwcx[] = {
+    &gen_op_stwcx_user,
+    &gen_op_stwcx_le_user,
+    &gen_op_stwcx_kernel,
+    &gen_op_stwcx_le_kernel,
+};
+#endif
+#endif
 
 /* lwarx */
-GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
+GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
 {
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    gen_addr_reg_index(ctx);
     op_lwarx();
     gen_op_store_T1_gpr(rD(ctx->opcode));
 }
@@ -1518,19 +2379,69 @@
 /* stwcx. */
 GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
 {
-        if (rA(ctx->opcode) == 0) {
-            gen_op_load_gpr_T0(rB(ctx->opcode));
-        } else {
-            gen_op_load_gpr_T0(rA(ctx->opcode));
-            gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-        }
+    gen_addr_reg_index(ctx);
     gen_op_load_gpr_T1(rS(ctx->opcode));
     op_stwcx();
 }
 
+#if defined(TARGET_PPC64)
+#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
+#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_ldarx[] = {
+    &gen_op_ldarx_raw,
+    &gen_op_ldarx_le_raw,
+    &gen_op_ldarx_64_raw,
+    &gen_op_ldarx_le_64_raw,
+};
+static GenOpFunc *gen_op_stdcx[] = {
+    &gen_op_stdcx_raw,
+    &gen_op_stdcx_le_raw,
+    &gen_op_stdcx_64_raw,
+    &gen_op_stdcx_le_64_raw,
+};
+#else
+static GenOpFunc *gen_op_ldarx[] = {
+    &gen_op_ldarx_user,
+    &gen_op_ldarx_le_user,
+    &gen_op_ldarx_kernel,
+    &gen_op_ldarx_le_kernel,
+    &gen_op_ldarx_64_user,
+    &gen_op_ldarx_le_64_user,
+    &gen_op_ldarx_64_kernel,
+    &gen_op_ldarx_le_64_kernel,
+};
+static GenOpFunc *gen_op_stdcx[] = {
+    &gen_op_stdcx_user,
+    &gen_op_stdcx_le_user,
+    &gen_op_stdcx_kernel,
+    &gen_op_stdcx_le_kernel,
+    &gen_op_stdcx_64_user,
+    &gen_op_stdcx_le_64_user,
+    &gen_op_stdcx_64_kernel,
+    &gen_op_stdcx_le_64_kernel,
+};
+#endif
+
+/* ldarx */
+GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_RES)
+{
+    gen_addr_reg_index(ctx);
+    op_ldarx();
+    gen_op_store_T1_gpr(rD(ctx->opcode));
+}
+
+/* stdcx. */
+GEN_HANDLER(stdcx_, 0x1F, 0x16, 0x06, 0x00000000, PPC_RES)
+{
+    gen_addr_reg_index(ctx);
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    op_stdcx();
+}
+#endif /* defined(TARGET_PPC64) */
+
 /* sync */
-GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
+GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM_SYNC)
 {
 }
 
@@ -1538,79 +2449,59 @@
 #define GEN_LDF(width, opc)                                                   \
 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_set_T0(simm);                                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        if (simm != 0)                                                        \
-            gen_op_addi(simm);                                                \
-    }                                                                         \
+    gen_addr_imm_index(ctx, 0);                                               \
     op_ldst(l##width);                                                        \
-    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
+    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
 #define GEN_LDUF(width, opc)                                                  \
 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0 ||                                               \
-        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    if (simm != 0)                                                            \
-        gen_op_addi(simm);                                                    \
+    gen_addr_imm_index(ctx, 0);                                               \
     op_ldst(l##width);                                                        \
-    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
+    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
 #define GEN_LDUXF(width, opc)                                                 \
 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0 ||                                               \
-        rA(ctx->opcode) == rD(ctx->opcode)) {                                 \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
-    gen_op_add();                                                             \
+    gen_addr_reg_index(ctx);                                                  \
     op_ldst(l##width);                                                        \
-    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
+    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
 
 #define GEN_LDXF(width, opc2, opc3)                                           \
 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
-        gen_op_add();                                                         \
-    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
     op_ldst(l##width);                                                        \
-    gen_op_store_FT1_fpr(rD(ctx->opcode));                                    \
+    gen_op_store_FT0_fpr(rD(ctx->opcode));                                    \
 }
 
 #define GEN_LDFS(width, op)                                                   \
@@ -1629,38 +2520,28 @@
 #define GEN_STF(width, opc)                                                   \
 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_set_T0(simm);                                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        if (simm != 0)                                                        \
-            gen_op_addi(simm);                                                \
-    }                                                                         \
-    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
+    gen_addr_imm_index(ctx, 0);                                               \
+    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
     op_ldst(st##width);                                                       \
 }
 
 #define GEN_STUF(width, opc)                                                  \
 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
 {                                                                             \
-    uint32_t simm = SIMM(ctx->opcode);                                        \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    if (simm != 0)                                                            \
-        gen_op_addi(simm);                                                    \
-    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
+    gen_addr_imm_index(ctx, 0);                                               \
+    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
     op_ldst(st##width);                                                       \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
@@ -1668,18 +2549,16 @@
 #define GEN_STUXF(width, opc)                                                 \
 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
+    if (unlikely(rA(ctx->opcode) == 0)) {                                     \
         RET_INVAL(ctx);                                                       \
         return;                                                               \
     }                                                                         \
-    gen_op_load_gpr_T0(rA(ctx->opcode));                                      \
-    gen_op_load_gpr_T1(rB(ctx->opcode));                                      \
-    gen_op_add();                                                             \
-    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
+    gen_addr_reg_index(ctx);                                                  \
+    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
     op_ldst(st##width);                                                       \
     gen_op_store_T0_gpr(rA(ctx->opcode));                                     \
 }
@@ -1687,18 +2566,12 @@
 #define GEN_STXF(width, opc2, opc3)                                           \
 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
 {                                                                             \
-    if (!ctx->fpu_enabled) {                                                  \
+    if (unlikely(!ctx->fpu_enabled)) {                                        \
         RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
         return;                                                               \
     }                                                                         \
-    if (rA(ctx->opcode) == 0) {                                               \
-        gen_op_load_gpr_T0(rB(ctx->opcode));                                  \
-    } else {                                                                  \
-        gen_op_load_gpr_T0(rA(ctx->opcode));                                  \
-        gen_op_load_gpr_T1(rB(ctx->opcode));                                  \
-        gen_op_add();                                                         \
-    }                                                                         \
-    gen_op_load_fpr_FT1(rS(ctx->opcode));                                     \
+    gen_addr_reg_index(ctx);                                                  \
+    gen_op_load_fpr_FT0(rS(ctx->opcode));                                     \
     op_ldst(st##width);                                                       \
 }
 
@@ -1718,10 +2591,12 @@
 /* stfiwx */
 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
 {
-    if (!ctx->fpu_enabled) {
+    if (unlikely(!ctx->fpu_enabled)) {
         RET_EXCP(ctx, EXCP_NO_FP, 0);
         return;
     }
+    gen_addr_reg_index(ctx);
+    /* XXX: TODO: memcpy low order 32 bits of FRP(rs) into memory */
     RET_INVAL(ctx);
 }
 
@@ -1736,18 +2611,28 @@
             gen_op_goto_tb0(TBPARAM(tb));
         else
             gen_op_goto_tb1(TBPARAM(tb));
-        gen_op_set_T1(dest);
-        gen_op_b_T1();
+        gen_set_T1(dest);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_b_T1_64();
+        else
+#endif
+            gen_op_b_T1();
         gen_op_set_T0((long)tb + n);
         if (ctx->singlestep_enabled)
             gen_op_debug();
         gen_op_exit_tb();
     } else {
-        gen_op_set_T1(dest);
-        gen_op_b_T1();
+        gen_set_T1(dest);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_b_T1_64();
+        else
+#endif
+            gen_op_b_T1();
+        gen_op_reset_T0();
         if (ctx->singlestep_enabled)
             gen_op_debug();
-        gen_op_set_T0(0);
         gen_op_exit_tb();
     }
 }
@@ -1755,17 +2640,26 @@
 /* b ba bl bla */
 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
 {
-    uint32_t li, target;
+    target_ulong li, target;
 
     /* sign extend LI */
-    li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
-
-    if (AA(ctx->opcode) == 0)
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
+    else
+#endif
+        li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
+    if (likely(AA(ctx->opcode) == 0))
         target = ctx->nip + li - 4;
     else
         target = li;
     if (LK(ctx->opcode)) {
-        gen_op_setlr(ctx->nip);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
+        else
+#endif
+            gen_op_setlr(ctx->nip);
     }
     gen_goto_tb(ctx, 0, target);
     ctx->exception = EXCP_BRANCH;
@@ -1775,20 +2669,20 @@
 #define BCOND_LR  1
 #define BCOND_CTR 2
 
-static inline void gen_bcond(DisasContext *ctx, int type) 
-{                                                                             
-    uint32_t target = 0;
-    uint32_t bo = BO(ctx->opcode);                                            
-    uint32_t bi = BI(ctx->opcode);                                            
-    uint32_t mask;                                                            
-    uint32_t li;
+static inline void gen_bcond(DisasContext *ctx, int type)
+{
+    target_ulong target = 0;
+    target_ulong li;
+    uint32_t bo = BO(ctx->opcode);
+    uint32_t bi = BI(ctx->opcode);
+    uint32_t mask;
 
     if ((bo & 0x4) == 0)
-        gen_op_dec_ctr();                                                     
+        gen_op_dec_ctr();
     switch(type) {
     case BCOND_IM:
-        li = (int32_t)((int16_t)(BD(ctx->opcode)));
-        if (AA(ctx->opcode) == 0) {
+        li = (target_long)((int16_t)(BD(ctx->opcode)));
+        if (likely(AA(ctx->opcode) == 0)) {
             target = ctx->nip + li - 4;
         } else {
             target = li;
@@ -1802,61 +2696,102 @@
         gen_op_movl_T1_lr();
         break;
     }
-    if (LK(ctx->opcode)) {                                        
-        gen_op_setlr(ctx->nip);
+    if (LK(ctx->opcode)) {
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
+        else
+#endif
+            gen_op_setlr(ctx->nip);
     }
     if (bo & 0x10) {
-        /* No CR condition */                                                 
-        switch (bo & 0x6) {                                                   
-        case 0:                                                               
-            gen_op_test_ctr();
+        /* No CR condition */
+        switch (bo & 0x6) {
+        case 0:
+#if defined(TARGET_PPC64)
+            if (ctx->sf_mode)
+                gen_op_test_ctr_64();
+            else
+#endif
+                gen_op_test_ctr();
             break;
-        case 2:                                                               
-            gen_op_test_ctrz();
-            break;                                                            
+        case 2:
+#if defined(TARGET_PPC64)
+            if (ctx->sf_mode)
+                gen_op_test_ctrz_64();
+            else
+#endif
+                gen_op_test_ctrz();
+            break;
         default:
-        case 4:                                                               
-        case 6:                                                               
+        case 4:
+        case 6:
             if (type == BCOND_IM) {
                 gen_goto_tb(ctx, 0, target);
             } else {
-                gen_op_b_T1();
+#if defined(TARGET_PPC64)
+                if (ctx->sf_mode)
+                    gen_op_b_T1_64();
+                else
+#endif
+                    gen_op_b_T1();
+                gen_op_reset_T0();
             }
             goto no_test;
         }
-    } else {                                                                  
-        mask = 1 << (3 - (bi & 0x03));                                        
-        gen_op_load_crf_T0(bi >> 2);                                          
-        if (bo & 0x8) {                                                       
-            switch (bo & 0x6) {                                               
-            case 0:                                                           
-                gen_op_test_ctr_true(mask);
-                break;                                                        
-            case 2:                                                           
-                gen_op_test_ctrz_true(mask);
-                break;                                                        
-            default:                                                          
-            case 4:                                                           
-            case 6:                                                           
+    } else {
+        mask = 1 << (3 - (bi & 0x03));
+        gen_op_load_crf_T0(bi >> 2);
+        if (bo & 0x8) {
+            switch (bo & 0x6) {
+            case 0:
+#if defined(TARGET_PPC64)
+                if (ctx->sf_mode)
+                    gen_op_test_ctr_true_64(mask);
+                else
+#endif
+                    gen_op_test_ctr_true(mask);
+                break;
+            case 2:
+#if defined(TARGET_PPC64)
+                if (ctx->sf_mode)
+                    gen_op_test_ctrz_true_64(mask);
+                else
+#endif
+                    gen_op_test_ctrz_true(mask);
+                break;
+            default:
+            case 4:
+            case 6:
                 gen_op_test_true(mask);
-                break;                                                        
-            }                                                                 
-        } else {                                                              
-            switch (bo & 0x6) {                                               
-            case 0:                                                           
-                gen_op_test_ctr_false(mask);
-                break;                                                        
-            case 2:                                                           
-                gen_op_test_ctrz_false(mask);
-                break;                                                        
+                break;
+            }
+        } else {
+            switch (bo & 0x6) {
+            case 0:
+#if defined(TARGET_PPC64)
+                if (ctx->sf_mode)
+                    gen_op_test_ctr_false_64(mask);
+                else
+#endif
+                    gen_op_test_ctr_false(mask);
+                break;                           
+            case 2:
+#if defined(TARGET_PPC64)
+                if (ctx->sf_mode)
+                    gen_op_test_ctrz_false_64(mask);
+                else
+#endif
+                    gen_op_test_ctrz_false(mask);
+                break;
             default:
-            case 4:                                                           
-            case 6:                                                           
+            case 4:
+            case 6:
                 gen_op_test_false(mask);
-                break;                                                        
-            }                                                                 
-        }                                                                     
-    }                                                                         
+                break;
+            }
+        }
+    }
     if (type == BCOND_IM) {
         int l1 = gen_new_label();
         gen_op_jz_T0(l1);
@@ -1864,24 +2799,33 @@
         gen_set_label(l1);
         gen_goto_tb(ctx, 1, ctx->nip);
     } else {
-        gen_op_btest_T1(ctx->nip);
+#if defined(TARGET_PPC64)
+        if (ctx->sf_mode)
+            gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
+        else
+#endif
+            gen_op_btest_T1(ctx->nip);
+        gen_op_reset_T0();
+ no_test:
+        if (ctx->singlestep_enabled)
+            gen_op_debug();
+        gen_op_exit_tb();
     }
- no_test:
-    ctx->exception = EXCP_BRANCH;                                             
+    ctx->exception = EXCP_BRANCH;
 }
 
 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
-{                                                                             
+{                     
     gen_bcond(ctx, BCOND_IM);
 }
 
 GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
-{                                                                             
+{                    
     gen_bcond(ctx, BCOND_CTR);
 }
 
 GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
-{                                                                             
+{                     
     gen_bcond(ctx, BCOND_LR);
 }
 
@@ -1901,21 +2845,21 @@
 }
 
 /* crand */
-GEN_CRLOGIC(and, 0x08)
+GEN_CRLOGIC(and, 0x08);
 /* crandc */
-GEN_CRLOGIC(andc, 0x04)
+GEN_CRLOGIC(andc, 0x04);
 /* creqv */
-GEN_CRLOGIC(eqv, 0x09)
+GEN_CRLOGIC(eqv, 0x09);
 /* crnand */
-GEN_CRLOGIC(nand, 0x07)
+GEN_CRLOGIC(nand, 0x07);
 /* crnor */
-GEN_CRLOGIC(nor, 0x01)
+GEN_CRLOGIC(nor, 0x01);
 /* cror */
-GEN_CRLOGIC(or, 0x0E)
+GEN_CRLOGIC(or, 0x0E);
 /* crorc */
-GEN_CRLOGIC(orc, 0x0D)
+GEN_CRLOGIC(orc, 0x0D);
 /* crxor */
-GEN_CRLOGIC(xor, 0x06)
+GEN_CRLOGIC(xor, 0x06);
 /* mcrf */
 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
 {
@@ -1925,13 +2869,13 @@
 
 /***                           System linkage                              ***/
 /* rfi (supervisor only) */
-GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
+GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVOPC(ctx);
         return;
     }
@@ -1940,6 +2884,23 @@
 #endif
 }
 
+#if defined(TARGET_PPC64)
+GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_FLOW)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    /* Restore CPU state */
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_rfid();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+#endif
+
 /* sc */
 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
 {
@@ -1952,12 +2913,12 @@
 
 /***                                Trap                                   ***/
 /* tw */
-GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
+GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
     /* Update the nip since this might generate a trap exception */
-    gen_op_update_nip(ctx->nip);
+    gen_update_nip(ctx, ctx->nip);
     gen_op_tw(TO(ctx->opcode));
 }
 
@@ -1965,51 +2926,58 @@
 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
 {
     gen_op_load_gpr_T0(rA(ctx->opcode));
-#if 0
-    printf("%s: param=0x%04x T0=0x%04x\n", __func__,
-           SIMM(ctx->opcode), TO(ctx->opcode));
-#endif
-    gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
+    gen_set_T1(SIMM(ctx->opcode));
+    /* Update the nip since this might generate a trap exception */
+    gen_update_nip(ctx, ctx->nip);
+    gen_op_tw(TO(ctx->opcode));
 }
 
-/***                          Processor control                            ***/
-static inline int check_spr_access (int spr, int rw, int supervisor)
+#if defined(TARGET_PPC64)
+/* td */
+GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
 {
-    uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    /* Update the nip since this might generate a trap exception */
+    gen_update_nip(ctx, ctx->nip);
+    gen_op_td(TO(ctx->opcode));
+}
 
-#if 0
-    if (spr != LR && spr != CTR) {
-    if (loglevel > 0) {
-        fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
-                SPR_ENCODE(spr), supervisor, rw, rights,
-                (rights >> ((2 * supervisor) + rw)) & 1);
-    } else {
-        printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
-               SPR_ENCODE(spr), supervisor, rw, rights,
-               (rights >> ((2 * supervisor) + rw)) & 1);
-    }
-    }
+/* tdi */
+GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_set_T1(SIMM(ctx->opcode));
+    /* Update the nip since this might generate a trap exception */
+    gen_update_nip(ctx, ctx->nip);
+    gen_op_td(TO(ctx->opcode));
+}
 #endif
-    if (rights == 0)
-        return -1;
-    rights = rights >> (2 * supervisor);
-    rights = rights >> rw;
 
-    return rights & 1;
-}
-
+/***                          Processor control                            ***/
 /* mcrxr */
 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
 {
     gen_op_load_xer_cr();
     gen_op_store_T0_crf(crfD(ctx->opcode));
-    gen_op_clear_xer_cr();
+    gen_op_clear_xer_ov();
+    gen_op_clear_xer_ca();
 }
 
 /* mfcr */
-GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
+GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
 {
-    gen_op_load_cr();
+    uint32_t crm, crn;
+    
+    if (likely(ctx->opcode & 0x00100000)) {
+        crm = CRM(ctx->opcode);
+        if (likely((crm ^ (crm - 1)) == 0)) {
+            crn = ffs(crm);
+            gen_op_load_cro(7 - crn);
+        }
+    } else {
+        gen_op_load_cr();
+    }
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
 
@@ -2019,7 +2987,7 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
@@ -2051,22 +3019,22 @@
     else
 #endif
         read_cb = ctx->spr_cb[sprn].uea_read;
-    if (read_cb != NULL) {
-        if (read_cb != SPR_NOACCESS) {
+    if (likely(read_cb != NULL)) {
+        if (likely(read_cb != SPR_NOACCESS)) {
             (*read_cb)(ctx, sprn);
             gen_op_store_T0_gpr(rD(ctx->opcode));
         } else {
             /* Privilege exception */
-            if (loglevel) {
+            if (loglevel != 0) {
                 fprintf(logfile, "Trying to read priviledged spr %d %03x\n",
                         sprn, sprn);
             }
             printf("Trying to read priviledged spr %d %03x\n", sprn, sprn);
-        RET_PRIVREG(ctx);
+            RET_PRIVREG(ctx);
         }
     } else {
         /* Not defined */
-        if (loglevel) {
+        if (loglevel != 0) {
             fprintf(logfile, "Trying to read invalid spr %d %03x\n",
                     sprn, sprn);
         }
@@ -2078,7 +3046,7 @@
 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
 {
     gen_op_mfspr(ctx);
-    }
+}
 
 /* mftb */
 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_TB)
@@ -2087,31 +3055,64 @@
 }
 
 /* mtcrf */
-/* The mask should be 0x00100801, but Mac OS X 10.4 use an alternate form */
 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
 {
+    uint32_t crm, crn;
+    
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    gen_op_store_cr(CRM(ctx->opcode));
+    crm = CRM(ctx->opcode);
+    if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
+        crn = ffs(crm);
+        gen_op_srli_T0(crn * 4);
+        gen_op_andi_T0(0xF);
+        gen_op_store_cro(7 - crn);
+    } else {
+        gen_op_store_cr(crm);
+    }
 }
 
 /* mtmsr */
-GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
+#if defined(TARGET_PPC64)
+GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
-    gen_op_update_nip((ctx)->nip);
+    gen_update_nip(ctx, ctx->nip);
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
     RET_CHG_FLOW(ctx);
 #endif
 }
+#endif
 
+GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_update_nip(ctx, ctx->nip);
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+#if defined(TARGET_PPC64)
+    if (!ctx->sf_mode)
+        gen_op_store_msr_32();
+    else
+#endif
+        gen_op_store_msr();
+    /* Must stop the translation as machine state (may have) changed */
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
 /* mtspr */
 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
 {
@@ -2124,22 +3125,22 @@
     else
 #endif
         write_cb = ctx->spr_cb[sprn].uea_write;
-    if (write_cb != NULL) {
-        if (write_cb != SPR_NOACCESS) {
+    if (likely(write_cb != NULL)) {
+        if (likely(write_cb != SPR_NOACCESS)) {
             gen_op_load_gpr_T0(rS(ctx->opcode));
             (*write_cb)(ctx, sprn);
         } else {
             /* Privilege exception */
-            if (loglevel) {
+            if (loglevel != 0) {
                 fprintf(logfile, "Trying to write priviledged spr %d %03x\n",
                         sprn, sprn);
             }
             printf("Trying to write priviledged spr %d %03x\n", sprn, sprn);
-        RET_PRIVREG(ctx);
-    }
+            RET_PRIVREG(ctx);
+        }
     } else {
         /* Not defined */
-        if (loglevel) {
+        if (loglevel != 0) {
             fprintf(logfile, "Trying to write invalid spr %d %03x\n",
                     sprn, sprn);
         }
@@ -2156,13 +3157,7 @@
 /* dcbf */
 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
 {
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    gen_addr_reg_index(ctx);
     op_ldst(lbz);
 }
 
@@ -2172,18 +3167,13 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVOPC(ctx);
         return;
     }
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
-    op_ldst(lbz);
+    gen_addr_reg_index(ctx);
+    /* XXX: specification says this should be treated as a store by the MMU */
+    //op_ldst(lbz);
     op_ldst(stb);
 #endif
 }
@@ -2191,63 +3181,116 @@
 /* dcdst */
 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
 {
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    /* XXX: specification say this is treated as a load by the MMU */
+    gen_addr_reg_index(ctx);
     op_ldst(lbz);
 }
 
 /* dcbt */
 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
 {
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
 }
 
 /* dcbtst */
 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
 {
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
 }
 
 /* dcbz */
+#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
+#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
-#define op_dcbz() gen_op_dcbz_raw()
+static GenOpFunc *gen_op_dcbz[] = {
+    &gen_op_dcbz_raw,
+    &gen_op_dcbz_raw,
+    &gen_op_dcbz_64_raw,
+    &gen_op_dcbz_64_raw,
+};
 #else
-#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
 static GenOpFunc *gen_op_dcbz[] = {
     &gen_op_dcbz_user,
     &gen_op_dcbz_user,
     &gen_op_dcbz_kernel,
     &gen_op_dcbz_kernel,
+    &gen_op_dcbz_64_user,
+    &gen_op_dcbz_64_user,
+    &gen_op_dcbz_64_kernel,
+    &gen_op_dcbz_64_kernel,
 };
 #endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_dcbz[] = {
+    &gen_op_dcbz_raw,
+    &gen_op_dcbz_raw,
+};
+#else
+static GenOpFunc *gen_op_dcbz[] = {
+    &gen_op_dcbz_user,
+    &gen_op_dcbz_user,
+    &gen_op_dcbz_kernel,
+    &gen_op_dcbz_kernel,
+};
+#endif
+#endif
 
 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
 {
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    gen_addr_reg_index(ctx);
     op_dcbz();
     gen_op_check_reservation();
 }
 
 /* icbi */
+#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
+#if defined(TARGET_PPC64)
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_icbi[] = {
+    &gen_op_icbi_raw,
+    &gen_op_icbi_raw,
+    &gen_op_icbi_64_raw,
+    &gen_op_icbi_64_raw,
+};
+#else
+static GenOpFunc *gen_op_icbi[] = {
+    &gen_op_icbi_user,
+    &gen_op_icbi_user,
+    &gen_op_icbi_kernel,
+    &gen_op_icbi_kernel,
+    &gen_op_icbi_64_user,
+    &gen_op_icbi_64_user,
+    &gen_op_icbi_64_kernel,
+    &gen_op_icbi_64_kernel,
+};
+#endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_icbi[] = {
+    &gen_op_icbi_raw,
+    &gen_op_icbi_raw,
+};
+#else
+static GenOpFunc *gen_op_icbi[] = {
+    &gen_op_icbi_user,
+    &gen_op_icbi_user,
+    &gen_op_icbi_kernel,
+    &gen_op_icbi_kernel,
+};
+#endif
+#endif
 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
 {
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
-    gen_op_icbi();
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
+    op_icbi();
+    RET_STOP(ctx);
 }
 
 /* Optional: */
@@ -2264,11 +3307,12 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
-    gen_op_load_sr(SR(ctx->opcode));
+    gen_op_set_T1(SR(ctx->opcode));
+    gen_op_load_sr();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
@@ -2279,12 +3323,13 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T1(rB(ctx->opcode));
-    gen_op_load_srin();
+    gen_op_srli_T1(28);
+    gen_op_load_sr();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 #endif
 }
@@ -2295,12 +3340,13 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
-    gen_op_store_sr(SR(ctx->opcode));
+    gen_op_set_T1(SR(ctx->opcode));
+    gen_op_store_sr();
     RET_STOP(ctx);
 #endif
 }
@@ -2311,13 +3357,14 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVREG(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
-    gen_op_store_srin();
+    gen_op_srli_T1(28);
+    gen_op_store_sr();
     RET_STOP(ctx);
 #endif
 }
@@ -2330,8 +3377,8 @@
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
 #else
-    if (!ctx->supervisor) {
-        if (loglevel)
+    if (unlikely(!ctx->supervisor)) {
+        if (loglevel != 0)
             fprintf(logfile, "%s: ! supervisor\n", __func__);
         RET_PRIVOPC(ctx);
         return;
@@ -2342,28 +3389,33 @@
 }
 
 /* tlbie */
-GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
+GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
-    gen_op_tlbie();
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_tlbie_64();
+    else
+#endif
+        gen_op_tlbie();
     RET_STOP(ctx);
 #endif
 }
 
 /* tlbsync */
-GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
+GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
 {
 #if defined(CONFIG_USER_ONLY)
     RET_PRIVOPC(ctx);
 #else
-    if (!ctx->supervisor) {
+    if (unlikely(!ctx->supervisor)) {
         RET_PRIVOPC(ctx);
         return;
     }
@@ -2374,18 +3426,58 @@
 #endif
 }
 
+#if defined(TARGET_PPC64)
+/* slbia */
+GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        if (loglevel != 0)
+            fprintf(logfile, "%s: ! supervisor\n", __func__);
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_slbia();
+    RET_STOP(ctx);
+#endif
+}
+
+/* slbie */
+GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_slbie();
+    RET_STOP(ctx);
+#endif
+}
+#endif
+
 /***                              External control                         ***/
 /* Optional: */
 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
+#if defined(TARGET_PPC64)
 #if defined(CONFIG_USER_ONLY)
 static GenOpFunc *gen_op_eciwx[] = {
     &gen_op_eciwx_raw,
     &gen_op_eciwx_le_raw,
+    &gen_op_eciwx_64_raw,
+    &gen_op_eciwx_le_64_raw,
 };
 static GenOpFunc *gen_op_ecowx[] = {
     &gen_op_ecowx_raw,
     &gen_op_ecowx_le_raw,
+    &gen_op_ecowx_64_raw,
+    &gen_op_ecowx_le_64_raw,
 };
 #else
 static GenOpFunc *gen_op_eciwx[] = {
@@ -2393,26 +3485,53 @@
     &gen_op_eciwx_le_user,
     &gen_op_eciwx_kernel,
     &gen_op_eciwx_le_kernel,
+    &gen_op_eciwx_64_user,
+    &gen_op_eciwx_le_64_user,
+    &gen_op_eciwx_64_kernel,
+    &gen_op_eciwx_le_64_kernel,
 };
 static GenOpFunc *gen_op_ecowx[] = {
     &gen_op_ecowx_user,
     &gen_op_ecowx_le_user,
     &gen_op_ecowx_kernel,
     &gen_op_ecowx_le_kernel,
+    &gen_op_ecowx_64_user,
+    &gen_op_ecowx_le_64_user,
+    &gen_op_ecowx_64_kernel,
+    &gen_op_ecowx_le_64_kernel,
 };
 #endif
+#else
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_eciwx[] = {
+    &gen_op_eciwx_raw,
+    &gen_op_eciwx_le_raw,
+};
+static GenOpFunc *gen_op_ecowx[] = {
+    &gen_op_ecowx_raw,
+    &gen_op_ecowx_le_raw,
+};
+#else
+static GenOpFunc *gen_op_eciwx[] = {
+    &gen_op_eciwx_user,
+    &gen_op_eciwx_le_user,
+    &gen_op_eciwx_kernel,
+    &gen_op_eciwx_le_kernel,
+};
+static GenOpFunc *gen_op_ecowx[] = {
+    &gen_op_ecowx_user,
+    &gen_op_ecowx_le_user,
+    &gen_op_ecowx_kernel,
+    &gen_op_ecowx_le_kernel,
+};
+#endif
+#endif
 
 /* eciwx */
 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
 {
     /* Should check EAR[E] & alignment ! */
-    if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
-    } else {
-        gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
-    }
+    gen_addr_reg_index(ctx);
     op_eciwx();
     gen_op_store_T0_gpr(rD(ctx->opcode));
 }
@@ -2421,17 +3540,2035 @@
 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
 {
     /* Should check EAR[E] & alignment ! */
+    gen_addr_reg_index(ctx);
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    op_ecowx();
+}
+
+/* PowerPC 601 specific instructions */
+/* abs - abs. */
+GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_POWER_abs();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* abso - abso. */
+GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_POWER_abso();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* clcs */
+GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR) /* 601 ? */
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_POWER_clcs();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+}
+
+/* div - div. */
+GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_div();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* divo - divo. */
+GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_divo();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* divs - divs. */
+GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_divs();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* divso - divso. */
+GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_divso();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* doz - doz. */
+GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_doz();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* dozo - dozo. */
+GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_dozo();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* dozi */
+GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_set_T1(SIMM(ctx->opcode));
+    gen_op_POWER_doz();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+}
+
+/* As lscbx load from memory byte after byte, it's always endian safe */
+#define op_POWER_lscbx(start, ra, rb) \
+(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc3 *gen_op_POWER_lscbx[] = {
+    &gen_op_POWER_lscbx_raw,
+    &gen_op_POWER_lscbx_raw,
+};
+#else
+static GenOpFunc3 *gen_op_POWER_lscbx[] = {
+    &gen_op_POWER_lscbx_user,
+    &gen_op_POWER_lscbx_user,
+    &gen_op_POWER_lscbx_kernel,
+    &gen_op_POWER_lscbx_kernel,
+};
+#endif
+
+/* lscbx - lscbx. */
+GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
+{
+    int ra = rA(ctx->opcode);
+    int rb = rB(ctx->opcode);
+
+    gen_addr_reg_index(ctx);
+    if (ra == 0) {
+        ra = rb;
+    }
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_op_load_xer_bc();
+    gen_op_load_xer_cmp();
+    op_POWER_lscbx(rD(ctx->opcode), ra, rb);
+    gen_op_store_xer_bc();
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* maskg - maskg. */
+GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_maskg();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* maskir - maskir. */
+GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_load_gpr_T2(rB(ctx->opcode));
+    gen_op_POWER_maskir();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* mul - mul. */
+GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_mul();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* mulo - mulo. */
+GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_mulo();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* nabs - nabs. */
+GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_POWER_nabs();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* nabso - nabso. */
+GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_POWER_nabso();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* rlmi - rlmi. */
+GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
+{
+    uint32_t mb, me;
+
+    mb = MB(ctx->opcode);
+    me = ME(ctx->opcode);
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rA(ctx->opcode));
+    gen_op_load_gpr_T2(rB(ctx->opcode));
+    gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* rrib - rrib. */
+GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rA(ctx->opcode));
+    gen_op_load_gpr_T2(rB(ctx->opcode));
+    gen_op_POWER_rrib();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sle - sle. */
+GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sle();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sleq - sleq. */
+GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sleq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sliq - sliq. */
+GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_set_T1(SH(ctx->opcode));
+    gen_op_POWER_sle();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* slliq - slliq. */
+GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_set_T1(SH(ctx->opcode));
+    gen_op_POWER_sleq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sllq - sllq. */
+GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sllq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* slq - slq. */
+GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_slq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sraiq - sraiq. */
+GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_set_T1(SH(ctx->opcode));
+    gen_op_POWER_sraq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sraq - sraq. */
+GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sraq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sre - sre. */
+GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sre();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* srea - srea. */
+GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_srea();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sreq */
+GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_sreq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* sriq */
+GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_set_T1(SH(ctx->opcode));
+    gen_op_POWER_srq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* srliq */
+GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_set_T1(SH(ctx->opcode));
+    gen_op_POWER_srlq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* srlq */
+GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_srlq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* srq */
+GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_POWER_srq();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    if (unlikely(Rc(ctx->opcode) != 0))
+        gen_set_Rc0(ctx);
+}
+
+/* PowerPC 602 specific instructions */
+/* dsa  */
+GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
+{
+    /* XXX: TODO */
+    RET_INVAL(ctx);
+}
+
+/* esa */
+GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
+{
+    /* XXX: TODO */
+    RET_INVAL(ctx);
+}
+
+/* mfrom */
+GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_602_mfrom();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* 602 - 603 - G2 TLB management */
+/* tlbld */
+GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_6xx_tlbld();
+    RET_STOP(ctx);
+#endif
+}
+
+/* tlbli */
+GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rB(ctx->opcode));
+    gen_op_6xx_tlbli();
+    RET_STOP(ctx);
+#endif
+}
+
+/* POWER instructions not in PowerPC 601 */
+/* clf */
+GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
+{
+    /* Cache line flush: implemented as no-op */
+}
+
+/* cli */
+GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
+{
+    /* Cache line invalidate: priviledged and treated as no-op */
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+#endif
+}
+
+/* dclst */
+GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
+{
+    /* Data cache line store: treated as no-op */
+}
+
+GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    int ra = rA(ctx->opcode);
+    int rd = rD(ctx->opcode);
+
+    gen_addr_reg_index(ctx);
+    gen_op_POWER_mfsri();
+    gen_op_store_T0_gpr(rd);
+    if (ra != 0 && ra != rd)
+        gen_op_store_T1_gpr(ra);
+#endif
+}
+
+GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_addr_reg_index(ctx);
+    gen_op_POWER_rac();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_POWER_rfsvc();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+/* svc is not implemented for now */
+
+/* POWER2 specific instructions */
+/* Quad manipulation (load/store two floats at a time) */
+#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
+#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+static GenOpFunc *gen_op_POWER2_lfq[] = {
+    &gen_op_POWER2_lfq_le_raw,
+    &gen_op_POWER2_lfq_raw,
+};
+static GenOpFunc *gen_op_POWER2_stfq[] = {
+    &gen_op_POWER2_stfq_le_raw,
+    &gen_op_POWER2_stfq_raw,
+};
+#else
+static GenOpFunc *gen_op_POWER2_lfq[] = {
+    &gen_op_POWER2_lfq_le_user,
+    &gen_op_POWER2_lfq_user,
+    &gen_op_POWER2_lfq_le_kernel,
+    &gen_op_POWER2_lfq_kernel,
+};
+static GenOpFunc *gen_op_POWER2_stfq[] = {
+    &gen_op_POWER2_stfq_le_user,
+    &gen_op_POWER2_stfq_user,
+    &gen_op_POWER2_stfq_le_kernel,
+    &gen_op_POWER2_stfq_kernel,
+};
+#endif
+
+/* lfq */
+GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
+{
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
+    op_POWER2_lfq();
+    gen_op_store_FT0_fpr(rD(ctx->opcode));
+    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
+}
+
+/* lfqu */
+GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
+{
+    int ra = rA(ctx->opcode);
+
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
+    op_POWER2_lfq();
+    gen_op_store_FT0_fpr(rD(ctx->opcode));
+    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
+    if (ra != 0)
+        gen_op_store_T0_gpr(ra);
+}
+
+/* lfqux */
+GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
+{
+    int ra = rA(ctx->opcode);
+
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
+    op_POWER2_lfq();
+    gen_op_store_FT0_fpr(rD(ctx->opcode));
+    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
+    if (ra != 0)
+        gen_op_store_T0_gpr(ra);
+}
+
+/* lfqx */
+GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
+{
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
+    op_POWER2_lfq();
+    gen_op_store_FT0_fpr(rD(ctx->opcode));
+    gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
+}
+
+/* stfq */
+GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
+{
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
+    gen_op_load_fpr_FT0(rS(ctx->opcode));
+    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
+    op_POWER2_stfq();
+}
+
+/* stfqu */
+GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
+{
+    int ra = rA(ctx->opcode);
+
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_imm_index(ctx, 0);
+    gen_op_load_fpr_FT0(rS(ctx->opcode));
+    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
+    op_POWER2_stfq();
+    if (ra != 0)
+        gen_op_store_T0_gpr(ra);
+}
+
+/* stfqux */
+GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
+{
+    int ra = rA(ctx->opcode);
+
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
+    gen_op_load_fpr_FT0(rS(ctx->opcode));
+    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
+    op_POWER2_stfq();
+    if (ra != 0)
+        gen_op_store_T0_gpr(ra);
+}
+
+/* stfqx */
+GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
+{
+    /* NIP cannot be restored if the memory exception comes from an helper */
+    gen_update_nip(ctx, ctx->nip - 4);
+    gen_addr_reg_index(ctx);
+    gen_op_load_fpr_FT0(rS(ctx->opcode));
+    gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
+    op_POWER2_stfq();
+}
+
+/* BookE specific instructions */
+GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE)
+{
+    /* XXX: TODO */
+    RET_INVAL(ctx);
+}
+
+GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_addr_reg_index(ctx);
+    /* Use the same micro-ops as for tlbie */
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode)
+        gen_op_tlbie_64();
+    else
+#endif
+        gen_op_tlbie();
+    RET_STOP(ctx);
+#endif
+}
+
+/* All 405 MAC instructions are translated here */
+static inline void gen_405_mulladd_insn (DisasContext *ctx, int opc2, int opc3,
+                                         int ra, int rb, int rt, int Rc)
+{
+    gen_op_load_gpr_T0(ra);
+    gen_op_load_gpr_T1(rb);
+    switch (opc3 & 0x0D) {
+    case 0x05:
+        /* macchw    - macchw.    - macchwo   - macchwo.   */
+        /* macchws   - macchws.   - macchwso  - macchwso.  */
+        /* nmacchw   - nmacchw.   - nmacchwo  - nmacchwo.  */
+        /* nmacchws  - nmacchws.  - nmacchwso - nmacchwso. */
+        /* mulchw - mulchw. */
+        gen_op_405_mulchw();
+        break;
+    case 0x04:
+        /* macchwu   - macchwu.   - macchwuo  - macchwuo.  */
+        /* macchwsu  - macchwsu.  - macchwsuo - macchwsuo. */
+        /* mulchwu - mulchwu. */
+        gen_op_405_mulchwu();
+        break;
+    case 0x01:
+        /* machhw    - machhw.    - machhwo   - machhwo.   */
+        /* machhws   - machhws.   - machhwso  - machhwso.  */
+        /* nmachhw   - nmachhw.   - nmachhwo  - nmachhwo.  */
+        /* nmachhws  - nmachhws.  - nmachhwso - nmachhwso. */
+        /* mulhhw - mulhhw. */
+        gen_op_405_mulhhw();
+        break;
+    case 0x00:
+        /* machhwu   - machhwu.   - machhwuo  - machhwuo.  */
+        /* machhwsu  - machhwsu.  - machhwsuo - machhwsuo. */
+        /* mulhhwu - mulhhwu. */
+        gen_op_405_mulhhwu();
+        break;
+    case 0x0D:
+        /* maclhw    - maclhw.    - maclhwo   - maclhwo.   */
+        /* maclhws   - maclhws.   - maclhwso  - maclhwso.  */
+        /* nmaclhw   - nmaclhw.   - nmaclhwo  - nmaclhwo.  */
+        /* nmaclhws  - nmaclhws.  - nmaclhwso - nmaclhwso. */
+        /* mullhw - mullhw. */
+        gen_op_405_mullhw();
+        break;
+    case 0x0C:
+        /* maclhwu   - maclhwu.   - maclhwuo  - maclhwuo.  */
+        /* maclhwsu  - maclhwsu.  - maclhwsuo - maclhwsuo. */
+        /* mullhwu - mullhwu. */
+        gen_op_405_mullhwu();
+        break;
+    }
+    if (opc2 & 0x02) {
+        /* nmultiply-and-accumulate (0x0E) */
+        gen_op_neg();
+    }
+    if (opc2 & 0x04) {
+        /* (n)multiply-and-accumulate (0x0C - 0x0E) */
+        gen_op_load_gpr_T2(rt);
+        gen_op_move_T1_T0();
+        gen_op_405_add_T0_T2();
+    }
+    if (opc3 & 0x10) {
+        /* Check overflow */
+        if (opc3 & 0x01)
+            gen_op_405_check_ov();
+        else
+            gen_op_405_check_ovu();
+    }
+    if (opc3 & 0x02) {
+        /* Saturate */
+        if (opc3 & 0x01)
+            gen_op_405_check_sat();
+        else
+            gen_op_405_check_satu();
+    }
+    gen_op_store_T0_gpr(rt);
+    if (unlikely(Rc) != 0) {
+        /* Update Rc0 */
+        gen_set_Rc0(ctx);
+    }
+}
+
+#define GEN_MAC_HANDLER(name, opc2, opc3)                                     \
+GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC)                  \
+{                                                                             \
+    gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode),   \
+                         rD(ctx->opcode), Rc(ctx->opcode));                   \
+}
+
+/* macchw    - macchw.    */
+GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
+/* macchwo   - macchwo.   */
+GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
+/* macchws   - macchws.   */
+GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
+/* macchwso  - macchwso.  */
+GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
+/* macchwsu  - macchwsu.  */
+GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
+/* macchwsuo - macchwsuo. */
+GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
+/* macchwu   - macchwu.   */
+GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
+/* macchwuo  - macchwuo.  */
+GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
+/* machhw    - machhw.    */
+GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
+/* machhwo   - machhwo.   */
+GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
+/* machhws   - machhws.   */
+GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
+/* machhwso  - machhwso.  */
+GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
+/* machhwsu  - machhwsu.  */
+GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
+/* machhwsuo - machhwsuo. */
+GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
+/* machhwu   - machhwu.   */
+GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
+/* machhwuo  - machhwuo.  */
+GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
+/* maclhw    - maclhw.    */
+GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
+/* maclhwo   - maclhwo.   */
+GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
+/* maclhws   - maclhws.   */
+GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
+/* maclhwso  - maclhwso.  */
+GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
+/* maclhwu   - maclhwu.   */
+GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
+/* maclhwuo  - maclhwuo.  */
+GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
+/* maclhwsu  - maclhwsu.  */
+GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
+/* maclhwsuo - maclhwsuo. */
+GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
+/* nmacchw   - nmacchw.   */
+GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
+/* nmacchwo  - nmacchwo.  */
+GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
+/* nmacchws  - nmacchws.  */
+GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
+/* nmacchwso - nmacchwso. */
+GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
+/* nmachhw   - nmachhw.   */
+GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
+/* nmachhwo  - nmachhwo.  */
+GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
+/* nmachhws  - nmachhws.  */
+GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
+/* nmachhwso - nmachhwso. */
+GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
+/* nmaclhw   - nmaclhw.   */
+GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
+/* nmaclhwo  - nmaclhwo.  */
+GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
+/* nmaclhws  - nmaclhws.  */
+GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
+/* nmaclhwso - nmaclhwso. */
+GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
+
+/* mulchw  - mulchw.  */
+GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
+/* mulchwu - mulchwu. */
+GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
+/* mulhhw  - mulhhw.  */
+GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
+/* mulhhwu - mulhhwu. */
+GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
+/* mullhw  - mullhw.  */
+GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
+/* mullhwu - mullhwu. */
+GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
+
+/* mfdcr */
+GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    uint32_t dcrn = SPR(ctx->opcode);
+
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_set_T0(dcrn);
+    gen_op_load_dcr();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* mtdcr */
+GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    uint32_t dcrn = SPR(ctx->opcode);
+
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_set_T0(dcrn);
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_store_dcr();
+#endif
+}
+
+/* mfdcrx */
+GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_dcr();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* mtdcrx */
+GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVREG(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVREG(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rA(ctx->opcode));
+    gen_op_load_gpr_T1(rS(ctx->opcode));
+    gen_op_store_dcr();
+#endif
+}
+
+/* dccci */
+GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* interpreted as no-op */
+#endif
+}
+
+/* dcread */
+GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_addr_reg_index(ctx);
+    op_ldst(lwz);
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* icbt */
+GEN_HANDLER(icbt_40x, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_SPEC)
+{
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
+}
+
+/* iccci */
+GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* interpreted as no-op */
+#endif
+}
+
+/* icread */
+GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* interpreted as no-op */
+#endif
+}
+
+/* rfci (supervisor only) */
+GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_40x_rfci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_rfci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+/* BookE specific */
+GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_rfdi();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+
+GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_BOOKE)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    /* Restore CPU state */
+    gen_op_rfmci();
+    RET_CHG_FLOW(ctx);
+#endif
+}
+/* TLB management - PowerPC 405 implementation */
+/* tlbre */
+GEN_HANDLER(tlbre, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_SPEC)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    switch (rB(ctx->opcode)) {
+    case 0:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_4xx_tlbre_hi();
+        gen_op_store_T0_gpr(rD(ctx->opcode));
+        break;
+    case 1:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_4xx_tlbre_lo();
+        gen_op_store_T0_gpr(rD(ctx->opcode));
+        break;
+    default:
+        RET_INVAL(ctx);
+        break;
+    }
+#endif
+}
+
+/* tlbsx - tlbsx. */
+GEN_HANDLER(tlbsx, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_SPEC)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_addr_reg_index(ctx);
+    if (Rc(ctx->opcode))
+        gen_op_4xx_tlbsx_();
+    else
+        gen_op_4xx_tlbsx();
+    gen_op_store_T0_gpr(rD(ctx->opcode));
+#endif
+}
+
+/* tlbwe */
+GEN_HANDLER(tlbwe, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_SPEC)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    switch (rB(ctx->opcode)) {
+    case 0:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rS(ctx->opcode));
+        gen_op_4xx_tlbwe_hi();
+        break;
+    case 1:
+        gen_op_load_gpr_T0(rA(ctx->opcode));
+        gen_op_load_gpr_T1(rS(ctx->opcode));
+        gen_op_4xx_tlbwe_lo();
+        break;
+    default:
+        RET_INVAL(ctx);
+        break;
+    }
+#endif
+}
+
+/* wrtee */
+GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_load_gpr_T0(rD(ctx->opcode));
+    gen_op_wrte();
+    RET_EXCP(ctx, EXCP_MTMSR, 0);
+#endif
+}
+
+/* wrteei */
+GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
+{
+#if defined(CONFIG_USER_ONLY)
+    RET_PRIVOPC(ctx);
+#else
+    if (unlikely(!ctx->supervisor)) {
+        RET_PRIVOPC(ctx);
+        return;
+    }
+    gen_op_set_T0(ctx->opcode & 0x00010000);
+    gen_op_wrte();
+    RET_EXCP(ctx, EXCP_MTMSR, 0);
+#endif
+}
+
+/* PowerPC 440 specific instructions */
+/* dlmzb */
+GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
+{
+    gen_op_load_gpr_T0(rS(ctx->opcode));
+    gen_op_load_gpr_T1(rB(ctx->opcode));
+    gen_op_440_dlmzb();
+    gen_op_store_T0_gpr(rA(ctx->opcode));
+    gen_op_store_xer_bc();
+    if (Rc(ctx->opcode)) {
+        gen_op_440_dlmzb_update_Rc();
+        gen_op_store_T0_crf(0);
+    }
+}
+
+/* mbar replaces eieio on 440 */
+GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
+{
+    /* interpreted as no-op */
+}
+
+/* msync replaces sync on 440 */
+GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_BOOKE)
+{
+    /* interpreted as no-op */
+}
+
+/* icbt */
+GEN_HANDLER(icbt_440, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
+{
+    /* interpreted as no-op */
+    /* XXX: specification say this is treated as a load by the MMU
+     *      but does not generate any exception
+     */
+}
+
+#if defined(TARGET_PPCEMB)
+/***                           SPE extension                               ***/
+
+/* Register moves */
+GEN32(gen_op_load_gpr64_T0, gen_op_load_gpr64_T0_gpr);
+GEN32(gen_op_load_gpr64_T1, gen_op_load_gpr64_T1_gpr);
+#if 0 // unused
+GEN32(gen_op_load_gpr64_T2, gen_op_load_gpr64_T2_gpr);
+#endif
+
+GEN32(gen_op_store_T0_gpr64, gen_op_store_T0_gpr64_gpr);
+GEN32(gen_op_store_T1_gpr64, gen_op_store_T1_gpr64_gpr);
+#if 0 // unused
+GEN32(gen_op_store_T2_gpr64, gen_op_store_T2_gpr64_gpr);
+#endif
+
+#define GEN_SPE(name0, name1, opc2, opc3, inval, type)                        \
+GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
+{                                                                             \
+    if (Rc(ctx->opcode))                                                      \
+        gen_##name1(ctx);                                                     \
+    else                                                                      \
+        gen_##name0(ctx);                                                     \
+}
+
+/* Handler for undefined SPE opcodes */
+static inline void gen_speundef (DisasContext *ctx)
+{
+    RET_INVAL(ctx);
+}
+
+/* SPE load and stores */
+static inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
+{
+    target_long simm = rB(ctx->opcode);
+
     if (rA(ctx->opcode) == 0) {
-        gen_op_load_gpr_T0(rB(ctx->opcode));
+        gen_set_T0(simm << sh);
     } else {
         gen_op_load_gpr_T0(rA(ctx->opcode));
-        gen_op_load_gpr_T1(rB(ctx->opcode));
-        gen_op_add();
+        if (likely(simm != 0))
+            gen_op_addi(simm << sh);
     }
-    gen_op_load_gpr_T2(rS(ctx->opcode));
-    op_ecowx();
 }
 
+#define op_spe_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
+#if defined(CONFIG_USER_ONLY)
+#if defined(TARGET_PPC64)
+#define OP_SPE_LD_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_l##name[] = {                                    \
+    &gen_op_spe_l##name##_raw,                                                \
+    &gen_op_spe_l##name##_le_raw,                                             \
+    &gen_op_spe_l##name##_64_raw,                                             \
+    &gen_op_spe_l##name##_le_64_raw,                                          \
+};
+#define OP_SPE_ST_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_st##name[] = {                                   \
+    &gen_op_spe_st##name##_raw,                                               \
+    &gen_op_spe_st##name##_le_raw,                                            \
+    &gen_op_spe_st##name##_64_raw,                                            \
+    &gen_op_spe_st##name##_le_64_raw,                                         \
+};
+#else /* defined(TARGET_PPC64) */
+#define OP_SPE_LD_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_l##name[] = {                                    \
+    &gen_op_spe_l##name##_raw,                                                \
+    &gen_op_spe_l##name##_le_raw,                                             \
+};
+#define OP_SPE_ST_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_st##name[] = {                                   \
+    &gen_op_spe_st##name##_raw,                                               \
+    &gen_op_spe_st##name##_le_raw,                                            \
+};
+#endif /* defined(TARGET_PPC64) */
+#else /* defined(CONFIG_USER_ONLY) */
+#if defined(TARGET_PPC64)
+#define OP_SPE_LD_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_l##name[] = {                                    \
+    &gen_op_spe_l##name##_user,                                               \
+    &gen_op_spe_l##name##_le_user,                                            \
+    &gen_op_spe_l##name##_kernel,                                             \
+    &gen_op_spe_l##name##_le_kernel,                                          \
+    &gen_op_spe_l##name##_64_user,                                            \
+    &gen_op_spe_l##name##_le_64_user,                                         \
+    &gen_op_spe_l##name##_64_kernel,                                          \
+    &gen_op_spe_l##name##_le_64_kernel,                                       \
+};
+#define OP_SPE_ST_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_st##name[] = {                                   \
+    &gen_op_spe_st##name##_user,                                              \
+    &gen_op_spe_st##name##_le_user,                                           \
+    &gen_op_spe_st##name##_kernel,                                            \
+    &gen_op_spe_st##name##_le_kernel,                                         \
+    &gen_op_spe_st##name##_64_user,                                           \
+    &gen_op_spe_st##name##_le_64_user,                                        \
+    &gen_op_spe_st##name##_64_kernel,                                         \
+    &gen_op_spe_st##name##_le_64_kernel,                                      \
+};
+#else /* defined(TARGET_PPC64) */
+#define OP_SPE_LD_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_l##name[] = {                                    \
+    &gen_op_spe_l##name##_user,                                               \
+    &gen_op_spe_l##name##_le_user,                                            \
+    &gen_op_spe_l##name##_kernel,                                             \
+    &gen_op_spe_l##name##_le_kernel,                                          \
+};
+#define OP_SPE_ST_TABLE(name)                                                 \
+static GenOpFunc *gen_op_spe_st##name[] = {                                   \
+    &gen_op_spe_st##name##_user,                                              \
+    &gen_op_spe_st##name##_le_user,                                           \
+    &gen_op_spe_st##name##_kernel,                                            \
+    &gen_op_spe_st##name##_le_kernel,                                         \
+};
+#endif /* defined(TARGET_PPC64) */
+#endif /* defined(CONFIG_USER_ONLY) */
+
+#define GEN_SPE_LD(name, sh)                                                  \
+static inline void gen_evl##name (DisasContext *ctx)                          \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_spe_imm_index(ctx, sh);                                          \
+    op_spe_ldst(spe_l##name);                                                 \
+    gen_op_store_T1_gpr64(rD(ctx->opcode));                                   \
+}
+
+#define GEN_SPE_LDX(name)                                                     \
+static inline void gen_evl##name##x (DisasContext *ctx)                       \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
+    op_spe_ldst(spe_l##name);                                                 \
+    gen_op_store_T1_gpr64(rD(ctx->opcode));                                   \
+}
+
+#define GEN_SPEOP_LD(name, sh)                                                \
+OP_SPE_LD_TABLE(name);                                                        \
+GEN_SPE_LD(name, sh);                                                         \
+GEN_SPE_LDX(name)
+
+#define GEN_SPE_ST(name, sh)                                                  \
+static inline void gen_evst##name (DisasContext *ctx)                         \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_spe_imm_index(ctx, sh);                                          \
+    gen_op_load_gpr64_T1(rS(ctx->opcode));                                    \
+    op_spe_ldst(spe_st##name);                                                \
+}
+
+#define GEN_SPE_STX(name)                                                     \
+static inline void gen_evst##name##x (DisasContext *ctx)                      \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_addr_reg_index(ctx);                                                  \
+    gen_op_load_gpr64_T1(rS(ctx->opcode));                                    \
+    op_spe_ldst(spe_st##name);                                                \
+}
+
+#define GEN_SPEOP_ST(name, sh)                                                \
+OP_SPE_ST_TABLE(name);                                                        \
+GEN_SPE_ST(name, sh);                                                         \
+GEN_SPE_STX(name)
+
+#define GEN_SPEOP_LDST(name, sh)                                              \
+GEN_SPEOP_LD(name, sh);                                                       \
+GEN_SPEOP_ST(name, sh)
+
+/* SPE arithmetic and logic */
+#define GEN_SPEOP_ARITH2(name)                                                \
+static inline void gen_##name (DisasContext *ctx)                             \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
+    gen_op_load_gpr64_T1(rB(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
+}
+
+#define GEN_SPEOP_ARITH1(name)                                                \
+static inline void gen_##name (DisasContext *ctx)                             \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
+}
+
+#define GEN_SPEOP_COMP(name)                                                  \
+static inline void gen_##name (DisasContext *ctx)                             \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
+    gen_op_load_gpr64_T1(rB(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_crf(crfD(ctx->opcode));                                   \
+}
+
+/* Logical */
+GEN_SPEOP_ARITH2(evand);
+GEN_SPEOP_ARITH2(evandc);
+GEN_SPEOP_ARITH2(evxor);
+GEN_SPEOP_ARITH2(evor);
+GEN_SPEOP_ARITH2(evnor);
+GEN_SPEOP_ARITH2(eveqv);
+GEN_SPEOP_ARITH2(evorc);
+GEN_SPEOP_ARITH2(evnand);
+GEN_SPEOP_ARITH2(evsrwu);
+GEN_SPEOP_ARITH2(evsrws);
+GEN_SPEOP_ARITH2(evslw);
+GEN_SPEOP_ARITH2(evrlw);
+GEN_SPEOP_ARITH2(evmergehi);
+GEN_SPEOP_ARITH2(evmergelo);
+GEN_SPEOP_ARITH2(evmergehilo);
+GEN_SPEOP_ARITH2(evmergelohi);
+
+/* Arithmetic */
+GEN_SPEOP_ARITH2(evaddw);
+GEN_SPEOP_ARITH2(evsubfw);
+GEN_SPEOP_ARITH1(evabs);
+GEN_SPEOP_ARITH1(evneg);
+GEN_SPEOP_ARITH1(evextsb);
+GEN_SPEOP_ARITH1(evextsh);
+GEN_SPEOP_ARITH1(evrndw);
+GEN_SPEOP_ARITH1(evcntlzw);
+GEN_SPEOP_ARITH1(evcntlsw);
+static inline void gen_brinc (DisasContext *ctx)
+{
+    /* Note: brinc is usable even if SPE is disabled */
+    gen_op_load_gpr64_T0(rA(ctx->opcode));
+    gen_op_load_gpr64_T1(rB(ctx->opcode));
+    gen_op_brinc();
+    gen_op_store_T0_gpr64(rD(ctx->opcode));
+}
+
+#define GEN_SPEOP_ARITH_IMM2(name)                                            \
+static inline void gen_##name##i (DisasContext *ctx)                          \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
+    gen_op_splatwi_T1_64(rA(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
+}
+
+#define GEN_SPEOP_LOGIC_IMM2(name)                                            \
+static inline void gen_##name##i (DisasContext *ctx)                          \
+{                                                                             \
+    if (unlikely(!ctx->spe_enabled)) {                                        \
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        return;                                                               \
+    }                                                                         \
+    gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
+    gen_op_splatwi_T1_64(rB(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
+}
+
+GEN_SPEOP_ARITH_IMM2(evaddw);
+#define gen_evaddiw gen_evaddwi
+GEN_SPEOP_ARITH_IMM2(evsubfw);
+#define gen_evsubifw gen_evsubfwi
+GEN_SPEOP_LOGIC_IMM2(evslw);
+GEN_SPEOP_LOGIC_IMM2(evsrwu);
+#define gen_evsrwis gen_evsrwsi
+GEN_SPEOP_LOGIC_IMM2(evsrws);
+#define gen_evsrwiu gen_evsrwui
+GEN_SPEOP_LOGIC_IMM2(evrlw);
+
+static inline void gen_evsplati (DisasContext *ctx)
+{
+    int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
+
+    gen_op_splatwi_T0_64(imm);
+    gen_op_store_T0_gpr64(rD(ctx->opcode));
+}
+
+static inline void gen_evsplatfi (DisasContext *ctx)
+{
+    uint32_t imm = rA(ctx->opcode) << 27;
+
+    gen_op_splatwi_T0_64(imm);
+    gen_op_store_T0_gpr64(rD(ctx->opcode));
+}
+
+/* Comparison */
+GEN_SPEOP_COMP(evcmpgtu);
+GEN_SPEOP_COMP(evcmpgts);
+GEN_SPEOP_COMP(evcmpltu);
+GEN_SPEOP_COMP(evcmplts);
+GEN_SPEOP_COMP(evcmpeq);
+
+GEN_SPE(evaddw,         speundef,      0x00, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evaddiw,        speundef,      0x01, 0x08, 0x00000000, PPC_SPE);
+GEN_SPE(evsubfw,        speundef,      0x02, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evsubifw,       speundef,      0x03, 0x08, 0x00000000, PPC_SPE);
+GEN_SPE(evabs,          evneg,         0x04, 0x08, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evextsb,        evextsh,       0x05, 0x08, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evrndw,         evcntlzw,      0x06, 0x08, 0x0000F800, PPC_SPE); ////
+GEN_SPE(evcntlsw,       brinc,         0x07, 0x08, 0x00000000, PPC_SPE); //
+GEN_SPE(speundef,       evand,         0x08, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evandc,         speundef,      0x09, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evxor,          evor,          0x0B, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evnor,          eveqv,         0x0C, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(speundef,       evorc,         0x0D, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evnand,         speundef,      0x0F, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evsrwu,         evsrws,        0x10, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evsrwiu,        evsrwis,       0x11, 0x08, 0x00000000, PPC_SPE);
+GEN_SPE(evslw,          speundef,      0x12, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evslwi,         speundef,      0x13, 0x08, 0x00000000, PPC_SPE);
+GEN_SPE(evrlw,          evsplati,      0x14, 0x08, 0x00000000, PPC_SPE); //
+GEN_SPE(evrlwi,         evsplatfi,     0x15, 0x08, 0x00000000, PPC_SPE);
+GEN_SPE(evmergehi,      evmergelo,     0x16, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evmergehilo,    evmergelohi,   0x17, 0x08, 0x00000000, PPC_SPE); ////
+GEN_SPE(evcmpgtu,       evcmpgts,      0x18, 0x08, 0x00600000, PPC_SPE); ////
+GEN_SPE(evcmpltu,       evcmplts,      0x19, 0x08, 0x00600000, PPC_SPE); ////
+GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
+
+static inline void gen_evsel (DisasContext *ctx)
+{
+    if (unlikely(!ctx->spe_enabled)) {
+        RET_EXCP(ctx, EXCP_NO_SPE, 0);
+        return;
+    }
+    gen_op_load_crf_T0(ctx->opcode & 0x7);
+    gen_op_load_gpr64_T0(rA(ctx->opcode));
+    gen_op_load_gpr64_T1(rB(ctx->opcode));
+    gen_op_evsel();
+    gen_op_store_T0_gpr64(rD(ctx->opcode));
+}
+
+GEN_HANDLER(evsel0, 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
+{
+    gen_evsel(ctx);
+}
+GEN_HANDLER(evsel1, 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
+{
+    gen_evsel(ctx);
+}
+GEN_HANDLER(evsel2, 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
+{
+    gen_evsel(ctx);
+}
+GEN_HANDLER(evsel3, 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
+{
+    gen_evsel(ctx);
+}
+
+/* Load and stores */
+#if defined(TARGET_PPC64)
+/* In that case, we already have 64 bits load & stores
+ * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
+ */
+#if defined(CONFIG_USER_ONLY)
+#define gen_op_spe_ldd_raw gen_op_ld_raw
+#define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
+#define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
+#define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
+#define gen_op_spe_stdd_raw gen_op_ld_raw
+#define gen_op_spe_stdd_64_raw gen_op_std_64_raw
+#define gen_op_spe_stdd_le_raw gen_op_std_le_raw
+#define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
+#else /* defined(CONFIG_USER_ONLY) */
+#define gen_op_spe_ldd_kernel gen_op_ld_kernel
+#define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
+#define gen_op_spe_ldd_le_kernel gen_op_ld_kernel
+#define gen_op_spe_ldd_le_64_kernel gen_op_ld_64_kernel
+#define gen_op_spe_ldd_user gen_op_ld_user
+#define gen_op_spe_ldd_64_user gen_op_ld_64_user
+#define gen_op_spe_ldd_le_user gen_op_ld_le_user
+#define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
+#define gen_op_spe_stdd_kernel gen_op_std_kernel
+#define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
+#define gen_op_spe_stdd_le_kernel gen_op_std_kernel
+#define gen_op_spe_stdd_le_64_kernel gen_op_std_64_kernel
+#define gen_op_spe_stdd_user gen_op_std_user
+#define gen_op_spe_stdd_64_user gen_op_std_64_user
+#define gen_op_spe_stdd_le_user gen_op_std_le_user
+#define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
+#endif /* defined(CONFIG_USER_ONLY) */
+#endif /* defined(TARGET_PPC64) */
+GEN_SPEOP_LDST(dd, 3);
+GEN_SPEOP_LDST(dw, 3);
+GEN_SPEOP_LDST(dh, 3);
+GEN_SPEOP_LDST(whe, 2);
+GEN_SPEOP_LD(whou, 2);
+GEN_SPEOP_LD(whos, 2);
+GEN_SPEOP_ST(who, 2);
+
+#if defined(TARGET_PPC64)
+/* In that case, spe_stwwo is equivalent to stw */
+#if defined(CONFIG_USER_ONLY)
+#define gen_op_spe_stwwo_raw gen_op_stw_raw
+#define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
+#define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
+#define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
+#else
+#define gen_op_spe_stwwo_user gen_op_stw_user
+#define gen_op_spe_stwwo_le_user gen_op_stw_le_user
+#define gen_op_spe_stwwo_64_user gen_op_stw_64_user
+#define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
+#define gen_op_spe_stwwo_kernel gen_op_stw_kernel
+#define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
+#define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
+#define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
+#endif
+#endif
+#define _GEN_OP_SPE_STWWE(suffix)                                             \
+static inline void gen_op_spe_stwwe_##suffix (void)                           \
+{                                                                             \
+    gen_op_srli32_T1_64();                                                    \
+    gen_op_spe_stwwo_##suffix();                                              \
+}
+#define _GEN_OP_SPE_STWWE_LE(suffix)                                          \
+static inline void gen_op_spe_stwwe_le_##suffix (void)                        \
+{                                                                             \
+    gen_op_srli32_T1_64();                                                    \
+    gen_op_spe_stwwo_le_##suffix();                                           \
+}
+#if defined(TARGET_PPC64)
+#define GEN_OP_SPE_STWWE(suffix)                                              \
+_GEN_OP_SPE_STWWE(suffix);                                                    \
+_GEN_OP_SPE_STWWE_LE(suffix);                                                 \
+static inline void gen_op_spe_stwwe_64_##suffix (void)                        \
+{                                                                             \
+    gen_op_srli32_T1_64();                                                    \
+    gen_op_spe_stwwo_64_##suffix();                                           \
+}                                                                             \
+static inline void gen_op_spe_stwwe_le_64_##suffix (void)                     \
+{                                                                             \
+    gen_op_srli32_T1_64();                                                    \
+    gen_op_spe_stwwo_le_64_##suffix();                                        \
+}
+#else
+#define GEN_OP_SPE_STWWE(suffix)                                              \
+_GEN_OP_SPE_STWWE(suffix);                                                    \
+_GEN_OP_SPE_STWWE_LE(suffix)
+#endif
+#if defined(CONFIG_USER_ONLY)
+GEN_OP_SPE_STWWE(raw);
+#else /* defined(CONFIG_USER_ONLY) */
+GEN_OP_SPE_STWWE(kernel);
+GEN_OP_SPE_STWWE(user);
+#endif /* defined(CONFIG_USER_ONLY) */
+GEN_SPEOP_ST(wwe, 2);
+GEN_SPEOP_ST(wwo, 2);
+
+#define GEN_SPE_LDSPLAT(name, op, suffix)                                     \
+static inline void gen_op_spe_l##name##_##suffix (void)                       \
+{                                                                             \
+    gen_op_##op##_##suffix();                                                 \
+    gen_op_splatw_T1_64();                                                    \
+}
+
+#define GEN_OP_SPE_LHE(suffix)                                                \
+static inline void gen_op_spe_lhe_##suffix (void)                             \
+{                                                                             \
+    gen_op_spe_lh_##suffix();                                                 \
+    gen_op_sli16_T1_64();                                                     \
+}
+
+#define GEN_OP_SPE_LHX(suffix)                                                \
+static inline void gen_op_spe_lhx_##suffix (void)                             \
+{                                                                             \
+    gen_op_spe_lh_##suffix();                                                 \
+    gen_op_extsh_T1_64();                                                     \
+}
+
+#if defined(CONFIG_USER_ONLY)
+GEN_OP_SPE_LHE(raw);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
+GEN_OP_SPE_LHE(le_raw);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
+GEN_OP_SPE_LHX(raw);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
+GEN_OP_SPE_LHX(le_raw);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
+#if defined(TARGET_PPC64)
+GEN_OP_SPE_LHE(64_raw);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
+GEN_OP_SPE_LHE(le_64_raw);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
+GEN_OP_SPE_LHX(64_raw);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
+GEN_OP_SPE_LHX(le_64_raw);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
+#endif
+#else
+GEN_OP_SPE_LHE(kernel);
+GEN_OP_SPE_LHE(user);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
+GEN_OP_SPE_LHE(le_kernel);
+GEN_OP_SPE_LHE(le_user);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
+GEN_OP_SPE_LHX(kernel);
+GEN_OP_SPE_LHX(user);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
+GEN_OP_SPE_LHX(le_kernel);
+GEN_OP_SPE_LHX(le_user);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
+#if defined(TARGET_PPC64)
+GEN_OP_SPE_LHE(64_kernel);
+GEN_OP_SPE_LHE(64_user);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
+GEN_OP_SPE_LHE(le_64_kernel);
+GEN_OP_SPE_LHE(le_64_user);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
+GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
+GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
+GEN_OP_SPE_LHX(64_kernel);
+GEN_OP_SPE_LHX(64_user);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
+GEN_OP_SPE_LHX(le_64_kernel);
+GEN_OP_SPE_LHX(le_64_user);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
+GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
+#endif
+#endif
+GEN_SPEOP_LD(hhesplat, 1);
+GEN_SPEOP_LD(hhousplat, 1);
+GEN_SPEOP_LD(hhossplat, 1);
+GEN_SPEOP_LD(wwsplat, 2);
+GEN_SPEOP_LD(whsplat, 2);
+
+GEN_SPE(evlddx,         evldd,         0x00, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evldwx,         evldw,         0x01, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evldhx,         evldh,         0x02, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlhhesplatx,   evlhhesplat,   0x04, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlhhousplatx,  evlhhousplat,  0x06, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlhhossplatx,  evlhhossplat,  0x07, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlwhex,        evlwhe,        0x08, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlwhoux,       evlwhou,       0x0A, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlwhosx,       evlwhos,       0x0B, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlwwsplatx,    evlwwsplat,    0x0C, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evlwhsplatx,    evlwhsplat,    0x0E, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstddx,        evstdd,        0x10, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstdwx,        evstdw,        0x11, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstdhx,        evstdh,        0x12, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstwhex,       evstwhe,       0x18, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstwhox,       evstwho,       0x1A, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstwwex,       evstwwe,       0x1C, 0x0C, 0x00000000, PPC_SPE); //
+GEN_SPE(evstwwox,       evstwwo,       0x1E, 0x0C, 0x00000000, PPC_SPE); //
+
+/* Multiply and add - TODO */
+#if 0
+GEN_SPE(speundef,       evmhessf,      0x01, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossf,      0x03, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumi,       evmhesmi,      0x04, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmf,      0x05, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumi,       evmhosmi,      0x06, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmf,      0x07, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfa,     0x11, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfa,     0x13, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumia,      evmhesmia,     0x14, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfa,     0x15, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumia,      evmhosmia,     0x16, 0x10, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfa,     0x17, 0x10, 0x00000000, PPC_SPE);
+
+GEN_SPE(speundef,       evmwhssf,      0x03, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumi,       speundef,      0x04, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwhumi,       evmwhsmi,      0x06, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhsmf,      0x07, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssf,       0x09, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumi,        evmwsmi,       0x0C, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmf,       0x0D, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhssfa,     0x13, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumia,      speundef,      0x14, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwhumia,      evmwhsmia,     0x16, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwhsmfa,     0x17, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfa,      0x19, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumia,       evmwsmia,      0x1C, 0x11, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfa,      0x1D, 0x11, 0x00000000, PPC_SPE);
+
+GEN_SPE(evadduiaaw,     evaddsiaaw,    0x00, 0x13, 0x0000F800, PPC_SPE);
+GEN_SPE(evsubfusiaaw,   evsubfssiaaw,  0x01, 0x13, 0x0000F800, PPC_SPE);
+GEN_SPE(evaddumiaaw,    evaddsmiaaw,   0x04, 0x13, 0x0000F800, PPC_SPE);
+GEN_SPE(evsubfumiaaw,   evsubfsmiaaw,  0x05, 0x13, 0x0000F800, PPC_SPE);
+GEN_SPE(evdivws,        evdivwu,       0x06, 0x13, 0x00000000, PPC_SPE);
+GEN_SPE(evmra,          speundef,      0x07, 0x13, 0x0000F800, PPC_SPE);
+
+GEN_SPE(evmheusiaaw,    evmhessiaaw,   0x00, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfaaw,   0x01, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(evmhousiaaw,    evmhossiaaw,   0x02, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfaaw,   0x03, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumiaaw,    evmhesmiaaw,   0x04, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfaaw,   0x05, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumiaaw,    evmhosmiaaw,   0x06, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfaaw,   0x07, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(evmhegumiaa,    evmhegsmiaa,   0x14, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhegsmfaa,   0x15, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(evmhogumiaa,    evmhogsmiaa,   0x16, 0x14, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhogsmfaa,   0x17, 0x14, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmwlusiaaw,    evmwlssiaaw,   0x00, 0x15, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumiaaw,    evmwlsmiaaw,   0x04, 0x15, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfaa,     0x09, 0x15, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumiaa,      evmwsmiaa,     0x0C, 0x15, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfaa,     0x0D, 0x15, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmheusianw,    evmhessianw,   0x00, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhessfanw,   0x01, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(evmhousianw,    evmhossianw,   0x02, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhossfanw,   0x03, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(evmheumianw,    evmhesmianw,   0x04, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhesmfanw,   0x05, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(evmhoumianw,    evmhosmianw,   0x06, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhosmfanw,   0x07, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(evmhegumian,    evmhegsmian,   0x14, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhegsmfan,   0x15, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(evmhigumian,    evmhigsmian,   0x16, 0x16, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmhogsmfan,   0x17, 0x16, 0x00000000, PPC_SPE);
+
+GEN_SPE(evmwlusianw,    evmwlssianw,   0x00, 0x17, 0x00000000, PPC_SPE);
+GEN_SPE(evmwlumianw,    evmwlsmianw,   0x04, 0x17, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwssfan,     0x09, 0x17, 0x00000000, PPC_SPE);
+GEN_SPE(evmwumian,      evmwsmian,     0x0C, 0x17, 0x00000000, PPC_SPE);
+GEN_SPE(speundef,       evmwsmfan,     0x0D, 0x17, 0x00000000, PPC_SPE);
+#endif
+
+/***                      SPE floating-point extension                     ***/
+#define GEN_SPEFPUOP_CONV(name)                                               \
+static inline void gen_##name (DisasContext *ctx)                             \
+{                                                                             \
+    gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
+    gen_op_##name();                                                          \
+    gen_op_store_T0_gpr64(rD(ctx->opcode));                                   \
+}
+
+/* Single precision floating-point vectors operations */
+/* Arithmetic */
+GEN_SPEOP_ARITH2(evfsadd);
+GEN_SPEOP_ARITH2(evfssub);
+GEN_SPEOP_ARITH2(evfsmul);
+GEN_SPEOP_ARITH2(evfsdiv);
+GEN_SPEOP_ARITH1(evfsabs);
+GEN_SPEOP_ARITH1(evfsnabs);
+GEN_SPEOP_ARITH1(evfsneg);
+/* Conversion */
+GEN_SPEFPUOP_CONV(evfscfui);
+GEN_SPEFPUOP_CONV(evfscfsi);
+GEN_SPEFPUOP_CONV(evfscfuf);
+GEN_SPEFPUOP_CONV(evfscfsf);
+GEN_SPEFPUOP_CONV(evfsctui);
+GEN_SPEFPUOP_CONV(evfsctsi);
+GEN_SPEFPUOP_CONV(evfsctuf);
+GEN_SPEFPUOP_CONV(evfsctsf);
+GEN_SPEFPUOP_CONV(evfsctuiz);
+GEN_SPEFPUOP_CONV(evfsctsiz);
+/* Comparison */
+GEN_SPEOP_COMP(evfscmpgt);
+GEN_SPEOP_COMP(evfscmplt);
+GEN_SPEOP_COMP(evfscmpeq);
+GEN_SPEOP_COMP(evfststgt);
+GEN_SPEOP_COMP(evfststlt);
+GEN_SPEOP_COMP(evfststeq);
+
+/* Opcodes definitions */
+GEN_SPE(evfsadd,        evfssub,       0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(evfsabs,        evfsnabs,      0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(evfsneg,        speundef,      0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(evfsmul,        evfsdiv,       0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(evfscmpgt,      evfscmplt,     0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(evfscmpeq,      speundef,      0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(evfscfui,       evfscfsi,      0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfscfuf,       evfscfsf,      0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfsctui,       evfsctsi,      0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfsctuf,       evfsctsf,      0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfsctuiz,      speundef,      0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfsctsiz,      speundef,      0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(evfststgt,      evfststlt,     0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(evfststeq,      speundef,      0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
+
+/* Single precision floating-point operations */
+/* Arithmetic */
+GEN_SPEOP_ARITH2(efsadd);
+GEN_SPEOP_ARITH2(efssub);
+GEN_SPEOP_ARITH2(efsmul);
+GEN_SPEOP_ARITH2(efsdiv);
+GEN_SPEOP_ARITH1(efsabs);
+GEN_SPEOP_ARITH1(efsnabs);
+GEN_SPEOP_ARITH1(efsneg);
+/* Conversion */
+GEN_SPEFPUOP_CONV(efscfui);
+GEN_SPEFPUOP_CONV(efscfsi);
+GEN_SPEFPUOP_CONV(efscfuf);
+GEN_SPEFPUOP_CONV(efscfsf);
+GEN_SPEFPUOP_CONV(efsctui);
+GEN_SPEFPUOP_CONV(efsctsi);
+GEN_SPEFPUOP_CONV(efsctuf);
+GEN_SPEFPUOP_CONV(efsctsf);
+GEN_SPEFPUOP_CONV(efsctuiz);
+GEN_SPEFPUOP_CONV(efsctsiz);
+GEN_SPEFPUOP_CONV(efscfd);
+/* Comparison */
+GEN_SPEOP_COMP(efscmpgt);
+GEN_SPEOP_COMP(efscmplt);
+GEN_SPEOP_COMP(efscmpeq);
+GEN_SPEOP_COMP(efststgt);
+GEN_SPEOP_COMP(efststlt);
+GEN_SPEOP_COMP(efststeq);
+
+/* Opcodes definitions */
+GEN_SPE(efsadd,         efssub,        0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(efsabs,         efsnabs,       0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(efsneg,         speundef,      0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(efsmul,         efsdiv,        0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(efscmpgt,       efscmplt,      0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efscmpeq,       efscfd,        0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efscfui,        efscfsi,       0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efscfuf,        efscfsf,       0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efsctui,        efsctsi,       0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efsctuf,        efsctsf,       0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efsctuiz,       efsctsiz,      0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efststgt,       efststlt,      0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efststeq,       speundef,      0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
+
+/* Double precision floating-point operations */
+/* Arithmetic */
+GEN_SPEOP_ARITH2(efdadd);
+GEN_SPEOP_ARITH2(efdsub);
+GEN_SPEOP_ARITH2(efdmul);
+GEN_SPEOP_ARITH2(efddiv);
+GEN_SPEOP_ARITH1(efdabs);
+GEN_SPEOP_ARITH1(efdnabs);
+GEN_SPEOP_ARITH1(efdneg);
+/* Conversion */
+
+GEN_SPEFPUOP_CONV(efdcfui);
+GEN_SPEFPUOP_CONV(efdcfsi);
+GEN_SPEFPUOP_CONV(efdcfuf);
+GEN_SPEFPUOP_CONV(efdcfsf);
+GEN_SPEFPUOP_CONV(efdctui);
+GEN_SPEFPUOP_CONV(efdctsi);
+GEN_SPEFPUOP_CONV(efdctuf);
+GEN_SPEFPUOP_CONV(efdctsf);
+GEN_SPEFPUOP_CONV(efdctuiz);
+GEN_SPEFPUOP_CONV(efdctsiz);
+GEN_SPEFPUOP_CONV(efdcfs);
+GEN_SPEFPUOP_CONV(efdcfuid);
+GEN_SPEFPUOP_CONV(efdcfsid);
+GEN_SPEFPUOP_CONV(efdctuidz);
+GEN_SPEFPUOP_CONV(efdctsidz);
+/* Comparison */
+GEN_SPEOP_COMP(efdcmpgt);
+GEN_SPEOP_COMP(efdcmplt);
+GEN_SPEOP_COMP(efdcmpeq);
+GEN_SPEOP_COMP(efdtstgt);
+GEN_SPEOP_COMP(efdtstlt);
+GEN_SPEOP_COMP(efdtsteq);
+
+/* Opcodes definitions */
+GEN_SPE(efdadd,         efdsub,        0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(efdcfuid,       efdcfsid,      0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdabs,         efdnabs,       0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(efdneg,         speundef,      0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
+GEN_SPE(efdmul,         efddiv,        0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
+GEN_SPE(efdctuidz,      efdctsidz,     0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdcmpgt,       efdcmplt,      0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efdcmpeq,       efdcfs,        0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efdcfui,        efdcfsi,       0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdcfuf,        efdcfsf,       0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdctui,        efdctsi,       0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdctuf,        efdctsf,       0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdctuiz,       speundef,      0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdctsiz,       speundef,      0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
+GEN_SPE(efdtstgt,       efdtstlt,      0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efdtsteq,       speundef,      0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
+#endif
+
 /* End opcode list */
 GEN_OPCODE_MARK(end);
 
@@ -2439,50 +5576,70 @@
 
 /*****************************************************************************/
 /* Misc PowerPC helpers */
+static inline uint32_t load_xer (CPUState *env)
+{
+    return (xer_so << XER_SO) |
+        (xer_ov << XER_OV) |
+        (xer_ca << XER_CA) |
+        (xer_bc << XER_BC) |
+        (xer_cmp << XER_CMP);
+}
+
 void cpu_dump_state(CPUState *env, FILE *f, 
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                     int flags)
 {
 #if defined(TARGET_PPC64) || 1
 #define FILL ""
-#define REGX "%016" PRIx64
 #define RGPL  4
 #define RFPL  4
 #else
 #define FILL "        "
-#define REGX "%08" PRIx64
 #define RGPL  8
 #define RFPL  4
 #endif
 
     int i;
 
-    cpu_fprintf(f, "NIP " REGX " LR " REGX " CTR " REGX "\n",
+    cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX "\n",
                 env->nip, env->lr, env->ctr);
-    cpu_fprintf(f, "MSR " REGX FILL " XER %08x      TB %08x %08x DECR %08x\n",
-                do_load_msr(env), do_load_xer(env), cpu_ppc_load_tbu(env),
-                cpu_ppc_load_tbl(env), cpu_ppc_load_decr(env));
-        for (i = 0; i < 32; i++) {
+    cpu_fprintf(f, "MSR " REGX FILL " XER %08x      "
+#if !defined(NO_TIMER_DUMP)
+                "TB %08x %08x "
+#if !defined(CONFIG_USER_ONLY)
+                "DECR %08x"
+#endif
+#endif
+                "\n",
+                do_load_msr(env), load_xer(env)
+#if !defined(NO_TIMER_DUMP)
+                , cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
+#if !defined(CONFIG_USER_ONLY)
+                , cpu_ppc_load_decr(env)
+#endif
+#endif
+                );
+    for (i = 0; i < 32; i++) {
         if ((i & (RGPL - 1)) == 0)
             cpu_fprintf(f, "GPR%02d", i);
         cpu_fprintf(f, " " REGX, env->gpr[i]);
         if ((i & (RGPL - 1)) == (RGPL - 1))
             cpu_fprintf(f, "\n");
-        }
+    }
     cpu_fprintf(f, "CR ");
-        for (i = 0; i < 8; i++)
+    for (i = 0; i < 8; i++)
         cpu_fprintf(f, "%01x", env->crf[i]);
     cpu_fprintf(f, "  [");
-        for (i = 0; i < 8; i++) {
-            char a = '-';
-            if (env->crf[i] & 0x08)
-                a = 'L';
-            else if (env->crf[i] & 0x04)
-                a = 'G';
-            else if (env->crf[i] & 0x02)
-                a = 'E';
+    for (i = 0; i < 8; i++) {
+        char a = '-';
+        if (env->crf[i] & 0x08)
+            a = 'L';
+        else if (env->crf[i] & 0x04)
+            a = 'G';
+        else if (env->crf[i] & 0x02)
+            a = 'E';
         cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
-        }
+    }
     cpu_fprintf(f, " ]             " FILL "RES " REGX "\n", env->reserve);
     for (i = 0; i < 32; i++) {
         if ((i & (RFPL - 1)) == 0)
@@ -2495,15 +5652,62 @@
                 "SDR1 " REGX "\n",
                 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
 
-#undef REGX
 #undef RGPL
 #undef RFPL
 #undef FILL
 }
 
+void cpu_dump_statistics (CPUState *env, FILE*f,
+                          int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+                          int flags)
+{
+#if defined(DO_PPC_STATISTICS)
+    opc_handler_t **t1, **t2, **t3, *handler;
+    int op1, op2, op3;
+
+    t1 = env->opcodes;
+    for (op1 = 0; op1 < 64; op1++) {
+        handler = t1[op1];
+        if (is_indirect_opcode(handler)) {
+            t2 = ind_table(handler);
+            for (op2 = 0; op2 < 32; op2++) {
+                handler = t2[op2];
+                if (is_indirect_opcode(handler)) {
+                    t3 = ind_table(handler);
+                    for (op3 = 0; op3 < 32; op3++) {
+                        handler = t3[op3];
+                        if (handler->count == 0)
+                            continue;
+                        cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
+                                    "%016llx %lld\n",
+                                    op1, op2, op3, op1, (op3 << 5) | op2,
+                                    handler->oname,
+                                    handler->count, handler->count);
+                    }
+                } else {
+                    if (handler->count == 0)
+                        continue;
+                    cpu_fprintf(f, "%02x %02x    (%02x %04d) %16s: "
+                                "%016llx %lld\n",
+                                op1, op2, op1, op2, handler->oname,
+                                handler->count, handler->count);
+                }
+            }
+        } else {
+            if (handler->count == 0)
+                continue;
+            cpu_fprintf(f, "%02x       (%02x     ) %16s: %016llx %lld\n",
+                        op1, op1, handler->oname,
+                        handler->count, handler->count);
+        }
+    }
+#endif
+}
+
 /*****************************************************************************/
-int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
-                                    int search_pc)
+static inline int gen_intermediate_code_internal (CPUState *env,
+                                                  TranslationBlock *tb,
+                                                  int search_pc)
 {
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
@@ -2522,11 +5726,23 @@
     ctx.spr_cb = env->spr_cb;
 #if defined(CONFIG_USER_ONLY)
     ctx.mem_idx = msr_le;
+#if defined(TARGET_PPC64)
+    ctx.mem_idx |= msr_sf << 1;
+#endif
 #else
     ctx.supervisor = 1 - msr_pr;
     ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le;
+#if defined(TARGET_PPC64)
+    ctx.mem_idx |= msr_sf << 2;
 #endif
+#endif
+#if defined(TARGET_PPC64)
+    ctx.sf_mode = msr_sf;
+#endif
     ctx.fpu_enabled = msr_fp;
+#if defined(TARGET_PPCEMB)
+    ctx.spe_enabled = msr_spe;
+#endif
     ctx.singlestep_enabled = env->singlestep_enabled;
 #if defined (DO_SINGLE_STEP) && 0
     /* Single step trace mode */
@@ -2534,16 +5750,16 @@
 #endif
     /* Set env in case of segfault during code fetch */
     while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
-        if (env->nb_breakpoints > 0) {
-            for(j = 0; j < env->nb_breakpoints; j++) {
+        if (unlikely(env->nb_breakpoints > 0)) {
+            for (j = 0; j < env->nb_breakpoints; j++) {
                 if (env->breakpoints[j] == ctx.nip) {
-                    gen_op_update_nip(ctx.nip); 
+                    gen_update_nip(&ctx, ctx.nip); 
                     gen_op_debug();
                     break;
                 }
             }
         }
-        if (search_pc) {
+        if (unlikely(search_pc)) {
             j = gen_opc_ptr - gen_opc_buf;
             if (lj < j) {
                 lj++;
@@ -2556,7 +5772,7 @@
 #if defined PPC_DEBUG_DISAS
         if (loglevel & CPU_LOG_TB_IN_ASM) {
             fprintf(logfile, "----------------\n");
-            fprintf(logfile, "nip=%08x super=%d ir=%d\n",
+            fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
                     ctx.nip, 1 - msr_pr, msr_ir);
         }
 #endif
@@ -2586,61 +5802,65 @@
             }
         }
         /* Is opcode *REALLY* valid ? */
-                if (handler->handler == &gen_invalid) {
-            if (loglevel > 0) {
-                    fprintf(logfile, "invalid/unsupported opcode: "
-                        "%02x - %02x - %02x (%08x) 0x%08x %d\n",
-                            opc1(ctx.opcode), opc2(ctx.opcode),
+        if (unlikely(handler->handler == &gen_invalid)) {
+            if (loglevel != 0) {
+                fprintf(logfile, "invalid/unsupported opcode: "
+                        "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
+                        opc1(ctx.opcode), opc2(ctx.opcode),
                         opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
             } else {
                 printf("invalid/unsupported opcode: "
-                       "%02x - %02x - %02x (%08x) 0x%08x %d\n",
+                       "%02x - %02x - %02x (%08x) 0x" ADDRX " %d\n",
                        opc1(ctx.opcode), opc2(ctx.opcode),
                        opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir);
             }
-                } else {
-            if ((ctx.opcode & handler->inval) != 0) {
-                if (loglevel > 0) {
+        } else {
+            if (unlikely((ctx.opcode & handler->inval) != 0)) {
+                if (loglevel != 0) {
                     fprintf(logfile, "invalid bits: %08x for opcode: "
-                            "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
+                            "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
                             ctx.opcode & handler->inval, opc1(ctx.opcode),
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
                 } else {
                     printf("invalid bits: %08x for opcode: "
-                           "%02x -%02x - %02x (0x%08x) (0x%08x)\n",
-                            ctx.opcode & handler->inval, opc1(ctx.opcode),
-                            opc2(ctx.opcode), opc3(ctx.opcode),
+                           "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
+                           ctx.opcode & handler->inval, opc1(ctx.opcode),
+                           opc2(ctx.opcode), opc3(ctx.opcode),
                            ctx.opcode, ctx.nip - 4);
-            }
+                }
                 RET_INVAL(ctxp);
                 break;
             }
         }
         (*(handler->handler))(&ctx);
+#if defined(DO_PPC_STATISTICS)
+        handler->count++;
+#endif
         /* Check trace mode exceptions */
-        if ((msr_be && ctx.exception == EXCP_BRANCH) ||
-            /* Check in single step trace mode
-             * we need to stop except if:
-             * - rfi, trap or syscall
-             * - first instruction of an exception handler
-             */
-            (msr_se && (ctx.nip < 0x100 ||
-                        ctx.nip > 0xF00 ||
-                        (ctx.nip & 0xFC) != 0x04) &&
-             ctx.exception != EXCP_SYSCALL &&
-             ctx.exception != EXCP_SYSCALL_USER &&
-             ctx.exception != EXCP_TRAP)) {
+#if 0 // XXX: buggy on embedded PowerPC
+        if (unlikely((msr_be && ctx.exception == EXCP_BRANCH) ||
+                     /* Check in single step trace mode
+                      * we need to stop except if:
+                      * - rfi, trap or syscall
+                      * - first instruction of an exception handler
+                      */
+                     (msr_se && (ctx.nip < 0x100 ||
+                                 ctx.nip > 0xF00 ||
+                                 (ctx.nip & 0xFC) != 0x04) &&
+                      ctx.exception != EXCP_SYSCALL &&
+                      ctx.exception != EXCP_SYSCALL_USER &&
+                      ctx.exception != EXCP_TRAP))) {
             RET_EXCP(ctxp, EXCP_TRACE, 0);
         }
-
+#endif
         /* if we reach a page boundary or are single stepping, stop
          * generation
          */
-        if (((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
-            (env->singlestep_enabled)) {
+        if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
+                     (env->singlestep_enabled))) {
             break;
-    }
+        }
 #if defined (DO_SINGLE_STEP)
         break;
 #endif
@@ -2648,39 +5868,30 @@
     if (ctx.exception == EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
     } else if (ctx.exception != EXCP_BRANCH) {
-        gen_op_set_T0(0);
+        gen_op_reset_T0();
+        /* Generate the return instruction */
+        gen_op_exit_tb();
     }
-#if 1
-    /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
-     *              do bad business and then qemu crashes !
-     */
-    gen_op_set_T0(0);
-#endif
-    /* Generate the return instruction */
-    gen_op_exit_tb();
     *gen_opc_ptr = INDEX_op_end;
-    if (search_pc) {
+    if (unlikely(search_pc)) {
         j = gen_opc_ptr - gen_opc_buf;
         lj++;
         while (lj <= j)
             gen_opc_instr_start[lj++] = 0;
         tb->size = 0;
-#if 0
-        if (loglevel > 0) {
-            page_dump(logfile);
-        }
-#endif
     } else {
         tb->size = ctx.nip - pc_start;
     }
-#ifdef DEBUG_DISAS
+#if defined(DEBUG_DISAS)
     if (loglevel & CPU_LOG_TB_CPU) {
         fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
         cpu_dump_state(env, logfile, fprintf, 0);
     }
     if (loglevel & CPU_LOG_TB_IN_ASM) {
+        int flags;
+        flags = msr_le;
         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
-	target_disas(logfile, pc_start, ctx.nip - pc_start, msr_le);
+        target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
         fprintf(logfile, "\n");
     }
     if (loglevel & CPU_LOG_TB_OP) {

Modified: trunk/src/host/qemu-neo1973/target-ppc/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-ppc/translate_init.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-ppc/translate_init.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  *  PowerPC CPU initialization for qemu.
  * 
- *  Copyright (c) 2003-2005 Jocelyn Mayer
+ *  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
@@ -25,21 +25,47 @@
 
 //#define PPC_DUMP_CPU
 //#define PPC_DEBUG_SPR
+//#define PPC_DEBUG_IRQ
 
 struct ppc_def_t {
     const unsigned char *name;
     uint32_t pvr;
     uint32_t pvr_mask;
-    uint32_t insns_flags;
+    uint64_t insns_flags;
     uint32_t flags;
     uint64_t msr_mask;
 };
 
+/* For user-mode emulation, we don't emulate any IRQ controller */
+#if defined(CONFIG_USER_ONLY)
+#define PPC_IRQ_INIT_FN(name)                                         \
+static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \
+{                                                                     \
+}
+#else
+#define PPC_IRQ_INIT_FN(name)                                         \
+void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
+#endif
+PPC_IRQ_INIT_FN(405);
+PPC_IRQ_INIT_FN(6xx);
+PPC_IRQ_INIT_FN(970);
+
 /* Generic callbacks:
  * do nothing but store/retrieve spr value
  */
+#ifdef PPC_DUMP_SPR_ACCESSES
 static void spr_read_generic (void *opaque, int sprn)
 {
+    gen_op_load_dump_spr(sprn);
+}
+
+static void spr_write_generic (void *opaque, int sprn)
+{
+    gen_op_store_dump_spr(sprn);
+}
+#else
+static void spr_read_generic (void *opaque, int sprn)
+{
     gen_op_load_spr(sprn);
 }
 
@@ -47,8 +73,16 @@
 {
     gen_op_store_spr(sprn);
 }
+#endif
 
-/* SPR common to all PPC */
+#if !defined(CONFIG_USER_ONLY)
+static void spr_write_clear (void *opaque, int sprn)
+{
+    gen_op_mask_spr(sprn);
+}
+#endif
+
+/* SPR common to all PowerPC */
 /* XER */
 static void spr_read_xer (void *opaque, int sprn)
 {
@@ -93,8 +127,9 @@
     gen_op_load_spr(sprn + 0x10);
 }
 
-/* SPR common to all non-embedded PPC (ie not 4xx) */
+/* SPR common to all non-embedded PowerPC */
 /* DECR */
+#if !defined(CONFIG_USER_ONLY)
 static void spr_read_decr (void *opaque, int sprn)
 {
     gen_op_load_decr();
@@ -104,29 +139,33 @@
 {
     gen_op_store_decr();
 }
+#endif
 
-/* SPR common to all non-embedded PPC, except 601 */
+/* SPR common to all non-embedded PowerPC, except 601 */
 /* Time base */
 static void spr_read_tbl (void *opaque, int sprn)
 {
     gen_op_load_tbl();
 }
 
-static void spr_write_tbl (void *opaque, int sprn)
+static void spr_read_tbu (void *opaque, int sprn)
 {
-    gen_op_store_tbl();
+    gen_op_load_tbu();
 }
 
-static void spr_read_tbu (void *opaque, int sprn)
+#if !defined(CONFIG_USER_ONLY)
+static void spr_write_tbl (void *opaque, int sprn)
 {
-    gen_op_load_tbu();
+    gen_op_store_tbl();
 }
 
 static void spr_write_tbu (void *opaque, int sprn)
 {
     gen_op_store_tbu();
 }
+#endif
 
+#if !defined(CONFIG_USER_ONLY)
 /* IBAT0U...IBAT0U */
 /* IBAT0L...IBAT7L */
 static void spr_read_ibat (void *opaque, int sprn)
@@ -229,11 +268,149 @@
     RET_STOP(ctx);
 }
 
+/* 64 bits PowerPC specific SPRs */
+/* ASR */
+#if defined(TARGET_PPC64)
+static void spr_read_asr (void *opaque, int sprn)
+{
+    gen_op_load_asr();
+}
+
+static void spr_write_asr (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_asr();
+    RET_STOP(ctx);
+}
+#endif
+#endif /* !defined(CONFIG_USER_ONLY) */
+
+/* PowerPC 601 specific registers */
+/* RTC */
+static void spr_read_601_rtcl (void *opaque, int sprn)
+{
+    gen_op_load_601_rtcl();
+}
+
+static void spr_read_601_rtcu (void *opaque, int sprn)
+{
+    gen_op_load_601_rtcu();
+}
+
+#if !defined(CONFIG_USER_ONLY)
+static void spr_write_601_rtcu (void *opaque, int sprn)
+{
+    gen_op_store_601_rtcu();
+}
+
+static void spr_write_601_rtcl (void *opaque, int sprn)
+{
+    gen_op_store_601_rtcl();
+}
+#endif
+
+/* Unified bats */
+#if !defined(CONFIG_USER_ONLY)
+static void spr_read_601_ubat (void *opaque, int sprn)
+{
+    gen_op_load_601_bat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
+}
+
+static void spr_write_601_ubatu (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2);
+    RET_STOP(ctx);
+}
+
+static void spr_write_601_ubatl (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2);
+    RET_STOP(ctx);
+}
+#endif
+
+/* PowerPC 40x specific registers */
+#if !defined(CONFIG_USER_ONLY)
+static void spr_read_40x_pit (void *opaque, int sprn)
+{
+    gen_op_load_40x_pit();
+}
+
+static void spr_write_40x_pit (void *opaque, int sprn)
+{
+    gen_op_store_40x_pit();
+}
+
+static void spr_write_40x_dbcr0 (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_40x_dbcr0();
+    /* We must stop translation as we may have rebooted */
+    RET_STOP(ctx);
+}
+
+static void spr_write_40x_sler (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_40x_sler();
+    /* We must stop the translation as we may have changed
+     * some regions endianness
+     */
+    RET_STOP(ctx);
+}
+
+static void spr_write_booke_tcr (void *opaque, int sprn)
+{
+    gen_op_store_booke_tcr();
+}
+
+static void spr_write_booke_tsr (void *opaque, int sprn)
+{
+    gen_op_store_booke_tsr();
+}
+#endif
+
+/* PowerPC 403 specific registers */
+/* PBL1 / PBU1 / PBL2 / PBU2 */
+#if !defined(CONFIG_USER_ONLY)
+static void spr_read_403_pbr (void *opaque, int sprn)
+{
+    gen_op_load_403_pb(sprn - SPR_403_PBL1);
+}
+
+static void spr_write_403_pbr (void *opaque, int sprn)
+{
+    DisasContext *ctx = opaque;
+
+    gen_op_store_403_pb(sprn - SPR_403_PBL1);
+    RET_STOP(ctx);
+}
+
 static void spr_write_pir (void *opaque, int sprn)
 {
     gen_op_store_pir();
 }
+#endif
 
+#if defined(CONFIG_USER_ONLY)
+#define spr_register(env, num, name, uea_read, uea_write,                     \
+                     oea_read, oea_write, initial_value)                      \
+do {                                                                          \
+     _spr_register(env, num, name, uea_read, uea_write, initial_value);       \
+} while (0)
+static inline void _spr_register (CPUPPCState *env, int num,
+                                  const unsigned char *name,
+                                  void (*uea_read)(void *opaque, int sprn),
+                                  void (*uea_write)(void *opaque, int sprn),
+                                  target_ulong initial_value)
+#else
 static inline void spr_register (CPUPPCState *env, int num,
                                  const unsigned char *name,
                                  void (*uea_read)(void *opaque, int sprn),
@@ -241,25 +418,30 @@
                                  void (*oea_read)(void *opaque, int sprn),
                                  void (*oea_write)(void *opaque, int sprn),
                                  target_ulong initial_value)
+#endif
 {
     ppc_spr_t *spr;
 
     spr = &env->spr_cb[num];
     if (spr->name != NULL ||env-> spr[num] != 0x00000000 ||
-        spr->uea_read != NULL || spr->uea_write != NULL ||
-        spr->oea_read != NULL || spr->oea_write != NULL) {
+#if !defined(CONFIG_USER_ONLY)
+        spr->oea_read != NULL || spr->oea_write != NULL ||
+#endif
+        spr->uea_read != NULL || spr->uea_write != NULL) {
         printf("Error: Trying to register SPR %d (%03x) twice !\n", num, num);
         exit(1);
     }
 #if defined(PPC_DEBUG_SPR)
-    printf("*** register spr %d (%03x) %s val %08" PRIx64 "\n", num, num, name,
-           (unsigned long long)initial_value);
+    printf("*** register spr %d (%03x) %s val " ADDRX "\n", num, num, name,
+           initial_value);
 #endif
     spr->name = name;
     spr->uea_read = uea_read;
     spr->uea_write = uea_write;
+#if !defined(CONFIG_USER_ONLY)
     spr->oea_read = oea_read;
     spr->oea_write = oea_write;
+#endif
     env->spr[num] = initial_value;
 }
 
@@ -493,6 +675,70 @@
                  0x00000000);
 }
 
+/* Softare table search registers */
+static void gen_6xx_7xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
+{
+    env->nb_tlb = nb_tlbs;
+    env->nb_ways = nb_ways;
+    env->id_tlbs = 1;
+    spr_register(env, SPR_DMISS, "DMISS",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_DCMP, "DCMP",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_HASH1, "HASH1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_HASH2, "HASH2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_IMISS, "IMISS",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_ICMP, "ICMP",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_RPA, "RPA",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR common to MPC755 and G2 */
+static void gen_spr_G2_755 (CPUPPCState *env)
+{
+    /* SGPRs */
+    spr_register(env, SPR_SPRG4, "SPRG4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_SPRG5, "SPRG5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_SPRG6, "SPRG6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_SPRG7, "SPRG7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* External access control */
+    /* XXX : not implemented */
+    spr_register(env, SPR_EAR, "EAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
 /* SPR common to all 7xx PowerPC implementations */
 static void gen_spr_7xx (CPUPPCState *env)
 {
@@ -513,6 +759,11 @@
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_L2CR, "L2CR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
     /* Performance monitors */
     /* XXX : not implemented */
     spr_register(env, SPR_MMCR0, "MMCR0",
@@ -669,7 +920,929 @@
                  0x00000000);
 }
 
-// XXX: TODO (64 bits PPC sprs)
+/* SPR specific to PowerPC 603 implementation */
+static void gen_spr_603 (CPUPPCState *env)
+{
+    /* External access control */
+    /* XXX : not implemented */
+    spr_register(env, SPR_EAR, "EAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC G2 implementation */
+static void gen_spr_G2 (CPUPPCState *env)
+{
+    /* Memory base address */
+    /* MBAR */
+    spr_register(env, SPR_MBAR, "MBAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* System version register */
+    /* SVR */
+    spr_register(env, SPR_SVR, "SVR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* Exception processing */
+    spr_register(env, SPR_BOOKE_CSRR0, "CSRR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_CSRR1, "CSRR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Breakpoints */
+    /* XXX : not implemented */
+    spr_register(env, SPR_DABR, "DABR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_DABR2, "DABR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_IABR, "IABR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_IABR2, "IABR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_IBCR, "IBCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_DBCR, "DBCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC 602 implementation */
+static void gen_spr_602 (CPUPPCState *env)
+{
+    /* ESA registers */
+    /* XXX : not implemented */
+    spr_register(env, SPR_SER, "SER",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_SEBR, "SEBR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_ESASR, "ESASR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Floating point status */
+    /* XXX : not implemented */
+    spr_register(env, SPR_SP, "SP",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_LT, "LT",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Watchdog timer */
+    /* XXX : not implemented */
+    spr_register(env, SPR_TCR, "TCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Interrupt base */
+    spr_register(env, SPR_IBR, "IBR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC 601 implementation */
+static void gen_spr_601 (CPUPPCState *env)
+{
+    /* Multiplication/division register */
+    /* MQ */
+    spr_register(env, SPR_MQ, "MQ",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* RTC registers */
+    spr_register(env, SPR_601_RTCU, "RTCU",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 SPR_NOACCESS, &spr_write_601_rtcu,
+                 0x00000000);
+    spr_register(env, SPR_601_VRTCU, "RTCU",
+                 &spr_read_601_rtcu, SPR_NOACCESS,
+                 &spr_read_601_rtcu, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_601_RTCL, "RTCL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 SPR_NOACCESS, &spr_write_601_rtcl,
+                 0x00000000);
+    spr_register(env, SPR_601_VRTCL, "RTCL",
+                 &spr_read_601_rtcl, SPR_NOACCESS,
+                 &spr_read_601_rtcl, SPR_NOACCESS,
+                 0x00000000);
+    /* Timer */
+#if 0 /* ? */
+    spr_register(env, SPR_601_UDECR, "UDECR",
+                 &spr_read_decr, SPR_NOACCESS,
+                 &spr_read_decr, SPR_NOACCESS,
+                 0x00000000);
+#endif
+    /* External access control */
+    /* XXX : not implemented */
+    spr_register(env, SPR_EAR, "EAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    spr_register(env, SPR_IBAT0U, "IBAT0U",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatu,
+                 0x00000000);
+    spr_register(env, SPR_IBAT0L, "IBAT0L",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatl,
+                 0x00000000);
+    spr_register(env, SPR_IBAT1U, "IBAT1U",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatu,
+                 0x00000000);
+    spr_register(env, SPR_IBAT1L, "IBAT1L",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatl,
+                 0x00000000);
+    spr_register(env, SPR_IBAT2U, "IBAT2U",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatu,
+                 0x00000000);
+    spr_register(env, SPR_IBAT2L, "IBAT2L",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatl,
+                 0x00000000);
+    spr_register(env, SPR_IBAT3U, "IBAT3U",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatu,
+                 0x00000000);
+    spr_register(env, SPR_IBAT3L, "IBAT3L",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_601_ubat, &spr_write_601_ubatl,
+                 0x00000000);
+}
+
+/* PowerPC BookE SPR */
+static void gen_spr_BookE (CPUPPCState *env)
+{
+    /* Processor identification */
+    spr_register(env, SPR_BOOKE_PIR, "PIR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_pir,
+                 0x00000000);
+    /* Interrupt processing */
+    spr_register(env, SPR_BOOKE_CSRR0, "CSRR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_CSRR1, "CSRR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_DSRR1, "DSRR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Debug */
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_IAC1, "IAC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_IAC2, "IAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_IAC3, "IAC3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_IAC4, "IAC4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DAC1, "DAC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DAC2, "DAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DVC1, "DVC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DVC2, "DVC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DBCR0, "DBCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DBCR1, "DBCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DBCR2, "DBCR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DBSR, "DBSR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_DEAR, "DEAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_ESR, "ESR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVPR, "IVPR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Exception vectors */
+    spr_register(env, SPR_BOOKE_IVOR0, "IVOR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR1, "IVOR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR2, "IVOR2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR3, "IVOR3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR4, "IVOR4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR5, "IVOR5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR6, "IVOR6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR7, "IVOR7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR8, "IVOR8",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR9, "IVOR9",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR10, "IVOR10",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR11, "IVOR11",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR12, "IVOR12",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR13, "IVOR13",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR14, "IVOR14",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR15, "IVOR15",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR32, "IVOR32",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR33, "IVOR33",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR34, "IVOR34",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR35, "IVOR35",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR36, "IVOR36",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_IVOR37, "IVOR37",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_PID, "PID",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_TCR, "TCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_booke_tcr,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_TSR, "TSR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_booke_tsr,
+                 0x00000000);
+    /* Timer */
+    spr_register(env, SPR_DECR, "DECR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_decr, &spr_write_decr,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_DECAR, "DECAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 SPR_NOACCESS, &spr_write_generic,
+                 0x00000000);
+    /* SPRGs */
+    spr_register(env, SPR_USPRG0, "USPRG0",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_SPRG4, "SPRG4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG4, "USPRG4",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG5, "SPRG5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG5, "USPRG5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG6, "SPRG6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG6, "USPRG6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG7, "SPRG7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG7, "USPRG7",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+}
+
+/* FSL storage control registers */
+static void gen_spr_BookE_FSL (CPUPPCState *env)
+{
+    /* TLB assist registers */
+    spr_register(env, SPR_BOOKE_MAS0, "MAS0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS1, "MAS2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS2, "MAS3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS3, "MAS4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS4, "MAS5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS6, "MAS6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MAS7, "MAS7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    if (env->nb_pids > 1) {
+        spr_register(env, SPR_BOOKE_PID1, "PID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+    }
+    if (env->nb_pids > 2) {
+        spr_register(env, SPR_BOOKE_PID2, "PID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+    }
+    spr_register(env, SPR_BOOKE_MMUCFG, "MMUCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000); /* TOFIX */
+    spr_register(env, SPR_BOOKE_MMUCSR0, "MMUCSR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000); /* TOFIX */
+    switch (env->nb_ways) {
+    case 4:
+        spr_register(env, SPR_BOOKE_TLB3CFG, "TLB3CFG",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, SPR_NOACCESS,
+                     0x00000000); /* TOFIX */
+        /* Fallthru */
+    case 3:
+        spr_register(env, SPR_BOOKE_TLB2CFG, "TLB2CFG",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, SPR_NOACCESS,
+                     0x00000000); /* TOFIX */
+        /* Fallthru */
+    case 2:
+        spr_register(env, SPR_BOOKE_TLB1CFG, "TLB1CFG",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, SPR_NOACCESS,
+                     0x00000000); /* TOFIX */
+        /* Fallthru */
+    case 1:
+        spr_register(env, SPR_BOOKE_TLB0CFG, "TLB0CFG",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, SPR_NOACCESS,
+                     0x00000000); /* TOFIX */
+        /* Fallthru */
+    case 0:
+    default:
+        break;
+    }
+}
+
+/* SPR specific to PowerPC 440 implementation */
+static void gen_spr_440 (CPUPPCState *env)
+{
+    /* Cache control */
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DNV0, "DNV0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DNV1, "DNV1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DNV2, "DNV2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DNV3, "DNV3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DVT0, "DVT0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DVT1, "DVT1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DVT2, "DVT2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DVT3, "DVT3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DVLIM, "DVLIM",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_INV0, "INV0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_INV1, "INV1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_INV2, "INV2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_INV3, "INV3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_IVT0, "IVT0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_IVT1, "IVT1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_IVT2, "IVT2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_IVT3, "IVT3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_IVLIM, "IVLIM",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Cache debug */
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DCBTRH, "DCBTRH",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_DCBTRL, "DCBTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_ICBDR, "ICBDR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_ICBTRH, "ICBTRH",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_ICBTRL, "ICBTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_440_DBDR, "DBDR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Processor control */
+    spr_register(env, SPR_4xx_CCR0, "CCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_440_RSTCFG, "RSTCFG",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* Storage control */
+    spr_register(env, SPR_440_MMUCR, "MMUCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR shared between PowerPC 40x implementations */
+static void gen_spr_40x (CPUPPCState *env)
+{
+    /* Cache */
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DCCR, "DCCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DCWR, "DCWR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_ICCR, "ICCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_BOOKE_ICBDR, "ICBDR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
+    /* Bus access control */
+    spr_register(env, SPR_40x_SGR, "SGR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0xFFFFFFFF);
+    spr_register(env, SPR_40x_ZPR, "ZPR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* MMU */
+    spr_register(env, SPR_40x_PID, "PID",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Exception */
+    spr_register(env, SPR_40x_DEAR, "DEAR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_ESR, "ESR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_EVPR, "EVPR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_SRR2, "SRR2",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_SRR3, "SRR3",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Timers */
+    spr_register(env, SPR_40x_PIT, "PIT",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_40x_pit, &spr_write_40x_pit,
+                 0x00000000);
+    spr_register(env, SPR_40x_TCR, "TCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_booke_tcr,
+                 0x00000000);
+    spr_register(env, SPR_40x_TSR, "TSR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_booke_tsr,
+                 0x00000000);
+    /* Debug interface */
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DAC1, "DAC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_DAC2, "DAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DBCR0, "DBCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_40x_dbcr0,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DBSR, "DBSR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_clear,
+                 /* Last reset was system reset */
+                 0x00000300);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_IAC1, "IAC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_40x_IAC2, "IAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC 405 implementation */
+static void gen_spr_405 (CPUPPCState *env)
+{
+    spr_register(env, SPR_4xx_CCR0, "CCR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00700000);
+    /* Debug */
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_DBCR1, "DBCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_DVC1, "DVC1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_DVC2, "DVC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_IAC3, "IAC3",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_IAC4, "IAC4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Storage control */
+    spr_register(env, SPR_405_SLER, "SLER",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_40x_sler,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_405_SU0R, "SU0R",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* SPRG */
+    spr_register(env, SPR_USPRG0, "USPRG0",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG4, "SPRG4",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG4, "USPRG4",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG5, "SPRG5",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG5, "USPRG5",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG6, "SPRG6",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG6, "USPRG6",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_SPRG7, "SPRG7",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_USPRG7, "USPRG7",
+                 &spr_read_ureg, SPR_NOACCESS,
+                 &spr_read_ureg, SPR_NOACCESS,
+                 0x00000000);
+}
+
+/* SPR shared between PowerPC 401 & 403 implementations */
+static void gen_spr_401_403 (CPUPPCState *env)
+{
+    /* Time base */
+    spr_register(env, SPR_403_VTBL,  "TBL",
+                 &spr_read_tbl, SPR_NOACCESS,
+                 &spr_read_tbl, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_403_TBL,   "TBL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 SPR_NOACCESS, &spr_write_tbl,
+                 0x00000000);
+    spr_register(env, SPR_403_VTBU,  "TBU",
+                 &spr_read_tbu, SPR_NOACCESS,
+                 &spr_read_tbu, SPR_NOACCESS,
+                 0x00000000);
+    spr_register(env, SPR_403_TBU,   "TBU",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 SPR_NOACCESS, &spr_write_tbu,
+                 0x00000000);
+    /* Debug */
+    /* XXX: not implemented */
+    spr_register(env, SPR_403_CDBCR, "CDBCR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC 403 implementation */
+static void gen_spr_403 (CPUPPCState *env)
+{
+    /* MMU */
+    spr_register(env, SPR_403_PBL1,  "PBL1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_403_pbr, &spr_write_403_pbr,
+                 0x00000000);
+    spr_register(env, SPR_403_PBU1,  "PBU1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_403_pbr, &spr_write_403_pbr,
+                 0x00000000);
+    spr_register(env, SPR_403_PBL2,  "PBL2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_403_pbr, &spr_write_403_pbr,
+                 0x00000000);
+    spr_register(env, SPR_403_PBU2,  "PBU2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_403_pbr, &spr_write_403_pbr,
+                 0x00000000);
+    /* Debug */
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_DAC2, "DAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* XXX : not implemented */
+    spr_register(env, SPR_40x_IAC2, "IAC2",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+
+/* SPR specific to PowerPC compression coprocessor extension */
+#if defined (TODO)
+static void gen_spr_compress (CPUPPCState *env)
+{
+    spr_register(env, SPR_401_SKR, "SKR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+}
+#endif
+
+// XXX: TODO (64 bits PowerPC SPRs)
 /*
  * ASR => SPR 280 (64 bits)
  * FPECR => SPR 1022 (?)
@@ -691,32 +1864,241 @@
 
 static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
 {
+    env->reserve = -1;
     /* Default MMU definitions */
     env->nb_BATs = -1;
     env->nb_tlb = 0;
     env->nb_ways = 0;
     /* XXX: missing:
-     * 32 bits PPC:
+     * 32 bits PowerPC:
      * - MPC5xx(x)
      * - MPC8xx(x)
-     * - RCPU (MPC5xx)
+     * - RCPU (same as MPC5xx ?)
      */
     spr_register(env, SPR_PVR, "PVR",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
                  def->pvr);
-    switch (def->pvr & def->pvr_mask) {
-    case CPU_PPC_604:     /* PPC 604                       */
-    case CPU_PPC_604E:    /* PPC 604e                      */
-    case CPU_PPC_604R:    /* PPC 604r                      */
+    printf("%s: PVR %08x mask %08x => %08x\n", __func__,
+           def->pvr, def->pvr_mask, def->pvr & def->pvr_mask);
+    switch (def->pvr) {
+    /* Embedded PowerPC from IBM                           */
+    case CPU_PPC_401A1:   /* 401 A1 family                 */
+    case CPU_PPC_401B2:   /* 401 B2 family                 */
+    case CPU_PPC_401C2:   /* 401 C2 family                 */
+    case CPU_PPC_401D2:   /* 401 D2 family                 */
+    case CPU_PPC_401E2:   /* 401 E2 family                 */
+    case CPU_PPC_401F2:   /* 401 F2 family                 */
+    case CPU_PPC_401G2:   /* 401 G2 family                 */
+    case CPU_PPC_IOP480:  /* IOP 480 family                */
+    case CPU_PPC_COBRA:   /* IBM Processor for Network Resources */
         gen_spr_generic(env);
+        gen_spr_40x(env);
+        gen_spr_401_403(env);
+#if defined (TODO)
+        /* XXX: optional ? */
+        gen_spr_compress(env);
+#endif
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* XXX: TODO: allocate internal IRQ controller */
+        break;
+
+    case CPU_PPC_403GA:   /* 403 GA family                 */
+    case CPU_PPC_403GB:   /* 403 GB family                 */
+    case CPU_PPC_403GC:   /* 403 GC family                 */
+    case CPU_PPC_403GCX:  /* 403 GCX family                */
+        gen_spr_generic(env);
+        gen_spr_40x(env);
+        gen_spr_401_403(env);
+        gen_spr_403(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* XXX: TODO: allocate internal IRQ controller */
+        break;
+
+    case CPU_PPC_405CR:   /* 405 GP/CR family              */
+    case CPU_PPC_405EP:   /* 405 EP family                 */
+    case CPU_PPC_405GPR:  /* 405 GPR family                */
+    case CPU_PPC_405D2:   /* 405 D2 family                 */
+    case CPU_PPC_405D4:   /* 405 D4 family                 */
+        gen_spr_generic(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_40x(env);
+        gen_spr_405(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* Allocate hardware IRQ controller */
+        ppc405_irq_init(env);
+        break;
+
+    case CPU_PPC_NPE405H: /* NPe405 H family               */
+    case CPU_PPC_NPE405H2:
+    case CPU_PPC_NPE405L: /* Npe405 L family               */
+        gen_spr_generic(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_40x(env);
+        gen_spr_405(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* Allocate hardware IRQ controller */
+        ppc405_irq_init(env);
+        break;
+
+#if defined (TODO)
+    case CPU_PPC_STB01000:
+#endif
+#if defined (TODO)
+    case CPU_PPC_STB01010:
+#endif
+#if defined (TODO)
+    case CPU_PPC_STB0210:
+#endif
+    case CPU_PPC_STB03:   /* STB03 family                  */
+#if defined (TODO)
+    case CPU_PPC_STB043:  /* STB043 family                  */
+#endif
+#if defined (TODO)
+    case CPU_PPC_STB045:  /* STB045 family                  */
+#endif
+    case CPU_PPC_STB25:   /* STB25 family                  */
+#if defined (TODO)
+    case CPU_PPC_STB130:  /* STB130 family                 */
+#endif
+        gen_spr_generic(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_40x(env);
+        gen_spr_405(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* Allocate hardware IRQ controller */
+        ppc405_irq_init(env);
+        break;
+
+    case CPU_PPC_440EP:   /* 440 EP family                 */
+    case CPU_PPC_440GP:   /* 440 GP family                 */
+    case CPU_PPC_440GX:   /* 440 GX family                 */
+    case CPU_PPC_440GXc:  /* 440 GXc family                */
+    case CPU_PPC_440GXf:  /* 440 GXf family                */
+    case CPU_PPC_440SP:   /* 440 SP family                 */
+    case CPU_PPC_440SP2:
+    case CPU_PPC_440SPE:  /* 440 SPE family                */
+        gen_spr_generic(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_BookE(env);
+        gen_spr_440(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* XXX: TODO: allocate internal IRQ controller */
+        break;
+
+    /* Embedded PowerPC from Freescale                     */
+#if defined (TODO)
+    case CPU_PPC_5xx:
+        break;
+#endif
+#if defined (TODO)
+    case CPU_PPC_8xx:     /* MPC821 / 823 / 850 / 860      */
+        break;
+#endif
+#if defined (TODO)
+    case CPU_PPC_82xx_HIP3:    /* MPC8240 / 8260                */
+    case CPU_PPC_82xx_HIP4:    /* MPC8240 / 8260                */
+        break;
+#endif
+#if defined (TODO)
+    case CPU_PPC_827x:    /* MPC 827x / 828x               */
+        break;
+#endif
+
+    /* XXX: Use MPC8540 PVR to implement a test PowerPC BookE target */
+    case CPU_PPC_e500v110:
+    case CPU_PPC_e500v120:
+    case CPU_PPC_e500v210:
+    case CPU_PPC_e500v220:
+        gen_spr_generic(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_BookE(env);
+        gen_spr_BookE_FSL(env);
+        env->nb_BATs = 0;
+        env->nb_tlb = 64;
+        env->nb_ways = 1;
+        env->id_tlbs = 0;
+        /* XXX: TODO: allocate internal IRQ controller */
+        break;
+
+#if defined (TODO)
+    case CPU_PPC_e600:
+        break;
+#endif
+
+    /* 32 bits PowerPC                                     */
+    case CPU_PPC_601:     /* PowerPC 601                   */
+        gen_spr_generic(env);
         gen_spr_ne_601(env);
+        gen_spr_601(env);
+        /* Hardware implementation registers */
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID0, "HID0",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_601_HID2, "HID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_601_HID5, "HID5",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+#if 0 /* ? */
+        spr_register(env, SPR_601_HID15, "HID15",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+#endif
+        env->nb_tlb = 64;
+        env->nb_ways = 2;
+        env->id_tlbs = 0;
+        env->id_tlbs = 0;
+        /* XXX: TODO: allocate internal IRQ controller */
+        break;
+
+    case CPU_PPC_602:     /* PowerPC 602                   */
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
         /* Memory management */
         gen_low_BATs(env);
         /* Time base */
         gen_tbl(env);
-        gen_spr_604(env);
-        /* Hardware implementation registers */
+        gen_6xx_7xx_soft_tlb(env, 64, 2);
+        gen_spr_602(env);
+        /* hardware implementation registers */
         /* XXX : not implemented */
         spr_register(env, SPR_HID0, "HID0",
                      SPR_NOACCESS, SPR_NOACCESS,
@@ -727,23 +2109,87 @@
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
         break;
 
-    case CPU_PPC_74x:     /* PPC 740 / 750                 */
-    case CPU_PPC_74xP:    /* PPC 740P / 750P               */
-    case CPU_PPC_750CXE:  /* IBM PPC 750cxe                */
+    case CPU_PPC_603:     /* PowerPC 603                   */
+    case CPU_PPC_603E:    /* PowerPC 603e                  */
+    case CPU_PPC_603E7v:
+    case CPU_PPC_603E7v2:
+    case CPU_PPC_603P:    /* PowerPC 603p                  */
+    case CPU_PPC_603R:    /* PowerPC 603r                  */
         gen_spr_generic(env);
         gen_spr_ne_601(env);
         /* Memory management */
         gen_low_BATs(env);
         /* Time base */
         gen_tbl(env);
-        gen_spr_7xx(env);
+        gen_6xx_7xx_soft_tlb(env, 64, 2);
+        gen_spr_603(env);
+        /* hardware implementation registers */
         /* XXX : not implemented */
-        spr_register(env, SPR_L2CR, "L2CR",
+        spr_register(env, SPR_HID0, "HID0",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
+        break;
+        
+    case CPU_PPC_G2:      /* PowerPC G2 family             */
+    case CPU_PPC_G2H4:
+    case CPU_PPC_G2gp:
+    case CPU_PPC_G2ls:
+    case CPU_PPC_G2LE:    /* PowerPC G2LE family           */
+    case CPU_PPC_G2LEgp:
+    case CPU_PPC_G2LEls:
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* Memory management */
+        gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        /* Memory management */
+        gen_high_BATs(env);
+        gen_6xx_7xx_soft_tlb(env, 64, 2);
+        gen_spr_G2_755(env);
+        gen_spr_G2(env);
+        /* Hardware implementation register */
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID0, "HID0",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID2, "HID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
+        break;
+
+    case CPU_PPC_604:     /* PowerPC 604                   */
+    case CPU_PPC_604E:    /* PowerPC 604e                  */
+    case CPU_PPC_604R:    /* PowerPC 604r                  */
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* Memory management */
+        gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_604(env);
         /* Hardware implementation registers */
         /* XXX : not implemented */
         spr_register(env, SPR_HID0, "HID0",
@@ -755,24 +2201,107 @@
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
         break;
 
-    case CPU_PPC_750FX:   /* IBM PPC 750 FX                */
-    case CPU_PPC_750GX:   /* IBM PPC 750 GX                */
+    case CPU_PPC_74x:     /* PowerPC 740 / 750             */
+    case CPU_PPC_740E:
+    case CPU_PPC_750E:
+    case CPU_PPC_74xP:    /* PowerPC 740P / 750P           */
+    case CPU_PPC_750CXE21: /* IBM PowerPC 750cxe            */
+    case CPU_PPC_750CXE22:
+    case CPU_PPC_750CXE23:
+    case CPU_PPC_750CXE24:
+    case CPU_PPC_750CXE24b:
+    case CPU_PPC_750CXE31:
+    case CPU_PPC_750CXE31b:
+    case CPU_PPC_750CXR:
         gen_spr_generic(env);
         gen_spr_ne_601(env);
         /* Memory management */
         gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_7xx(env);
+        /* Hardware implementation registers */
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID0, "HID0",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
+        break;
+
+    case CPU_PPC_750FX10: /* IBM PowerPC 750 FX            */
+    case CPU_PPC_750FX20:
+    case CPU_PPC_750FX21:
+    case CPU_PPC_750FX22:
+    case CPU_PPC_750FX23:
+    case CPU_PPC_750GX10: /* IBM PowerPC 750 GX            */
+    case CPU_PPC_750GX11:
+    case CPU_PPC_750GX12:
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* Memory management */
+        gen_low_BATs(env);
         /* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
         gen_high_BATs(env);
         /* Time base */
         gen_tbl(env);
         gen_spr_7xx(env);
+        /* Hardware implementation registers */
         /* XXX : not implemented */
-        spr_register(env, SPR_L2CR, "L2CR",
+        spr_register(env, SPR_HID0, "HID0",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_750_HID2, "HID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
+        break;
+
+    case CPU_PPC_755_10:  /* PowerPC 755                   */
+    case CPU_PPC_755_11:
+    case CPU_PPC_755_20:
+    case CPU_PPC_755D:
+    case CPU_PPC_755E:
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* Memory management */
+        gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        /* Memory management */
+        gen_high_BATs(env);
+        gen_6xx_7xx_soft_tlb(env, 64, 2);
+        gen_spr_G2_755(env);
+        /* L2 cache control */
+        /* XXX : not implemented */
+        spr_register(env, SPR_ICTC, "ICTC",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_L2PM, "L2PM",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
         /* Hardware implementation registers */
         /* XXX : not implemented */
         spr_register(env, SPR_HID0, "HID0",
@@ -781,22 +2310,130 @@
                      0x00000000);
         /* XXX : not implemented */
         spr_register(env, SPR_HID1, "HID1",
-                 SPR_NOACCESS, SPR_NOACCESS,
+                     SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
         /* XXX : not implemented */
+        spr_register(env, SPR_HID2, "HID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc6xx_irq_init(env);
+        break;
+
+#if defined (TODO)
+    /* G4 family */
+    case CPU_PPC_7400:    /* PowerPC 7400                  */
+    case CPU_PPC_7410C:   /* PowerPC 7410                  */
+    case CPU_PPC_7410D:
+    case CPU_PPC_7410E:
+    case CPU_PPC_7441:    /* PowerPC 7441                  */
+    case CPU_PPC_7445:    /* PowerPC 7445                  */
+    case CPU_PPC_7447:    /* PowerPC 7447                  */
+    case CPU_PPC_7447A:   /* PowerPC 7447A                 */
+    case CPU_PPC_7448:    /* PowerPC 7448                  */
+    case CPU_PPC_7450:    /* PowerPC 7450                  */
+    case CPU_PPC_7450b:
+    case CPU_PPC_7451:    /* PowerPC 7451                  */
+    case CPU_PPC_7451G:
+    case CPU_PPC_7455:    /* PowerPC 7455                  */
+    case CPU_PPC_7455F:
+    case CPU_PPC_7455G:
+    case CPU_PPC_7457:    /* PowerPC 7457                  */
+    case CPU_PPC_7457C:
+    case CPU_PPC_7457A:   /* PowerPC 7457A                 */
+        break;
+#endif
+
+    /* 64 bits PowerPC                                     */
+#if defined (TARGET_PPC64)
+#if defined (TODO)
+    case CPU_PPC_620:     /* PowerPC 620                   */
+    case CPU_PPC_630:     /* PowerPC 630 (Power 3)         */
+    case CPU_PPC_631:     /* PowerPC 631 (Power 3+)        */
+    case CPU_PPC_POWER4:  /* Power 4                       */
+    case CPU_PPC_POWER4P: /* Power 4+                      */
+    case CPU_PPC_POWER5:  /* Power 5                       */
+    case CPU_PPC_POWER5P: /* Power 5+                      */
+#endif
+        break;
+
+    case CPU_PPC_970:     /* PowerPC 970                   */
+    case CPU_PPC_970FX10: /* PowerPC 970 FX                */
+    case CPU_PPC_970FX20:
+    case CPU_PPC_970FX21:
+    case CPU_PPC_970FX30:
+    case CPU_PPC_970FX31:
+    case CPU_PPC_970MP10: /* PowerPC 970 MP                */
+    case CPU_PPC_970MP11:
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* XXX: not correct */
+        gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_7xx(env);
+        /* Hardware implementation registers */
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID0, "HID0",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
         spr_register(env, SPR_750_HID2, "HID2",
                      SPR_NOACCESS, SPR_NOACCESS,
                      &spr_read_generic, &spr_write_generic,
                      0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc970_irq_init(env);
         break;
 
+#if defined (TODO)
+    case CPU_PPC_CELL10:  /* Cell family                   */
+    case CPU_PPC_CELL20:
+    case CPU_PPC_CELL30:
+    case CPU_PPC_CELL31:
+#endif
+        break;
+
+#if defined (TODO)
+    case CPU_PPC_RS64:    /* Apache (RS64/A35)             */
+    case CPU_PPC_RS64II:  /* NorthStar (RS64-II/A50)       */
+    case CPU_PPC_RS64III: /* Pulsar (RS64-III)             */
+    case CPU_PPC_RS64IV:  /* IceStar/IStar/SStar (RS64-IV) */
+#endif
+        break;
+#endif /* defined (TARGET_PPC64) */
+
+#if defined (TODO)
+        /* POWER                                               */
+    case CPU_POWER:       /* POWER                         */
+    case CPU_POWER2:      /* POWER2                        */
+        break;
+#endif
+
     default:
         gen_spr_generic(env);
+        /* XXX: TODO: allocate internal IRQ controller */
         break;
     }
     if (env->nb_BATs == -1)
         env->nb_BATs = 4;
+    /* Allocate TLBs buffer when needed */
+    if (env->nb_tlb != 0) {
+        int nb_tlb = env->nb_tlb;
+        if (env->id_tlbs != 0)
+            nb_tlb *= 2;
+        env->tlb = qemu_mallocz(nb_tlb * sizeof(ppc_tlb_t));
+        /* Pre-compute some useful values */
+        env->tlb_per_way = env->nb_tlb / env->nb_ways;
+    }
 }
 
 #if defined(PPC_DUMP_CPU)
@@ -812,8 +2449,13 @@
         for (j = 0; j < 32; j++) {
             n = (i << 5) | j;
             spr = &env->spr_cb[n];
+#if !defined(CONFIG_USER_ONLY)
             sw = spr->oea_write != NULL && spr->oea_write != SPR_NOACCESS;
             sr = spr->oea_read != NULL && spr->oea_read != SPR_NOACCESS;
+#else
+            sw = 0;
+            sr = 0;
+#endif
             uw = spr->uea_write != NULL && spr->uea_write != SPR_NOACCESS;
             ur = spr->uea_read != NULL && spr->uea_read != SPR_NOACCESS;
             if (sw || sr || uw || ur) {
@@ -889,7 +2531,7 @@
 {
     if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
         printf("*** ERROR: opcode %02x already assigned in main "
-                "opcode table\n", idx);
+               "opcode table\n", idx);
         return -1;
     }
 
@@ -903,20 +2545,20 @@
     if (table[idx1] == &invalid_handler) {
         if (create_new_table(table, idx1) < 0) {
             printf("*** ERROR: unable to create indirect table "
-                    "idx=%02x\n", idx1);
+                   "idx=%02x\n", idx1);
             return -1;
         }
     } else {
         if (!is_indirect_opcode(table[idx1])) {
             printf("*** ERROR: idx %02x already assigned to a direct "
-                    "opcode\n", idx1);
+                   "opcode\n", idx1);
             return -1;
         }
     }
     if (handler != NULL &&
         insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
         printf("*** ERROR: opcode %02x already assigned in "
-                "opcode table %02x\n", idx2, idx1);
+               "opcode table %02x\n", idx2, idx1);
         return -1;
     }
 
@@ -925,7 +2567,7 @@
 
 static int register_ind_insn (opc_handler_t **ppc_opcodes,
                               unsigned char idx1, unsigned char idx2,
-                               opc_handler_t *handler)
+                              opc_handler_t *handler)
 {
     int ret;
 
@@ -936,17 +2578,17 @@
 
 static int register_dblind_insn (opc_handler_t **ppc_opcodes, 
                                  unsigned char idx1, unsigned char idx2,
-                                  unsigned char idx3, opc_handler_t *handler)
+                                 unsigned char idx3, opc_handler_t *handler)
 {
     if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
         printf("*** ERROR: unable to join indirect table idx "
-                "[%02x-%02x]\n", idx1, idx2);
+               "[%02x-%02x]\n", idx1, idx2);
         return -1;
     }
     if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
                               handler) < 0) {
         printf("*** ERROR: unable to insert opcode "
-                "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
+               "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
         return -1;
     }
 
@@ -1012,21 +2654,23 @@
 
     fill_new_table(env->opcodes, 0x40);
 #if defined(PPC_DUMP_CPU)
-    printf("* PPC instructions for PVR %08x: %s\n", def->pvr, def->name);
+    printf("* PowerPC instructions for PVR %08x: %s flags %016" PRIx64
+           " %08x\n",
+           def->pvr, def->name, def->insns_flags, def->flags);
 #endif
     if (&opc_start < &opc_end) {
-	start = &opc_start;
-	end = &opc_end;
+        start = &opc_start;
+        end = &opc_end;
     } else {
-	start = &opc_end;
-	end = &opc_start;
+        start = &opc_end;
+        end = &opc_start;
     }
     for (opc = start + 1; opc != end; opc++) {
         if ((opc->handler.type & def->insns_flags) != 0) {
             if (register_insn(env->opcodes, opc) < 0) {
-                printf("*** ERROR initializing PPC instruction "
-                        "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
-                        opc->opc3);
+                printf("*** ERROR initializing PowerPC instruction "
+                       "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
+                       opc->opc3);
                 return -1;
             }
 #if defined(PPC_DUMP_CPU)
@@ -1038,7 +2682,7 @@
                     } else {
                         printf(" %02x %02x -- (%2d %4d) : %s\n",
                                opc->opc1, opc->opc2, opc->opc1, opc->opc2,
-                                    opc->oname);
+                               opc->oname);
                     }
                 } else {
                     printf(" %02x %02x %02x (%2d %4d) : %s\n",
@@ -1061,61 +2705,26 @@
 {
     env->msr_mask = def->msr_mask;
     env->flags = def->flags;
-    if (create_ppc_opcodes(env, def) < 0) {
-        printf("Error creating opcodes table\n");
-        fflush(stdout);
-        fflush(stderr);
+    if (create_ppc_opcodes(env, def) < 0)
         return -1;
-    }
     init_ppc_proc(env, def);
 #if defined(PPC_DUMP_CPU)
     dump_sprs(env);
+    if (env->tlb != NULL) {
+        printf("%d %s TLB in %d ways\n", env->nb_tlb,
+               env->id_tlbs ? "splitted" : "merged", env->nb_ways);
+    }
 #endif
-    fflush(stdout);
-    fflush(stderr);
 
     return 0;
 }
 
-CPUPPCState *cpu_ppc_init(void)
-{
-    CPUPPCState *env;
-
-    env = qemu_mallocz(sizeof(CPUPPCState));
-    if (!env)
-        return NULL;
-    cpu_exec_init(env);
-    tlb_flush(env, 1);
-#if defined (DO_SINGLE_STEP) && 0
-    /* Single step trace mode */
-    msr_se = 1;
-    msr_be = 1;
-#endif
-    msr_fp = 1; /* Allow floating point exceptions */
-    msr_me = 1; /* Allow machine check exceptions  */
-#if defined(CONFIG_USER_ONLY)
-    msr_pr = 1;
-#else
-    env->nip = 0xFFFFFFFC;
-#endif
-    do_compute_hflags(env);
-    env->reserve = -1;
-    return env;
-}
-
-void cpu_ppc_close(CPUPPCState *env)
-{
-    /* Should also remove all opcode tables... */
-    free(env);
-}
-
 /*****************************************************************************/
 /* PowerPC CPU definitions */
-static ppc_def_t ppc_defs[] =
-{
-    /* Embedded PPC */
+static ppc_def_t ppc_defs[] = {
+    /* Embedded PowerPC */
 #if defined (TODO)
-    /* PPC 401 */
+    /* PowerPC 401 */
     {
         .name        = "401",
         .pvr         = CPU_PPC_401,
@@ -1137,124 +2746,158 @@
     },
 #endif
 #if defined (TODO)
-    /* PPC 403 GA */
+    /* IBM Processor for Network Resources */
     {
+        .name        = "Cobra",
+        .pvr         = CPU_PPC_COBRA,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_401,
+        .flags       = PPC_FLAGS_401,
+        .msr_mask    = xxx,
+    },
+#endif
+#if defined (TODO)
+    /* Generic PowerPC 403 */
+    {
+        .name        = "403",
+        .pvr         = CPU_PPC_403,
+        .pvr_mask    = 0xFFFFFF00,
+        .insns_flags = PPC_INSNS_403,
+        .flags       = PPC_FLAGS_403,
+        .msr_mask    = 0x000000000007D23DULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 403 GA */
+    {
         .name        = "403ga",
         .pvr         = CPU_PPC_403GA,
         .pvr_mask    = 0xFFFFFF00,
         .insns_flags = PPC_INSNS_403,
         .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23D,
+        .msr_mask    = 0x000000000007D23DULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 403 GB */
+    /* PowerPC 403 GB */
     {
         .name        = "403gb",
         .pvr         = CPU_PPC_403GB,
         .pvr_mask    = 0xFFFFFF00,
         .insns_flags = PPC_INSNS_403,
         .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23D,
+        .msr_mask    = 0x000000000007D23DULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 403 GC */
+    /* PowerPC 403 GC */
     {
         .name        = "403gc",
         .pvr         = CPU_PPC_403GC,
         .pvr_mask    = 0xFFFFFF00,
         .insns_flags = PPC_INSNS_403,
         .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23D,
+        .msr_mask    = 0x000000000007D23DULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 403 GCX */
+    /* PowerPC 403 GCX */
     {
         .name        = "403gcx",
         .pvr         = CPU_PPC_403GCX,
         .pvr_mask    = 0xFFFFFF00,
         .insns_flags = PPC_INSNS_403,
         .flags       = PPC_FLAGS_403,
-        .msr_mask    = 0x000000000007D23D,
+        .msr_mask    = 0x000000000007D23DULL,
     },
 #endif
-#if defined (TODO)
-    /* PPC 405 CR */
+    /* Generic PowerPC 405 */
     {
-        .name        = "405cr",
+        .name        = "405",
         .pvr         = CPU_PPC_405,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
-#endif
+    /* PowerPC 405 CR */
+    {
+        .name        = "405cr",
+        .pvr         = CPU_PPC_405,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
 #if defined (TODO)
-    /* PPC 405 GP */
+    /* PowerPC 405 GP */
     {
         .name        = "405gp",
         .pvr         = CPU_PPC_405,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
-#if defined (TODO)
-    /* PPC 405 EP */
+    /* PowerPC 405 EP */
     {
         .name        = "405ep",
         .pvr         = CPU_PPC_405EP,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000000ED630ULL,
     },
+#if defined (TODO)
+    /* PowerPC 405 EZ */
+    {
+        .name        = "405ez",
+        .pvr         = CPU_PPC_405EZ,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
 #endif
 #if defined (TODO)
-    /* PPC 405 GPR */
+    /* PowerPC 405 GPR */
     {
         .name        = "405gpr",
         .pvr         = CPU_PPC_405GPR,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
-#if defined (TODO)
-    /* PPC 405 D2 */
+    /* PowerPC 405 D2 */
     {
         .name        = "405d2",
         .pvr         = CPU_PPC_405D2,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
-#endif
-#if defined (TODO)
-    /* PPC 405 D4 */
+    /* PowerPC 405 D4 */
     {
         .name        = "405d4",
         .pvr         = CPU_PPC_405D4,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
-#endif
 #if defined (TODO)
     /* Npe405 H */
     {
         .name        = "Npe405H",
         .pvr         = CPU_PPC_NPE405H,
-        .pvr_mask    = 0xFFFF0000,
-        .insns_flags = PPC_INSNS_405,
+        .pvr_mask    = 0xFFFFFFFF,
+            .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
 #if defined (TODO)
@@ -1262,162 +2905,353 @@
     {
         .name        = "Npe405L",
         .pvr         = CPU_PPC_NPE405L,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
 #if defined (TODO)
+    /* STB010000 */
+    {
+        .name        = "STB01000",
+        .pvr         = CPU_PPC_STB01000,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+#if defined (TODO)
+    /* STB01010 */
+    {
+        .name        = "STB01010",
+        .pvr         = CPU_PPC_STB01010,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+#if defined (TODO)
+    /* STB0210 */
+    {
+        .name        = "STB0210",
+        .pvr         = CPU_PPC_STB0210,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+#if defined (TODO)
     /* STB03xx */
     {
         .name        = "STB03",
         .pvr         = CPU_PPC_STB03,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
 #if defined (TODO)
-    /* STB04xx */
+    /* STB043x */
     {
-        .name        = "STB04",
-        .pvr         = CPU_PPC_STB04,
-        .pvr_mask    = 0xFFFF0000,
+        .name        = "STB043",
+        .pvr         = CPU_PPC_STB043,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
 #if defined (TODO)
+    /* STB045x */
+    {
+        .name        = "STB045",
+        .pvr         = CPU_PPC_STB045,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+#if defined (TODO)
     /* STB25xx */
     {
         .name        = "STB25",
         .pvr         = CPU_PPC_STB25,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_405,
-        .msr_mask    = 0x00000000020EFF30,
+        .msr_mask    = 0x00000000020EFF30ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 440 EP */
+    /* STB130 */
     {
+        .name        = "STB130",
+        .pvr         = CPU_PPC_STB130,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+        /* Xilinx PowerPC 405 cores */
+#if defined (TODO)
+    {
+        .name        = "x2vp4",
+        .pvr         = CPU_PPC_X2VP4,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+    {
+        .name        = "x2vp7",
+        .pvr         = CPU_PPC_X2VP7,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+    {
+        .name        = "x2vp20",
+        .pvr         = CPU_PPC_X2VP20,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+    {
+        .name        = "x2vp50",
+        .pvr         = CPU_PPC_X2VP50,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_405,
+        .msr_mask    = 0x00000000020EFF30ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 EP */
+    {
         .name        = "440ep",
         .pvr         = CPU_PPC_440EP,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_440,
         .flags       = PPC_FLAGS_440,
-        .msr_mask    = 0x000000000006D630,
+        .msr_mask    = 0x000000000006D630ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 440 GP */
+    /* PowerPC 440 GR */
     {
+        .name        = "440gr",
+        .pvr         = CPU_PPC_440GR,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_440,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 GP */
+    {
         .name        = "440gp",
         .pvr         = CPU_PPC_440GP,
         .pvr_mask    = 0xFFFFFF00,
         .insns_flags = PPC_INSNS_440,
         .flags       = PPC_FLAGS_440,
-        .msr_mask    = 0x000000000006D630,
+        .msr_mask    = 0x000000000006D630ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 440 GX */
+    /* PowerPC 440 GX */
     {
         .name        = "440gx",
         .pvr         = CPU_PPC_440GX,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_405,
         .flags       = PPC_FLAGS_440,
-        .msr_mask    = 0x000000000006D630,
+        .msr_mask    = 0x000000000006D630ULL,
     },
 #endif
+#if defined (TODO)
+    /* PowerPC 440 GXc */
+    {
+        .name        = "440gxc",
+        .pvr         = CPU_PPC_440GXC,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 GXf */
+    {
+        .name        = "440gxf",
+        .pvr         = CPU_PPC_440GXF,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 SP */
+    {
+        .name        = "440sp",
+        .pvr         = CPU_PPC_440SP,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 SP2 */
+    {
+        .name        = "440sp2",
+        .pvr         = CPU_PPC_440SP2,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+#if defined (TODO)
+    /* PowerPC 440 SPE */
+    {
+        .name        = "440spe",
+        .pvr         = CPU_PPC_440SPE,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_405,
+        .flags       = PPC_FLAGS_440,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+#endif
+    /* Fake generic BookE PowerPC */
+    {
+        .name        = "BookE",
+        .pvr         = CPU_PPC_e500,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_BOOKE,
+        .flags       = PPC_FLAGS_BOOKE,
+        .msr_mask    = 0x000000000006D630ULL,
+    },
+    /* PowerPC 460 cores - TODO */
+    /* PowerPC MPC 5xx cores - TODO */
+    /* PowerPC MPC 8xx cores - TODO */
+    /* PowerPC MPC 8xxx cores - TODO */
+    /* e200 cores - TODO */
+    /* e500 cores - TODO */
+    /* e600 cores - TODO */
 
-    /* 32 bits "classic" powerpc */
+    /* 32 bits "classic" PowerPC */
 #if defined (TODO)
-    /* PPC 601 */
+    /* PowerPC 601 */
     {
         .name        = "601",
         .pvr         = CPU_PPC_601,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_601,
         .flags       = PPC_FLAGS_601,
-        .msr_mask    = 0x000000000000FD70,
+        .msr_mask    = 0x000000000000FD70ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 602 */
+    /* PowerPC 602 */
     {
         .name        = "602",
         .pvr         = CPU_PPC_602,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_602,
         .flags       = PPC_FLAGS_602,
-        .msr_mask    = 0x0000000000C7FF73,
+        .msr_mask    = 0x0000000000C7FF73ULL,
     },
 #endif
-#if defined (TODO)
-    /* PPC 603 */
+    /* PowerPC 603 */
     {
         .name        = "603",
         .pvr         = CPU_PPC_603,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
-#endif
-#if defined (TODO)
-    /* PPC 603e */
+    /* PowerPC 603e */
     {
         .name        = "603e",
         .pvr         = CPU_PPC_603E,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
     {
         .name        = "Stretch",
         .pvr         = CPU_PPC_603E,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
-#endif
-#if defined (TODO)
-    /* PPC 603ev */
+    /* PowerPC 603p */
     {
-        .name        = "603ev",
-        .pvr         = CPU_PPC_603EV,
-        .pvr_mask    = 0xFFFFF000,
+        .name        = "603p",
+        .pvr         = CPU_PPC_603P,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
-#endif
-#if defined (TODO)
-    /* PPC 603r */
+    /* PowerPC 603e7 */
     {
+        .name        = "603e7",
+        .pvr         = CPU_PPC_603E7,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_603,
+        .flags       = PPC_FLAGS_603,
+        .msr_mask    = 0x000000000007FF73ULL,
+    },
+    /* PowerPC 603e7v */
+    {
+        .name        = "603e7v",
+        .pvr         = CPU_PPC_603E7v,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_603,
+        .flags       = PPC_FLAGS_603,
+        .msr_mask    = 0x000000000007FF73ULL,
+    },
+    /* PowerPC 603e7v2 */
+    {
+        .name        = "603e7v2",
+        .pvr         = CPU_PPC_603E7v2,
+        .pvr_mask    = 0xFFFFFFFF,
+        .insns_flags = PPC_INSNS_603,
+        .flags       = PPC_FLAGS_603,
+        .msr_mask    = 0x000000000007FF73ULL,
+    },
+    /* PowerPC 603r */
+    {
         .name        = "603r",
         .pvr         = CPU_PPC_603R,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
     {
         .name        = "Goldeneye",
         .pvr         = CPU_PPC_603R,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_603,
         .flags       = PPC_FLAGS_603,
-        .msr_mask    = 0x000000000007FF73,
+        .msr_mask    = 0x000000000007FF73ULL,
     },
-#endif
 #if defined (TODO)
     /* XXX: TODO: according to Motorola UM, this is a derivative to 603e */
     {
@@ -1426,72 +3260,110 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_G2,
         .flags       = PPC_FLAGS_G2,
-        .msr_mask    = 0x000000000006FFF2,
+        .msr_mask    = 0x000000000006FFF2ULL,
     },
+    {
+        .name        = "G2h4",
+        .pvr         = CPU_PPC_G2H4,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_G2,
+        .flags       = PPC_FLAGS_G2,
+        .msr_mask    = 0x000000000006FFF2ULL,
+    },
+    {
+        .name        = "G2gp",
+        .pvr         = CPU_PPC_G2gp,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_G2,
+        .flags       = PPC_FLAGS_G2,
+        .msr_mask    = 0x000000000006FFF2ULL,
+    },
+    {
+        .name        = "G2ls",
+        .pvr         = CPU_PPC_G2ls,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_G2,
+        .flags       = PPC_FLAGS_G2,
+        .msr_mask    = 0x000000000006FFF2ULL,
+    },
     { /* Same as G2, with LE mode support */
         .name        = "G2le",
         .pvr         = CPU_PPC_G2LE,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_G2,
         .flags       = PPC_FLAGS_G2,
-        .msr_mask    = 0x000000000007FFF3,
+        .msr_mask    = 0x000000000007FFF3ULL,
     },
+    {
+        .name        = "G2legp",
+        .pvr         = CPU_PPC_G2LEgp,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_G2,
+        .flags       = PPC_FLAGS_G2,
+        .msr_mask    = 0x000000000007FFF3ULL,
+    },
+    {
+        .name        = "G2lels",
+        .pvr         = CPU_PPC_G2LEls,
+        .pvr_mask    = 0xFFFF0000,
+        .insns_flags = PPC_INSNS_G2,
+        .flags       = PPC_FLAGS_G2,
+        .msr_mask    = 0x000000000007FFF3ULL,
+    },
 #endif
-    /* PPC 604 */
+    /* PowerPC 604 */
     {
         .name        = "604",
         .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_604,
         .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77,
+        .msr_mask    = 0x000000000005FF77ULL,
     },
-    /* PPC 604e */
+    /* PowerPC 604e */
     {
         .name        = "604e",
         .pvr         = CPU_PPC_604E,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_604,
         .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77,
+        .msr_mask    = 0x000000000005FF77ULL,
     },
-    /* PPC 604r */
+    /* PowerPC 604r */
     {
         .name        = "604r",
         .pvr         = CPU_PPC_604R,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_604,
         .flags       = PPC_FLAGS_604,
-        .msr_mask    = 0x000000000005FF77,
+        .msr_mask    = 0x000000000005FF77ULL,
     },
     /* generic G3 */
     {
         .name        = "G3",
         .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
-#if defined (TODO)
     /* MPC740 (G3) */
     {
         .name        = "740",
         .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
     {
         .name        = "Arthur",
         .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
-#endif
 #if defined (TODO)
     /* MPC745 (G3) */
     {
@@ -1500,7 +3372,7 @@
         .pvr_mask    = 0xFFFFF000,
         .insns_flags = PPC_INSNS_7x5,
         .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
     {
         .name        = "Goldfinger",
@@ -1508,17 +3380,17 @@
         .pvr_mask    = 0xFFFFF000,
         .insns_flags = PPC_INSNS_7x5,
         .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #endif
     /* MPC750 (G3) */
     {
         .name        = "750",
         .pvr         = CPU_PPC_74x,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #if defined (TODO)
     /* MPC755 (G3) */
@@ -1528,28 +3400,26 @@
         .pvr_mask    = 0xFFFFF000,
         .insns_flags = PPC_INSNS_7x5,
         .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #endif
-#if defined (TODO)
     /* MPC740P (G3) */
     {
         .name        = "740p",
         .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
     {
         .name        = "Conan/Doyle",
         .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
-#endif
 #if defined (TODO)
     /* MPC745P (G3) */
     {
@@ -1558,17 +3428,17 @@
         .pvr_mask    = 0xFFFFF000,
         .insns_flags = PPC_INSNS_7x5,
         .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #endif
     /* MPC750P (G3) */
     {
         .name        = "750p",
         .pvr         = CPU_PPC_74xP,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #if defined (TODO)
     /* MPC755P (G3) */
@@ -1578,35 +3448,35 @@
         .pvr_mask    = 0xFFFFF000,
         .insns_flags = PPC_INSNS_7x5,
         .flags       = PPC_FLAGS_7x5,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #endif
     /* IBM 750CXe (G3 embedded) */
     {
         .name        = "750cxe",
         .pvr         = CPU_PPC_750CXE,
-        .pvr_mask    = 0xFFFFF000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
     /* IBM 750FX (G3 embedded) */
     {
         .name        = "750fx",
         .pvr         = CPU_PPC_750FX,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
     /* IBM 750GX (G3 embedded) */
     {
         .name        = "750gx",
         .pvr         = CPU_PPC_750GX,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_7x0,
         .flags       = PPC_FLAGS_7x0,
-        .msr_mask    = 0x000000000007FF77,
+        .msr_mask    = 0x000000000007FF77ULL,
     },
 #if defined (TODO)
     /* generic G4 */
@@ -1616,18 +3486,18 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 7400 (G4) */
+    /* PowerPC 7400 (G4) */
     {
         .name        = "7400",
         .pvr         = CPU_PPC_7400,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Max",
@@ -1635,18 +3505,18 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 7410 (G4) */
+    /* PowerPC 7410 (G4) */
     {
         .name        = "7410",
         .pvr         = CPU_PPC_7410,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Nitro",
@@ -1654,7 +3524,7 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
     /* XXX: 7441 */
@@ -1662,14 +3532,14 @@
     /* XXX: 7447 */
     /* XXX: 7447A */
 #if defined (TODO)
-    /* PPC 7450 (G4) */
+    /* PowerPC 7450 (G4) */
     {
         .name        = "7450",
         .pvr         = CPU_PPC_7450,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Vger",
@@ -1677,19 +3547,19 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
     /* XXX: 7451 */
 #if defined (TODO)
-    /* PPC 7455 (G4) */
+    /* PowerPC 7455 (G4) */
     {
         .name        = "7455",
         .pvr         = CPU_PPC_7455,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Apollo 6",
@@ -1697,18 +3567,18 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 7457 (G4) */
+    /* PowerPC 7457 (G4) */
     {
         .name        = "7457",
         .pvr         = CPU_PPC_7457,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Apollo 7",
@@ -1716,18 +3586,18 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 7457A (G4) */
+    /* PowerPC 7457A (G4) */
     {
         .name        = "7457A",
         .pvr         = CPU_PPC_7457A,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
     {
         .name        = "Apollo 7 PM",
@@ -1735,23 +3605,24 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_74xx,
         .flags       = PPC_FLAGS_74xx,
-        .msr_mask    = 0x000000000205FF77,
+        .msr_mask    = 0x000000000205FF77ULL,
     },
 #endif
-    /* 64 bits PPC */
+    /* 64 bits PowerPC */
+#if defined (TARGET_PPC64)
 #if defined (TODO)
-    /* PPC 620 */
+    /* PowerPC 620 */
     {
         .name        = "620",
         .pvr         = CPU_PPC_620,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_620,
         .flags       = PPC_FLAGS_620,
-        .msr_mask    = 0x800000000005FF73,
+        .msr_mask    = 0x800000000005FF73ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 630 (POWER3) */
+    /* PowerPC 630 (POWER3) */
     {
         .name        = "630",
         .pvr         = CPU_PPC_630,
@@ -1770,7 +3641,7 @@
     }
 #endif
 #if defined (TODO)
-    /* PPC 631 (Power 3+)*/
+    /* PowerPC 631 (Power 3+)*/
     {
         .name        = "631",
         .pvr         = CPU_PPC_631,
@@ -1833,25 +3704,25 @@
     },
 #endif
 #if defined (TODO)
-    /* PPC 970 */
+    /* PowerPC 970 */
     {
         .name        = "970",
         .pvr         = CPU_PPC_970,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_970,
         .flags       = PPC_FLAGS_970,
-        .msr_mask    = 0x900000000204FF36,
+        .msr_mask    = 0x900000000204FF36ULL,
     },
 #endif
 #if defined (TODO)
-    /* PPC 970FX (G5) */
+    /* PowerPC 970FX (G5) */
     {
         .name        = "970fx",
         .pvr         = CPU_PPC_970FX,
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_970FX,
         .flags       = PPC_FLAGS_970FX,
-        .msr_mask    = 0x800000000204FF36,
+        .msr_mask    = 0x800000000204FF36ULL,
     },
 #endif
 #if defined (TODO)
@@ -1977,6 +3848,7 @@
         .msr_mask    = xxx,
     },
 #endif
+#endif /* defined (TARGET_PPC64) */
 #if defined (TODO)
     /* POWER2 */
     {
@@ -1996,25 +3868,25 @@
         .pvr_mask    = 0xFFFF0000,
         .insns_flags = PPC_INSNS_PPC64,
         .flags       = PPC_FLAGS_PPC64,
-        .msr_mask    = 0xA00000000204FF36,
+        .msr_mask    = 0xA00000000204FF36ULL,
     },
 #endif
     {
         .name        = "ppc32",
         .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_PPC32,
         .flags       = PPC_FLAGS_PPC32,
-        .msr_mask    = 0x000000000005FF77,
+        .msr_mask    = 0x000000000005FF77ULL,
     },
     /* Fallback */
     {
         .name        = "ppc",
         .pvr         = CPU_PPC_604,
-        .pvr_mask    = 0xFFFF0000,
+        .pvr_mask    = 0xFFFFFFFF,
         .insns_flags = PPC_INSNS_PPC32,
         .flags       = PPC_FLAGS_PPC32,
-        .msr_mask    = 0x000000000005FF77,
+        .msr_mask    = 0x000000000005FF77ULL,
     },
 };
 
@@ -2058,7 +3930,7 @@
     int i;
 
     for (i = 0; ; i++) {
-        (*cpu_fprintf)(f, "PowerPC '%s' PVR %08x mask %08x\n",
+        (*cpu_fprintf)(f, "PowerPC %16s PVR %08x mask %08x\n",
                        ppc_defs[i].name,
                        ppc_defs[i].pvr, ppc_defs[i].pvr_mask);
         if (strcmp(ppc_defs[i].name, "ppc") == 0)

Modified: trunk/src/host/qemu-neo1973/target-sh4/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sh4/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -121,9 +121,8 @@
 
 CPUSH4State *cpu_sh4_init(void);
 int cpu_sh4_exec(CPUSH4State * s);
-struct siginfo;
-int cpu_sh4_signal_handler(int hostsignum, struct siginfo *info,
-			   void *puc);
+int cpu_sh4_signal_handler(int host_signum, void *pinfo, 
+                           void *puc);
 
 #include "softfloat.h"
 

Modified: trunk/src/host/qemu-neo1973/target-sh4/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sh4/helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -53,7 +53,7 @@
     return 1;
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
 {
     return addr;
 }
@@ -429,7 +429,7 @@
     return tlb_set_page(env, address, physical, prot, is_user, is_softmmu);
 }
 
-target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
 {
     target_ulong physical;
     int prot;

Modified: trunk/src/host/qemu-neo1973/target-sh4/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sh4/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -737,7 +737,7 @@
 
 void OPPROTO op_dec8_rN(void)
 {
-    env->gregs[PARAM1] -= 4;
+    env->gregs[PARAM1] -= 8;
     RETURN();
 }
 
@@ -761,7 +761,7 @@
 
 void OPPROTO op_inc8_rN(void)
 {
-    env->gregs[PARAM1] += 4;
+    env->gregs[PARAM1] += 8;
     RETURN();
 }
 

Modified: trunk/src/host/qemu-neo1973/target-sh4/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sh4/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sh4/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1003,8 +1003,8 @@
 	LDST(mach, 0x400a, 0x4006, lds, 0x000a, 0x4002, sts,)
 	LDST(macl, 0x401a, 0x4016, lds, 0x001a, 0x4012, sts,)
 	LDST(pr, 0x402a, 0x4026, lds, 0x002a, 0x4022, sts,)
-	LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x0052, sts,)
-	LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x0062, sts, ctx->flags |=
+	LDST(fpul, 0x405a, 0x4056, lds, 0x005a, 0x4052, sts,)
+	LDST(fpscr, 0x406a, 0x4066, lds, 0x006a, 0x4062, sts, ctx->flags |=
 	     MODE_CHANGE;)
     case 0x00c3:		/* movca.l R0, at Rm */
 	gen_op_movl_rN_T0(REG(0));
@@ -1087,8 +1087,9 @@
     ctx->flags |= BRANCH_EXCEPTION;
 }
 
-int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
-				   int search_pc)
+static inline int
+gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
+                               int search_pc)
 {
     DisasContext ctx;
     target_ulong pc_start;

Modified: trunk/src/host/qemu-neo1973/target-sparc/cpu.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/cpu.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sparc/cpu.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -35,10 +35,14 @@
 #define TT_NFPU_INSN 0x04
 #define TT_WIN_OVF  0x05
 #define TT_WIN_UNF  0x06 
+#define TT_UNALIGNED 0x07
 #define TT_FP_EXCP  0x08
 #define TT_DFAULT   0x09
+#define TT_TOVF     0x0a
 #define TT_EXTINT   0x10
+#define TT_DATA_ACCESS 0x29
 #define TT_DIV_ZERO 0x2a
+#define TT_NCP_INSN 0x24
 #define TT_TRAP     0x80
 #else
 #define TT_TFAULT   0x08
@@ -47,11 +51,14 @@
 #define TT_PRIV_INSN 0x11
 #define TT_NFPU_INSN 0x20
 #define TT_FP_EXCP  0x21
+#define TT_TOVF     0x23
 #define TT_CLRWIN   0x24
 #define TT_DIV_ZERO 0x28
 #define TT_DFAULT   0x30
 #define TT_DMISS    0x31
-#define TT_DPROT    0x32
+#define TT_DATA_ACCESS 0x32
+#define TT_DPROT    0x33
+#define TT_UNALIGNED 0x34
 #define TT_PRIV_ACT 0x37
 #define TT_EXTINT   0x40
 #define TT_SPILL    0x80
@@ -124,6 +131,7 @@
 #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
 #define FSR_FTT_IEEE_EXCP (1 << 14)
 #define FSR_FTT_UNIMPFPOP (3 << 14)
+#define FSR_FTT_SEQ_ERROR (4 << 14)
 #define FSR_FTT_INVAL_FPR (6 << 14)
 
 #define FSR_FCC1  (1<<11)
@@ -150,6 +158,8 @@
 /* 2 <= NWINDOWS <= 32. In QEMU it must also be a power of two. */
 #define NWINDOWS  8
 
+typedef struct sparc_def_t sparc_def_t;
+
 typedef struct CPUSPARCState {
     target_ulong gregs[8]; /* general registers */
     target_ulong *regwptr; /* pointer to current register window */
@@ -168,6 +178,7 @@
     int      psret;    /* enable traps */
     uint32_t psrpil;   /* interrupt level */
     int      psref;    /* enable fpu */
+    target_ulong version;
     jmp_buf  jmp_env;
     int user_mode_only;
     int exception_index;
@@ -213,10 +224,12 @@
     uint64_t bgregs[8]; /* backup for normal global registers */
     uint64_t igregs[8]; /* interrupt general registers */
     uint64_t mgregs[8]; /* mmu general registers */
-    uint64_t version;
     uint64_t fprs;
     uint64_t tick_cmpr, stick_cmpr;
     uint64_t gsr;
+    uint32_t gl; // UA2005
+    /* UA 2005 hyperprivileged registers */
+    uint64_t hpstate, htstate[MAXTL], hintp, htba, hver, hstick_cmpr, ssr;
 #endif
 #if !defined(TARGET_SPARC64) && !defined(reg_T2)
     target_ulong t2;
@@ -231,22 +244,22 @@
 #define PUT_FSR64(env, val) do { uint64_t _tmp = val;	\
 	env->fsr = _tmp & 0x3fcfc1c3ffULL;		\
     } while (0)
-// Manuf 0x17, version 0x11, mask 0 (UltraSparc-II)
-#define GET_VER(env) ((0x17ULL << 48) | (0x11ULL << 32) |		\
-		      (0 << 24) | (MAXTL << 8) | (NWINDOWS - 1))
 #else
 #define GET_FSR32(env) (env->fsr)
-#define PUT_FSR32(env, val) do { uint32_t _tmp = val;	\
-	env->fsr = _tmp & 0xcfc1ffff;			\
+#define PUT_FSR32(env, val) do { uint32_t _tmp = val;                   \
+        env->fsr = (_tmp & 0xcfc1dfff) | (env->fsr & 0x000e0000);       \
     } while (0)
 #endif
 
 CPUSPARCState *cpu_sparc_init(void);
 int cpu_sparc_exec(CPUSPARCState *s);
 int cpu_sparc_close(CPUSPARCState *s);
+int sparc_find_by_name (const unsigned char *name, const sparc_def_t **def);
+void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
+                                                 ...));
+int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def);
 
-/* Fake impl 0, version 4 */
-#define GET_PSR(env) ((0 << 28) | (4 << 24) | (env->psr & PSR_ICC) |	\
+#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) |             \
 		      (env->psref? PSR_EF : 0) |			\
 		      (env->psrpil << 8) |				\
 		      (env->psrs? PSR_S : 0) |				\
@@ -264,7 +277,7 @@
 	env->psrs = (_tmp & PSR_S)? 1 : 0;				\
 	env->psrps = (_tmp & PSR_PS)? 1 : 0;				\
 	env->psret = (_tmp & PSR_ET)? 1 : 0;				\
-	cpu_set_cwp(env, _tmp & PSR_CWP & (NWINDOWS - 1));		\
+        cpu_set_cwp(env, _tmp & PSR_CWP);                               \
     } while (0)
 
 #ifdef TARGET_SPARC64
@@ -275,8 +288,8 @@
     } while (0)
 #endif
 
-struct siginfo;
-int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
+int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
+void raise_exception(int tt);
 
 #include "cpu-all.h"
 

Modified: trunk/src/host/qemu-neo1973/target-sparc/exec.h
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/exec.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sparc/exec.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,9 +1,10 @@
 #ifndef EXEC_SPARC_H
 #define EXEC_SPARC_H 1
+#include "config.h"
 #include "dyngen-exec.h"
-#include "config.h"
 
 register struct CPUSPARCState *env asm(AREG0);
+
 #ifdef TARGET_SPARC64
 #define T0 (env->t0)
 #define T1 (env->t1)
@@ -15,7 +16,11 @@
 
 #undef REG_REGWPTR // Broken
 #ifdef REG_REGWPTR
+#if defined(__sparc__)
+register uint32_t *REGWPTR asm(AREG4);
+#else
 register uint32_t *REGWPTR asm(AREG3);
+#endif
 #define reg_REGWPTR
 
 #ifdef AREG4
@@ -28,9 +33,9 @@
 #else
 #define REGWPTR env->regwptr
 register uint32_t T2 asm(AREG3);
+#endif
 #define reg_T2
 #endif
-#endif
 
 #define FT0 (env->ft0)
 #define FT1 (env->ft1)
@@ -56,6 +61,8 @@
 void do_fsqrtd(void);
 void do_fcmps(void);
 void do_fcmpd(void);
+void do_fcmpes(void);
+void do_fcmped(void);
 #ifdef TARGET_SPARC64
 void do_fabsd(void);
 void do_fcmps_fcc1(void);
@@ -64,6 +71,12 @@
 void do_fcmpd_fcc2(void);
 void do_fcmps_fcc3(void);
 void do_fcmpd_fcc3(void);
+void do_fcmpes_fcc1(void);
+void do_fcmped_fcc1(void);
+void do_fcmpes_fcc2(void);
+void do_fcmped_fcc2(void);
+void do_fcmpes_fcc3(void);
+void do_fcmped_fcc3(void);
 void do_popc();
 void do_wrpstate();
 void do_done();
@@ -74,6 +87,7 @@
 void do_ldd_raw(target_ulong addr);
 void do_interrupt(int intno);
 void raise_exception(int tt);
+void check_ieee_exceptions();
 void memcpy32(target_ulong *dst, const target_ulong *src);
 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev);
 void dump_mmu(CPUState *env);

Modified: trunk/src/host/qemu-neo1973/target-sparc/op.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sparc/op.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -472,6 +472,96 @@
     FORCE_RET();
 }
 
+void OPPROTO op_tadd_T1_T0_cc(void)
+{
+    target_ulong src1;
+
+    src1 = T0;
+    T0 += T1;
+    env->psr = 0;
+#ifdef TARGET_SPARC64
+    if (!(T0 & 0xffffffff))
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
+	env->psr |= PSR_CARRY;
+    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
+	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+	env->psr |= PSR_OVF;
+    if ((src1 & 0x03) || (T1 & 0x03))
+	env->psr |= PSR_OVF;
+
+    env->xcc = 0;
+    if (!T0)
+	env->xcc |= PSR_ZERO;
+    if ((int64_t) T0 < 0)
+	env->xcc |= PSR_NEG;
+    if (T0 < src1)
+	env->xcc |= PSR_CARRY;
+    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
+	env->xcc |= PSR_OVF;
+#else
+    if (!T0)
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if (T0 < src1)
+	env->psr |= PSR_CARRY;
+    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
+	env->psr |= PSR_OVF;
+    if ((src1 & 0x03) || (T1 & 0x03))
+	env->psr |= PSR_OVF;
+#endif
+    FORCE_RET();
+}
+
+void OPPROTO op_tadd_T1_T0_ccTV(void)
+{
+    target_ulong src1;
+
+    if ((T0 & 0x03) || (T1 & 0x03))
+        raise_exception(TT_TOVF);
+
+    src1 = T0;
+    T0 += T1;
+
+#ifdef TARGET_SPARC64
+    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
+	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        raise_exception(TT_TOVF);
+#else
+    if ((src1 & 0x03) || (T1 & 0x03))
+        raise_exception(TT_TOVF);
+#endif
+
+    env->psr = 0;
+#ifdef TARGET_SPARC64
+    if (!(T0 & 0xffffffff))
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
+	env->psr |= PSR_CARRY;
+
+    env->xcc = 0;
+    if (!T0)
+	env->xcc |= PSR_ZERO;
+    if ((int64_t) T0 < 0)
+	env->xcc |= PSR_NEG;
+    if (T0 < src1)
+	env->xcc |= PSR_CARRY;
+#else
+    if (!T0)
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if (T0 < src1)
+	env->psr |= PSR_CARRY;
+#endif
+    FORCE_RET();
+}
+
 void OPPROTO op_sub_T1_T0(void)
 {
     T0 -= T1;
@@ -582,6 +672,96 @@
     FORCE_RET();
 }
 
+void OPPROTO op_tsub_T1_T0_cc(void)
+{
+    target_ulong src1;
+
+    src1 = T0;
+    T0 -= T1;
+    env->psr = 0;
+#ifdef TARGET_SPARC64
+    if (!(T0 & 0xffffffff))
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
+	env->psr |= PSR_CARRY;
+    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
+	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+	env->psr |= PSR_OVF;
+    if ((src1 & 0x03) || (T1 & 0x03))
+	env->psr |= PSR_OVF;
+
+    env->xcc = 0;
+    if (!T0)
+	env->xcc |= PSR_ZERO;
+    if ((int64_t) T0 < 0)
+	env->xcc |= PSR_NEG;
+    if (src1 < T1)
+	env->xcc |= PSR_CARRY;
+    if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
+	env->xcc |= PSR_OVF;
+#else
+    if (!T0)
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if (src1 < T1)
+	env->psr |= PSR_CARRY;
+    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
+	env->psr |= PSR_OVF;
+    if ((src1 & 0x03) || (T1 & 0x03))
+	env->psr |= PSR_OVF;
+#endif
+    FORCE_RET();
+}
+
+void OPPROTO op_tsub_T1_T0_ccTV(void)
+{
+    target_ulong src1;
+
+    if ((T0 & 0x03) || (T1 & 0x03))
+        raise_exception(TT_TOVF);
+
+    src1 = T0;
+    T0 -= T1;
+
+#ifdef TARGET_SPARC64
+    if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
+	 ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
+        raise_exception(TT_TOVF);
+#else
+    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
+        raise_exception(TT_TOVF);
+#endif
+
+    env->psr = 0;
+#ifdef TARGET_SPARC64
+    if (!(T0 & 0xffffffff))
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
+	env->psr |= PSR_CARRY;
+
+    env->xcc = 0;
+    if (!T0)
+	env->xcc |= PSR_ZERO;
+    if ((int64_t) T0 < 0)
+	env->xcc |= PSR_NEG;
+    if (src1 < T1)
+	env->xcc |= PSR_CARRY;
+#else
+    if (!T0)
+	env->psr |= PSR_ZERO;
+    if ((int32_t) T0 < 0)
+	env->psr |= PSR_NEG;
+    if (src1 < T1)
+	env->psr |= PSR_CARRY;
+#endif
+    FORCE_RET();
+}
+
 void OPPROTO op_and_T1_T0(void)
 {
     T0 &= T1;
@@ -671,6 +851,11 @@
 
     x0 = T0 | ((uint64_t) (env->y) << 32);
     x1 = T1;
+
+    if (x1 == 0) {
+        raise_exception(TT_DIV_ZERO);
+    }
+
     x0 = x0 / x1;
     if (x0 > 0xffffffff) {
 	T0 = 0xffffffff;
@@ -689,6 +874,11 @@
 
     x0 = T0 | ((int64_t) (env->y) << 32);
     x1 = T1;
+
+    if (x1 == 0) {
+        raise_exception(TT_DIV_ZERO);
+    }
+
     x0 = x0 / x1;
     if ((int32_t) x0 != x0) {
 	T0 = x0 < 0? 0x80000000: 0x7fffffff;
@@ -736,12 +926,18 @@
 
 void OPPROTO op_udivx_T1_T0(void)
 {
+    if (T1 == 0) {
+        raise_exception(TT_DIV_ZERO);
+    }
     T0 /= T1;
     FORCE_RET();
 }
 
 void OPPROTO op_sdivx_T1_T0(void)
 {
+    if (T1 == 0) {
+        raise_exception(TT_DIV_ZERO);
+    }
     if (T0 == INT64_MIN && T1 == -1)
 	T0 = INT64_MIN;
     else
@@ -775,38 +971,43 @@
 
 void OPPROTO op_sll(void)
 {
-    T0 <<= T1;
+    T0 <<= (T1 & 0x1f);
 }
 
 #ifdef TARGET_SPARC64
+void OPPROTO op_sllx(void)
+{
+    T0 <<= (T1 & 0x3f);
+}
+
 void OPPROTO op_srl(void)
 {
-    T0 = (T0 & 0xffffffff) >> T1;
+    T0 = (T0 & 0xffffffff) >> (T1 & 0x1f);
 }
 
 void OPPROTO op_srlx(void)
 {
-    T0 >>= T1;
+    T0 >>= (T1 & 0x3f);
 }
 
 void OPPROTO op_sra(void)
 {
-    T0 = ((int32_t) (T0 & 0xffffffff)) >> T1;
+    T0 = ((int32_t) (T0 & 0xffffffff)) >> (T1 & 0x1f);
 }
 
 void OPPROTO op_srax(void)
 {
-    T0 = ((int64_t) T0) >> T1;
+    T0 = ((int64_t) T0) >> (T1 & 0x3f);
 }
 #else
 void OPPROTO op_srl(void)
 {
-    T0 >>= T1;
+    T0 >>= (T1 & 0x1f);
 }
 
 void OPPROTO op_sra(void)
 {
-    T0 = ((int32_t) T0) >> T1;
+    T0 = ((int32_t) T0) >> (T1 & 0x1f);
 }
 #endif
 
@@ -900,7 +1101,7 @@
 
 void OPPROTO op_wrtick(void)
 {
-    // XXX write cycle counter and bit 31
+    T0 = 0; // XXX write cycle counter and bit 31
 }
 
 void OPPROTO op_rdtpc(void)
@@ -1291,7 +1492,10 @@
 
 void OPPROTO op_movl_npc_T0(void)
 {
-    env->npc = T0;
+    if (T0 & 0x3)
+	raise_exception(TT_UNALIGNED);
+    else
+	env->npc = T0;
 }
 
 void OPPROTO op_mov_pc_npc(void)
@@ -1339,16 +1543,25 @@
     helper_flush(T0);
 }
 
+void OPPROTO op_clear_ieee_excp_and_FTT(void)
+{
+    env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);;
+}
+
 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
 
 #define F_BINOP(name)                                           \
     F_OP(name, s)                                               \
     {                                                           \
+	set_float_exception_flags(0, &env->fp_status);		\
         FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
+	check_ieee_exceptions();				\
     }                                                           \
     F_OP(name, d)                                               \
     {                                                           \
+	set_float_exception_flags(0, &env->fp_status);		\
         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
+	check_ieee_exceptions();				\
     }
 
 F_BINOP(add);
@@ -1359,9 +1572,11 @@
 
 void OPPROTO op_fsmuld(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
                       float32_to_float64(FT1, &env->fp_status),
                       &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #define F_HELPER(name)    \
@@ -1387,6 +1602,7 @@
 }
 
 F_HELPER(cmp);
+F_HELPER(cmpe);
 
 #ifdef TARGET_SPARC64
 F_OP(neg, d)
@@ -1428,6 +1644,37 @@
 {
     do_fcmpd_fcc3();
 }
+
+void OPPROTO op_fcmpes_fcc1(void)
+{
+    do_fcmpes_fcc1();
+}
+
+void OPPROTO op_fcmped_fcc1(void)
+{
+    do_fcmped_fcc1();
+}
+
+void OPPROTO op_fcmpes_fcc2(void)
+{
+    do_fcmpes_fcc2();
+}
+
+void OPPROTO op_fcmped_fcc2(void)
+{
+    do_fcmped_fcc2();
+}
+
+void OPPROTO op_fcmpes_fcc3(void)
+{
+    do_fcmpes_fcc3();
+}
+
+void OPPROTO op_fcmped_fcc3(void)
+{
+    do_fcmped_fcc3();
+}
+
 #endif
 
 /* Integer to float conversion.  */
@@ -1436,23 +1683,31 @@
 #else
 F_OP(ito, s)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 F_OP(ito, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #ifdef TARGET_SPARC64
 F_OP(xto, s)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 F_OP(xto, d)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 #endif
 #endif
@@ -1461,34 +1716,46 @@
 /* floating point conversion */
 void OPPROTO op_fdtos(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = float64_to_float32(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fstod(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float32_to_float64(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 /* Float to integer conversion.  */
 void OPPROTO op_fstoi(void)
 {
-    *((int32_t *)&FT0) = float32_to_int32(FT1, &env->fp_status);
+    set_float_exception_flags(0, &env->fp_status);
+    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fdtoi(void)
 {
-    *((int32_t *)&FT0) = float64_to_int32(DT1, &env->fp_status);
+    set_float_exception_flags(0, &env->fp_status);
+    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 #ifdef TARGET_SPARC64
 void OPPROTO op_fstox(void)
 {
-    *((int64_t *)&DT0) = float32_to_int64(FT1, &env->fp_status);
+    set_float_exception_flags(0, &env->fp_status);
+    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fdtox(void)
 {
-    *((int64_t *)&DT0) = float64_to_int64(DT1, &env->fp_status);
+    set_float_exception_flags(0, &env->fp_status);
+    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void OPPROTO op_fmovs_cc(void)
@@ -1557,8 +1824,7 @@
 
 void OPPROTO op_sir(void)
 {
-    // XXX
-
+    T0 = 0;  // XXX
 }
 
 void OPPROTO op_ld_asi_reg()
@@ -1585,6 +1851,44 @@
 }
 
 #ifdef TARGET_SPARC64
+// This function uses non-native bit order
+#define GET_FIELD(X, FROM, TO)                                  \
+    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
+
+// This function uses the order in the manuals, i.e. bit 0 is 2^0
+#define GET_FIELD_SP(X, FROM, TO)               \
+    GET_FIELD(X, 63 - (TO), 63 - (FROM))
+
+void OPPROTO op_array8()
+{
+    T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
+        (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
+        (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
+        (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
+        (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
+        (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
+}
+
+void OPPROTO op_array16()
+{
+    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
+          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
+          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
+          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
+          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
+          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
+}
+
+void OPPROTO op_array32()
+{
+    T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
+          (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
+          (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
+          (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
+          (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
+          (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
+}
+
 void OPPROTO op_alignaddr()
 {
     uint64_t tmp;
@@ -1601,6 +1905,440 @@
 
     tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
     tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
-    (*((uint64_t *)&DT0)) = tmp;
+    *((uint64_t *)&DT0) = tmp;
 }
+
+void OPPROTO op_movl_FT0_0(void)
+{
+    *((uint32_t *)&FT0) = 0;
+}
+
+void OPPROTO op_movl_DT0_0(void)
+{
+    *((uint64_t *)&DT0) = 0;
+}
+
+void OPPROTO op_movl_FT0_1(void)
+{
+    *((uint32_t *)&FT0) = 0xffffffff;
+}
+
+void OPPROTO op_movl_DT0_1(void)
+{
+    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
+}
+
+void OPPROTO op_fnot(void)
+{
+    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fnots(void)
+{
+    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fnor(void)
+{
+    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
+}
+
+void OPPROTO op_fnors(void)
+{
+    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
+}
+
+void OPPROTO op_for(void)
+{
+    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fors(void)
+{
+    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fxor(void)
+{
+    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fxors(void)
+{
+    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fand(void)
+{
+    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fands(void)
+{
+    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fornot(void)
+{
+    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fornots(void)
+{
+    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fandnot(void)
+{
+    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fandnots(void)
+{
+    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
+}
+
+void OPPROTO op_fnand(void)
+{
+    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
+}
+
+void OPPROTO op_fnands(void)
+{
+    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
+}
+
+void OPPROTO op_fxnor(void)
+{
+    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
+}
+
+void OPPROTO op_fxnors(void)
+{
+    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
+}
+
+#ifdef WORDS_BIGENDIAN
+#define VIS_B64(n) b[7 - (n)]
+#define VIS_W64(n) w[3 - (n)]
+#define VIS_SW64(n) sw[3 - (n)]
+#define VIS_L64(n) l[1 - (n)]
+#define VIS_B32(n) b[3 - (n)]
+#define VIS_W32(n) w[1 - (n)]
+#else
+#define VIS_B64(n) b[n]
+#define VIS_W64(n) w[n]
+#define VIS_SW64(n) sw[n]
+#define VIS_L64(n) l[n]
+#define VIS_B32(n) b[n]
+#define VIS_W32(n) w[n]
 #endif
+
+typedef union {
+    uint8_t b[8];
+    uint16_t w[4];
+    int16_t sw[4];
+    uint32_t l[2];
+    float64 d;
+} vis64;
+
+typedef union {
+    uint8_t b[4];
+    uint16_t w[2];
+    uint32_t l;
+    float32 f;
+} vis32;
+
+void OPPROTO op_fpmerge(void)
+{
+    vis64 s, d;
+
+    s.d = DT0;
+    d.d = DT1;
+
+    // Reverse calculation order to handle overlap
+    d.VIS_B64(7) = s.VIS_B64(3);
+    d.VIS_B64(6) = d.VIS_B64(3);
+    d.VIS_B64(5) = s.VIS_B64(2);
+    d.VIS_B64(4) = d.VIS_B64(2);
+    d.VIS_B64(3) = s.VIS_B64(1);
+    d.VIS_B64(2) = d.VIS_B64(1);
+    d.VIS_B64(1) = s.VIS_B64(0);
+    //d.VIS_B64(0) = d.VIS_B64(0);
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmul8x16(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f)                                    \
+        tmp += 0x100;                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmul8x16al(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f)                                    \
+        tmp += 0x100;                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmul8x16au(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                 \
+    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
+    if ((tmp & 0xff) > 0x7f)                                    \
+        tmp += 0x100;                                           \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmul8sux16(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
+    if ((tmp & 0xff) > 0x7f)                                            \
+        tmp += 0x100;                                                   \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmul8ulx16(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
+    if ((tmp & 0xff) > 0x7f)                                            \
+        tmp += 0x100;                                                   \
+    d.VIS_W64(r) = tmp >> 8;
+
+    PMUL(0);
+    PMUL(1);
+    PMUL(2);
+    PMUL(3);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmuld8sux16(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
+    if ((tmp & 0xff) > 0x7f)                                            \
+        tmp += 0x100;                                                   \
+    d.VIS_L64(r) = tmp;
+
+    // Reverse calculation order to handle overlap
+    PMUL(1);
+    PMUL(0);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fmuld8ulx16(void)
+{
+    vis64 s, d;
+    uint32_t tmp;
+
+    s.d = DT0;
+    d.d = DT1;
+
+#define PMUL(r)                                                         \
+    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
+    if ((tmp & 0xff) > 0x7f)                                            \
+        tmp += 0x100;                                                   \
+    d.VIS_L64(r) = tmp;
+
+    // Reverse calculation order to handle overlap
+    PMUL(1);
+    PMUL(0);
+#undef PMUL
+
+    DT0 = d.d;
+}
+
+void OPPROTO op_fexpand(void)
+{
+    vis32 s;
+    vis64 d;
+
+    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
+    d.d = DT1;
+    d.VIS_L64(0) = s.VIS_W32(0) << 4;
+    d.VIS_L64(1) = s.VIS_W32(1) << 4;
+    d.VIS_L64(2) = s.VIS_W32(2) << 4;
+    d.VIS_L64(3) = s.VIS_W32(3) << 4;
+
+    DT0 = d.d;
+}
+
+#define VIS_OP(name, F)                                 \
+    void OPPROTO name##16(void)                         \
+    {                                                   \
+        vis64 s, d;                                     \
+                                                        \
+        s.d = DT0;                                      \
+        d.d = DT1;                                      \
+                                                        \
+        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
+        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
+        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
+        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
+                                                        \
+        DT0 = d.d;                                      \
+    }                                                   \
+                                                        \
+    void OPPROTO name##16s(void)                        \
+    {                                                   \
+        vis32 s, d;                                     \
+                                                        \
+        s.f = FT0;                                      \
+        d.f = FT1;                                      \
+                                                        \
+        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
+        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
+                                                        \
+        FT0 = d.f;                                      \
+    }                                                   \
+                                                        \
+    void OPPROTO name##32(void)                         \
+    {                                                   \
+        vis64 s, d;                                     \
+                                                        \
+        s.d = DT0;                                      \
+        d.d = DT1;                                      \
+                                                        \
+        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
+        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
+                                                        \
+        DT0 = d.d;                                      \
+    }                                                   \
+                                                        \
+    void OPPROTO name##32s(void)                        \
+    {                                                   \
+        vis32 s, d;                                     \
+                                                        \
+        s.f = FT0;                                      \
+        d.f = FT1;                                      \
+                                                        \
+        d.l = F(d.l, s.l);                              \
+                                                        \
+        FT0 = d.f;                                      \
+    }
+
+#define FADD(a, b) ((a) + (b))
+#define FSUB(a, b) ((a) - (b))
+VIS_OP(op_fpadd, FADD)
+VIS_OP(op_fpsub, FSUB)
+
+#define VIS_CMPOP(name, F)                                        \
+    void OPPROTO name##16(void)                                   \
+    {                                                             \
+        vis64 s, d;                                               \
+                                                                  \
+        s.d = DT0;                                                \
+        d.d = DT1;                                                \
+                                                                  \
+        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
+        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
+        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
+        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
+                                                                  \
+        DT0 = d.d;                                                \
+    }                                                             \
+                                                                  \
+    void OPPROTO name##32(void)                                   \
+    {                                                             \
+        vis64 s, d;                                               \
+                                                                  \
+        s.d = DT0;                                                \
+        d.d = DT1;                                                \
+                                                                  \
+        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
+        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
+                                                                  \
+        DT0 = d.d;                                                \
+    }
+
+#define FCMPGT(a, b) ((a) > (b))
+#define FCMPEQ(a, b) ((a) == (b))
+#define FCMPLE(a, b) ((a) <= (b))
+#define FCMPNE(a, b) ((a) != (b))
+
+VIS_CMPOP(op_fcmpgt, FCMPGT)
+VIS_CMPOP(op_fcmpeq, FCMPEQ)
+VIS_CMPOP(op_fcmple, FCMPLE)
+VIS_CMPOP(op_fcmpne, FCMPNE)
+
+#endif

Modified: trunk/src/host/qemu-neo1973/target-sparc/op_helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/op_helper.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sparc/op_helper.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2,6 +2,7 @@
 
 //#define DEBUG_PCALL
 //#define DEBUG_MMU
+//#define DEBUG_UNALIGNED
 
 void raise_exception(int tt)
 {
@@ -9,10 +10,43 @@
     cpu_loop_exit();
 }   
 
+void check_ieee_exceptions()
+{
+     T0 = get_float_exception_flags(&env->fp_status);
+     if (T0)
+     {
+	/* Copy IEEE 754 flags into FSR */
+	if (T0 & float_flag_invalid)
+	    env->fsr |= FSR_NVC;
+	if (T0 & float_flag_overflow)
+	    env->fsr |= FSR_OFC;
+	if (T0 & float_flag_underflow)
+	    env->fsr |= FSR_UFC;
+	if (T0 & float_flag_divbyzero)
+	    env->fsr |= FSR_DZC;
+	if (T0 & float_flag_inexact)
+	    env->fsr |= FSR_NXC;
+
+	if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
+	{
+	    /* Unmasked exception, generate a trap */
+	    env->fsr |= FSR_FTT_IEEE_EXCP;
+	    raise_exception(TT_FP_EXCP);
+	}
+	else
+	{
+	    /* Accumulate exceptions */
+	    env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
+	}
+     }
+}
+
 #ifdef USE_INT_TO_FLOAT_HELPERS
 void do_fitos(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void do_fitod(void)
@@ -35,23 +69,29 @@
 
 void do_fsqrts(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     FT0 = float32_sqrt(FT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
 void do_fsqrtd(void)
 {
+    set_float_exception_flags(0, &env->fp_status);
     DT0 = float64_sqrt(DT1, &env->fp_status);
+    check_ieee_exceptions();
 }
 
-#define GEN_FCMP(name, size, reg1, reg2, FS)                            \
+#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
     void glue(do_, name) (void)                                         \
     {                                                                   \
         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
         case float_relation_unordered:                                  \
             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
-            if (env->fsr & FSR_NVM) {                                   \
+            if ((env->fsr & FSR_NVM) || TRAP) {                         \
                 env->fsr |= T0;                                         \
+                env->fsr |= FSR_NVC;                                    \
+                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
                 raise_exception(TT_FP_EXCP);                            \
             } else {                                                    \
                 env->fsr |= FSR_NVA;                                    \
@@ -70,18 +110,30 @@
         env->fsr |= T0;                                                 \
     }
 
-GEN_FCMP(fcmps, float32, FT0, FT1, 0);
-GEN_FCMP(fcmpd, float64, DT0, DT1, 0);
+GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
+GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
 
+GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
+GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
+
 #ifdef TARGET_SPARC64
-GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);
-GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);
+GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
+GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
 
-GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);
-GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);
+GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
+GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
 
-GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);
-GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);
+GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
+GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
+
+GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
+GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
+
+GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
+GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
+
+GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
+GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
 #endif
 
 #if defined(CONFIG_USER_ONLY) 
@@ -615,6 +667,9 @@
 {
     unsigned int cwp;
 
+    if (env->psret == 1)
+        raise_exception(TT_ILL_INSN);
+
     env->psret = 1;
     cwp = (env->cwp + 1) & (NWINDOWS - 1); 
     if (env->wim & (1 << cwp)) {
@@ -655,7 +710,10 @@
 #ifndef TARGET_SPARC64
 void do_wrpsr()
 {
-    PUT_PSR(env, T0);
+    if ((T0 & PSR_CWP) >= NWINDOWS)
+        raise_exception(TT_ILL_INSN);
+    else
+        PUT_PSR(env, T0);
 }
 
 void do_rdpsr()
@@ -866,7 +924,11 @@
 
 #if !defined(CONFIG_USER_ONLY) 
 
+static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
+                                void *retaddr);
+
 #define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
 #define GETPC() (__builtin_return_address(0))
 
 #define SHIFT 0
@@ -881,6 +943,14 @@
 #define SHIFT 3
 #include "softmmu_template.h"
 
+static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
+                                void *retaddr)
+{
+#ifdef DEBUG_UNALIGNED
+    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
+#endif
+    raise_exception(TT_UNALIGNED);
+}
 
 /* try to fill the TLB and return an exception if error. If retaddr is
    NULL, it means that the function was called in C code (i.e. not

Modified: trunk/src/host/qemu-neo1973/target-sparc/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-sparc/translate.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/target-sparc/translate.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -25,9 +25,7 @@
    Rest of V9 instructions, VIS instructions
    NPC/PC static optimisations (use JUMP_TB when possible)
    Optimize synthetic instructions
-   Optional alignment check
    128-bit float
-   Tagged add/sub
 */
 
 #include <stdarg.h>
@@ -56,6 +54,13 @@
     struct TranslationBlock *tb;
 } DisasContext;
 
+struct sparc_def_t {
+    const unsigned char *name;
+    target_ulong iu_version;
+    uint32_t fpu_version;
+    uint32_t mmu_version;
+};
+
 static uint16_t *gen_opc_ptr;
 static uint32_t *gen_opparam_ptr;
 extern FILE *logfile;
@@ -84,7 +89,7 @@
 #ifdef TARGET_SPARC64
 #define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
 #else
-#define DFPREG(r) (r)
+#define DFPREG(r) (r & 0x1e)
 #endif
 
 #ifdef USE_DIRECT_JUMP
@@ -103,7 +108,7 @@
 
 static void disas_sparc_insn(DisasContext * dc);
 
-static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
+static GenOpFunc * const gen_op_movl_TN_reg[2][32] = {
     {
      gen_op_movl_g0_T0,
      gen_op_movl_g1_T0,
@@ -174,7 +179,7 @@
      }
 };
 
-static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
+static GenOpFunc * const gen_op_movl_reg_TN[3][32] = {
     {
      gen_op_movl_T0_g0,
      gen_op_movl_T0_g1,
@@ -279,7 +284,7 @@
      }
 };
 
-static GenOpFunc1 *gen_op_movl_TN_im[3] = {
+static GenOpFunc1 * const gen_op_movl_TN_im[3] = {
     gen_op_movl_T0_im,
     gen_op_movl_T1_im,
     gen_op_movl_T2_im
@@ -294,7 +299,7 @@
 
 #ifdef TARGET_SPARC64
 #define GEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [64] = {                                     \
+static GenOpFunc * const NAME ## _table [64] = {                              \
 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
@@ -314,7 +319,7 @@
 }
 #else
 #define GEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [32] = {                                     \
+static GenOpFunc *const NAME ## _table [32] = {                               \
 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
@@ -345,6 +350,7 @@
 // 'a' versions allowed to user depending on asi
 #if defined(CONFIG_USER_ONLY)
 #define supervisor(dc) 0
+#define hypervisor(dc) 0
 #define gen_op_ldst(name)        gen_op_##name##_raw()
 #define OP_LD_TABLE(width)						\
     static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
@@ -375,7 +381,7 @@
 #else
 #define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
 #define OP_LD_TABLE(width)						\
-    static GenOpFunc *gen_op_##width[] = {				\
+    static GenOpFunc * const gen_op_##width[] = {                       \
 	&gen_op_##width##_user,						\
 	&gen_op_##width##_kernel,					\
     };									\
@@ -400,6 +406,7 @@
     }
 
 #define supervisor(dc) (dc->mem_idx == 1)
+#define hypervisor(dc) (dc->mem_idx == 2)
 #endif
 #else
 #if defined(CONFIG_USER_ONLY)
@@ -409,7 +416,7 @@
 #else
 #define gen_op_ldst(name)        (*gen_op_##name[dc->mem_idx])()
 #define OP_LD_TABLE(width)						      \
-static GenOpFunc *gen_op_##width[] = {                                        \
+static GenOpFunc * const gen_op_##width[] = {                                 \
     &gen_op_##width##_user,                                                   \
     &gen_op_##width##_kernel,                                                 \
 };                                                                            \
@@ -681,7 +688,7 @@
 
 static GenOpFunc * const gen_cond[2][16] = {
     {
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_be,
 	gen_op_eval_ble,
 	gen_op_eval_bl,
@@ -689,7 +696,7 @@
 	gen_op_eval_bcs,
 	gen_op_eval_bneg,
 	gen_op_eval_bvs,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_bne,
 	gen_op_eval_bg,
 	gen_op_eval_bge,
@@ -700,7 +707,7 @@
     },
     {
 #ifdef TARGET_SPARC64
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_xbe,
 	gen_op_eval_xble,
 	gen_op_eval_xbl,
@@ -708,7 +715,7 @@
 	gen_op_eval_xbcs,
 	gen_op_eval_xbneg,
 	gen_op_eval_xbvs,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_xbne,
 	gen_op_eval_xbg,
 	gen_op_eval_xbge,
@@ -722,7 +729,7 @@
 
 static GenOpFunc * const gen_fcond[4][16] = {
     {
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_fbne,
 	gen_op_eval_fblg,
 	gen_op_eval_fbul,
@@ -730,7 +737,7 @@
 	gen_op_eval_fbug,
 	gen_op_eval_fbg,
 	gen_op_eval_fbu,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_fbe,
 	gen_op_eval_fbue,
 	gen_op_eval_fbge,
@@ -741,7 +748,7 @@
     },
 #ifdef TARGET_SPARC64
     {
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_fbne_fcc1,
 	gen_op_eval_fblg_fcc1,
 	gen_op_eval_fbul_fcc1,
@@ -749,7 +756,7 @@
 	gen_op_eval_fbug_fcc1,
 	gen_op_eval_fbg_fcc1,
 	gen_op_eval_fbu_fcc1,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_fbe_fcc1,
 	gen_op_eval_fbue_fcc1,
 	gen_op_eval_fbge_fcc1,
@@ -759,7 +766,7 @@
 	gen_op_eval_fbo_fcc1,
     },
     {
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_fbne_fcc2,
 	gen_op_eval_fblg_fcc2,
 	gen_op_eval_fbul_fcc2,
@@ -767,7 +774,7 @@
 	gen_op_eval_fbug_fcc2,
 	gen_op_eval_fbg_fcc2,
 	gen_op_eval_fbu_fcc2,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_fbe_fcc2,
 	gen_op_eval_fbue_fcc2,
 	gen_op_eval_fbge_fcc2,
@@ -777,7 +784,7 @@
 	gen_op_eval_fbo_fcc2,
     },
     {
-	gen_op_eval_ba,
+	gen_op_eval_bn,
 	gen_op_eval_fbne_fcc3,
 	gen_op_eval_fblg_fcc3,
 	gen_op_eval_fbul_fcc3,
@@ -785,7 +792,7 @@
 	gen_op_eval_fbug_fcc3,
 	gen_op_eval_fbg_fcc3,
 	gen_op_eval_fbu_fcc3,
-	gen_op_eval_bn,
+	gen_op_eval_ba,
 	gen_op_eval_fbe_fcc3,
 	gen_op_eval_fbue_fcc3,
 	gen_op_eval_fbge_fcc3,
@@ -937,6 +944,21 @@
     gen_op_fcmpd_fcc2,
     gen_op_fcmpd_fcc3,
 };
+
+static GenOpFunc * const gen_fcmpes[4] = {
+    gen_op_fcmpes,
+    gen_op_fcmpes_fcc1,
+    gen_op_fcmpes_fcc2,
+    gen_op_fcmpes_fcc3,
+};
+
+static GenOpFunc * const gen_fcmped[4] = {
+    gen_op_fcmped,
+    gen_op_fcmped_fcc1,
+    gen_op_fcmped_fcc2,
+    gen_op_fcmped_fcc3,
+};
+
 #endif
 
 static int gen_trap_ifnofpu(DisasContext * dc)
@@ -1006,6 +1028,11 @@
 		    do_fbranch(dc, target, insn, cc);
 		    goto jmp_insn;
 		}
+#else
+	    case 0x7:		/* CBN+x */
+		{
+		    goto ncp_insn;
+		}
 #endif
 	    case 0x2:		/* BN+x */
 		{
@@ -1124,11 +1151,19 @@
                 rs1 = GET_FIELD(insn, 13, 17);
                 switch(rs1) {
                 case 0: /* rdy */
-		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
+#ifndef TARGET_SPARC64
+                case 0x01 ... 0x0e: /* undefined in the SPARCv8
+                                       manual, rdy on the microSPARC
+                                       II */
+                case 0x0f:          /* stbar in the SPARCv8 manual,
+                                       rdy on the microSPARC II */
+                case 0x10 ... 0x1f: /* implementation-dependent in the
+                                       SPARCv8 manual, rdy on the
+                                       microSPARC II */
+#endif
+                    gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
                     gen_movl_T0_reg(rd);
                     break;
-                case 15: /* stbar / V9 membar */
-		    break; /* no effect? */
 #ifdef TARGET_SPARC64
 		case 0x2: /* V9 rdccr */
                     gen_op_rdccr();
@@ -1154,6 +1189,8 @@
 		    gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
                     gen_movl_T0_reg(rd);
                     break;
+                case 0xf: /* V9 membar */
+                    break; /* no effect */
 		case 0x13: /* Graphics Status */
                     if (gen_trap_ifnofpu(dc))
                         goto jmp_insn;
@@ -1183,14 +1220,40 @@
                     goto illegal_insn;
                 }
 #if !defined(CONFIG_USER_ONLY)
+            } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
 #ifndef TARGET_SPARC64
-            } else if (xop == 0x29) { /* rdpsr / V9 unimp */
 		if (!supervisor(dc))
 		    goto priv_insn;
                 gen_op_rdpsr();
+#else
+                if (!hypervisor(dc))
+                    goto priv_insn;
+                rs1 = GET_FIELD(insn, 13, 17);
+                switch (rs1) {
+                case 0: // hpstate
+                    // gen_op_rdhpstate();
+                    break;
+                case 1: // htstate
+                    // gen_op_rdhtstate();
+                    break;
+                case 3: // hintp
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hintp));
+                    break;
+                case 5: // htba
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, htba));
+                    break;
+                case 6: // hver
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, hver));
+                    break;
+                case 31: // hstick_cmpr
+                    gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+                    break;
+                default:
+                    goto illegal_insn;
+                }
+#endif
                 gen_movl_T0_reg(rd);
                 break;
-#endif
             } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
 		if (!supervisor(dc))
 		    goto priv_insn;
@@ -1242,6 +1305,14 @@
 		case 14: // wstate
 		    gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
 		    break;
+                case 16: // UA2005 gl
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, gl));
+                    break;
+                case 26: // UA2005 strand status
+                    if (!hypervisor(dc))
+                        goto priv_insn;
+                    gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
+                    break;
 		case 31: // ver
 		    gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
 		    break;
@@ -1268,6 +1339,7 @@
 	    } else if (xop == 0x34) {	/* FPU Operations */
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
+		gen_op_clear_ieee_excp_and_FTT();
                 rs1 = GET_FIELD(insn, 13, 17);
 	        rs2 = GET_FIELD(insn, 27, 31);
 	        xop = GET_FIELD(insn, 18, 26);
@@ -1455,6 +1527,7 @@
 #endif
                 if (gen_trap_ifnofpu(dc))
                     goto jmp_insn;
+		gen_op_clear_ieee_excp_and_FTT();
                 rs1 = GET_FIELD(insn, 13, 17);
 	        rs2 = GET_FIELD(insn, 27, 31);
 	        xop = GET_FIELD(insn, 18, 26);
@@ -1632,18 +1705,18 @@
                 	gen_op_load_fpr_FT0(rs1);
                 	gen_op_load_fpr_FT1(rs2);
 #ifdef TARGET_SPARC64
-			gen_fcmps[rd & 3]();
+			gen_fcmpes[rd & 3]();
 #else
-			gen_op_fcmps(); /* XXX should trap if qNaN or sNaN  */
+			gen_op_fcmpes();
 #endif
 			break;
 		    case 0x56: /* fcmped, V9 %fcc */
                 	gen_op_load_fpr_DT0(DFPREG(rs1));
                 	gen_op_load_fpr_DT1(DFPREG(rs2));
 #ifdef TARGET_SPARC64
-			gen_fcmpd[rd & 3]();
+			gen_fcmped[rd & 3]();
 #else
-			gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN  */
+			gen_op_fcmped();
 #endif
 			break;
 		    case 0x57: /* fcmpeq */
@@ -1687,7 +1760,7 @@
 		}
 #endif
 #ifdef TARGET_SPARC64
-	    } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */
+	    } else if (xop == 0x25) { /* sll, V9 sllx */
                 rs1 = GET_FIELD(insn, 13, 17);
 		gen_movl_reg_T0(rs1);
 		if (IS_IMM) {	/* immediate */
@@ -1697,7 +1770,10 @@
                     rs2 = GET_FIELD(insn, 27, 31);
                     gen_movl_reg_T1(rs2);
                 }
-		gen_op_sll();
+		if (insn & (1 << 12))
+		    gen_op_sllx();
+		else
+		    gen_op_sll();
 		gen_movl_T0_reg(rd);
 	    } else if (xop == 0x26) { /* srl, V9 srlx */
                 rs1 = GET_FIELD(insn, 13, 17);
@@ -1730,7 +1806,7 @@
 		    gen_op_sra();
 		gen_movl_T0_reg(rd);
 #endif
-	    } else if (xop < 0x38) {
+            } else if (xop < 0x36) {
                 rs1 = GET_FIELD(insn, 13, 17);
 		gen_movl_reg_T0(rs1);
 		if (IS_IMM) {	/* immediate */
@@ -1833,10 +1909,21 @@
                 } else {
                     switch (xop) {
 		    case 0x20: /* taddcc */
+			gen_op_tadd_T1_T0_cc();
+		        gen_movl_T0_reg(rd);
+			break;
 		    case 0x21: /* tsubcc */
+			gen_op_tsub_T1_T0_cc();
+		        gen_movl_T0_reg(rd);
+			break;
 		    case 0x22: /* taddcctv */
+			gen_op_tadd_T1_T0_ccTV();
+		        gen_movl_T0_reg(rd);
+			break;
 		    case 0x23: /* tsubcctv */
-			goto illegal_insn;
+			gen_op_tsub_T1_T0_ccTV();
+		        gen_movl_T0_reg(rd);
+			break;
                     case 0x24: /* mulscc */
                         gen_op_mulscc_T1_T0();
                         gen_movl_T0_reg(rd);
@@ -1862,7 +1949,17 @@
 				gen_op_xor_T1_T0();
 				gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
                                 break;
-#ifdef TARGET_SPARC64
+#ifndef TARGET_SPARC64
+                            case 0x01 ... 0x0f: /* undefined in the
+                                                   SPARCv8 manual, nop
+                                                   on the microSPARC
+                                                   II */
+                            case 0x10 ... 0x1f: /* implementation-dependent
+                                                   in the SPARCv8
+                                                   manual, nop on the
+                                                   microSPARC II */
+                                break;
+#else
 			    case 0x2: /* V9 wrccr */
                                 gen_op_wrccr();
 				break;
@@ -1870,7 +1967,13 @@
 				gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
 				break;
 			    case 0x6: /* V9 wrfprs */
+				gen_op_xor_T1_T0();
 				gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
+                                save_state(dc);
+                                gen_op_next_insn();
+                                gen_op_movl_T0_0();
+                                gen_op_exit_tb();
+                                dc->is_br = 1;
 				break;
 			    case 0xf: /* V9 sir, nop if user */
 #if !defined(CONFIG_USER_ONLY)
@@ -1930,6 +2033,11 @@
 			    case 1:
 				gen_op_restored();
 				break;
+                            case 2: /* UA2005 allclean */
+                            case 3: /* UA2005 otherw */
+                            case 4: /* UA2005 normalw */
+                            case 5: /* UA2005 invalw */
+                                // XXX
 			    default:
                                 goto illegal_insn;
                             }
@@ -2001,6 +2109,14 @@
 			    case 14: // wstate
 				gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
 				break;
+                            case 16: // UA2005 gl
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, gl));
+                                break;
+                            case 26: // UA2005 strand status
+                                if (!hypervisor(dc))
+                                    goto priv_insn;
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
+                                break;
 			    default:
 				goto illegal_insn;
 			    }
@@ -2009,17 +2125,46 @@
 #endif
                         }
                         break;
+                    case 0x33: /* wrtbr, UA2005 wrhpr */
+                        {
 #ifndef TARGET_SPARC64
-                    case 0x33: /* wrtbr, V9 unimp */
-                        {
 			    if (!supervisor(dc))
 				goto priv_insn;
                             gen_op_xor_T1_T0();
-			    gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
+                            gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
+#else
+                            if (!hypervisor(dc))
+                                goto priv_insn;
+                            gen_op_xor_T1_T0();
+                            switch (rd) {
+                            case 0: // hpstate
+                                // XXX gen_op_wrhpstate();
+                                save_state(dc);
+                                gen_op_next_insn();
+                                gen_op_movl_T0_0();
+                                gen_op_exit_tb();
+                                dc->is_br = 1;
+                                break;
+                            case 1: // htstate
+                                // XXX gen_op_wrhtstate();
+                                break;
+                            case 3: // hintp
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hintp));
+                                break;
+                            case 5: // htba
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
+                                break;
+                            case 31: // hstick_cmpr
+                                gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
+                                break;
+                            case 6: // hver readonly
+                            default:
+                                goto illegal_insn;
+                            }
+#endif
                         }
                         break;
 #endif
-#endif
 #ifdef TARGET_SPARC64
 		    case 0x2c: /* V9 movcc */
 			{
@@ -2087,45 +2232,416 @@
 			    gen_movl_T0_reg(rd);
 			    break;
 			}
-		    case 0x36: /* UltraSparc shutdown, VIS */
-			{
-			    int opf = GET_FIELD_SP(insn, 5, 13);
-                            rs1 = GET_FIELD(insn, 13, 17);
-                            rs2 = GET_FIELD(insn, 27, 31);
-
-                            switch (opf) {
-                            case 0x018: /* VIS I alignaddr */
-                                if (gen_trap_ifnofpu(dc))
-                                    goto jmp_insn;
-                                gen_movl_reg_T0(rs1);
-                                gen_movl_reg_T1(rs2);
-                                gen_op_alignaddr();
-                                gen_movl_T0_reg(rd);
-                                break;
-                            case 0x01a: /* VIS I alignaddrl */
-                                if (gen_trap_ifnofpu(dc))
-                                    goto jmp_insn;
-                                // XXX
-                                break;
-                            case 0x048: /* VIS I faligndata */
-                                if (gen_trap_ifnofpu(dc))
-                                    goto jmp_insn;
-                                gen_op_load_fpr_DT0(rs1);
-                                gen_op_load_fpr_DT1(rs2);
-                                gen_op_faligndata();
-                                gen_op_store_DT0_fpr(rd);
-                                break;
-                            default:
-                                goto illegal_insn;
-                            }
-                            break;
-			}
 #endif
 		    default:
 			goto illegal_insn;
 		    }
 		}
+            } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
 #ifdef TARGET_SPARC64
+                int opf = GET_FIELD_SP(insn, 5, 13);
+                rs1 = GET_FIELD(insn, 13, 17);
+                rs2 = GET_FIELD(insn, 27, 31);
+                if (gen_trap_ifnofpu(dc))
+                    goto jmp_insn;
+
+                switch (opf) {
+                case 0x000: /* VIS I edge8cc */
+                case 0x001: /* VIS II edge8n */
+                case 0x002: /* VIS I edge8lcc */
+                case 0x003: /* VIS II edge8ln */
+                case 0x004: /* VIS I edge16cc */
+                case 0x005: /* VIS II edge16n */
+                case 0x006: /* VIS I edge16lcc */
+                case 0x007: /* VIS II edge16ln */
+                case 0x008: /* VIS I edge32cc */
+                case 0x009: /* VIS II edge32n */
+                case 0x00a: /* VIS I edge32lcc */
+                case 0x00b: /* VIS II edge32ln */
+                    // XXX
+                    goto illegal_insn;
+                case 0x010: /* VIS I array8 */
+                    gen_movl_reg_T0(rs1);
+                    gen_movl_reg_T1(rs2);
+                    gen_op_array8();
+                    gen_movl_T0_reg(rd);
+                    break;
+                case 0x012: /* VIS I array16 */
+                    gen_movl_reg_T0(rs1);
+                    gen_movl_reg_T1(rs2);
+                    gen_op_array16();
+                    gen_movl_T0_reg(rd);
+                    break;
+                case 0x014: /* VIS I array32 */
+                    gen_movl_reg_T0(rs1);
+                    gen_movl_reg_T1(rs2);
+                    gen_op_array32();
+                    gen_movl_T0_reg(rd);
+                    break;
+                case 0x018: /* VIS I alignaddr */
+                    gen_movl_reg_T0(rs1);
+                    gen_movl_reg_T1(rs2);
+                    gen_op_alignaddr();
+                    gen_movl_T0_reg(rd);
+                    break;
+                case 0x019: /* VIS II bmask */
+                case 0x01a: /* VIS I alignaddrl */
+                    // XXX
+                    goto illegal_insn;
+                case 0x020: /* VIS I fcmple16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmple16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x022: /* VIS I fcmpne16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpne16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x024: /* VIS I fcmple32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmple32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x026: /* VIS I fcmpne32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpne32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x028: /* VIS I fcmpgt16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpgt16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x02a: /* VIS I fcmpeq16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpeq16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x02c: /* VIS I fcmpgt32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpgt32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x02e: /* VIS I fcmpeq32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fcmpeq32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x031: /* VIS I fmul8x16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmul8x16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x033: /* VIS I fmul8x16au */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmul8x16au();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x035: /* VIS I fmul8x16al */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmul8x16al();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x036: /* VIS I fmul8sux16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmul8sux16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x037: /* VIS I fmul8ulx16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmul8ulx16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x038: /* VIS I fmuld8sux16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmuld8sux16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x039: /* VIS I fmuld8ulx16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fmuld8ulx16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x03a: /* VIS I fpack32 */
+                case 0x03b: /* VIS I fpack16 */
+                case 0x03d: /* VIS I fpackfix */
+                case 0x03e: /* VIS I pdist */
+                    // XXX
+                    goto illegal_insn;
+                case 0x048: /* VIS I faligndata */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_faligndata();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x04b: /* VIS I fpmerge */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fpmerge();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x04c: /* VIS II bshuffle */
+                    // XXX
+                    goto illegal_insn;
+                case 0x04d: /* VIS I fexpand */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fexpand();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x050: /* VIS I fpadd16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fpadd16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x051: /* VIS I fpadd16s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fpadd16s();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x052: /* VIS I fpadd32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fpadd32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x053: /* VIS I fpadd32s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fpadd32s();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x054: /* VIS I fpsub16 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fpsub16();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x055: /* VIS I fpsub16s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fpsub16s();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x056: /* VIS I fpsub32 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fpadd32();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x057: /* VIS I fpsub32s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fpsub32s();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x060: /* VIS I fzero */
+                    gen_op_movl_DT0_0();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x061: /* VIS I fzeros */
+                    gen_op_movl_FT0_0();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x062: /* VIS I fnor */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fnor();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x063: /* VIS I fnors */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fnors();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x064: /* VIS I fandnot2 */
+                    gen_op_load_fpr_DT1(rs1);
+                    gen_op_load_fpr_DT0(rs2);
+                    gen_op_fandnot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x065: /* VIS I fandnot2s */
+                    gen_op_load_fpr_FT1(rs1);
+                    gen_op_load_fpr_FT0(rs2);
+                    gen_op_fandnots();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x066: /* VIS I fnot2 */
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fnot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x067: /* VIS I fnot2s */
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fnot();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x068: /* VIS I fandnot1 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fandnot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x069: /* VIS I fandnot1s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fandnots();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x06a: /* VIS I fnot1 */
+                    gen_op_load_fpr_DT1(rs1);
+                    gen_op_fnot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x06b: /* VIS I fnot1s */
+                    gen_op_load_fpr_FT1(rs1);
+                    gen_op_fnot();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x06c: /* VIS I fxor */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fxor();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x06d: /* VIS I fxors */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fxors();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x06e: /* VIS I fnand */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fnand();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x06f: /* VIS I fnands */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fnands();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x070: /* VIS I fand */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fand();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x071: /* VIS I fands */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fands();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x072: /* VIS I fxnor */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fxnor();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x073: /* VIS I fxnors */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fxnors();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x074: /* VIS I fsrc1 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x075: /* VIS I fsrc1s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x076: /* VIS I fornot2 */
+                    gen_op_load_fpr_DT1(rs1);
+                    gen_op_load_fpr_DT0(rs2);
+                    gen_op_fornot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x077: /* VIS I fornot2s */
+                    gen_op_load_fpr_FT1(rs1);
+                    gen_op_load_fpr_FT0(rs2);
+                    gen_op_fornots();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x078: /* VIS I fsrc2 */
+                    gen_op_load_fpr_DT0(rs2);
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x079: /* VIS I fsrc2s */
+                    gen_op_load_fpr_FT0(rs2);
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x07a: /* VIS I fornot1 */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_fornot();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x07b: /* VIS I fornot1s */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fornots();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x07c: /* VIS I for */
+                    gen_op_load_fpr_DT0(rs1);
+                    gen_op_load_fpr_DT1(rs2);
+                    gen_op_for();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x07d: /* VIS I fors */
+                    gen_op_load_fpr_FT0(rs1);
+                    gen_op_load_fpr_FT1(rs2);
+                    gen_op_fors();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x07e: /* VIS I fone */
+                    gen_op_movl_DT0_1();
+                    gen_op_store_DT0_fpr(rd);
+                    break;
+                case 0x07f: /* VIS I fones */
+                    gen_op_movl_FT0_1();
+                    gen_op_store_FT0_fpr(rd);
+                    break;
+                case 0x080: /* VIS I shutdown */
+                case 0x081: /* VIS II siam */
+                    // XXX
+                    goto illegal_insn;
+                default:
+                    goto illegal_insn;
+                }
+#else
+	        goto ncp_insn;
+#endif
+            } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
+#ifdef TARGET_SPARC64
+	        goto illegal_insn;
+#else
+	        goto ncp_insn;
+#endif
+#ifdef TARGET_SPARC64
 	    } else if (xop == 0x39) { /* V9 return */
                 rs1 = GET_FIELD(insn, 13, 17);
 		gen_movl_reg_T0(rs1);
@@ -2260,6 +2776,7 @@
 	{
 	    unsigned int xop = GET_FIELD(insn, 7, 12);
 	    rs1 = GET_FIELD(insn, 13, 17);
+            save_state(dc);
 	    gen_movl_reg_T0(rs1);
 	    if (IS_IMM) {	/* immediate */
 		rs2 = GET_FIELDs(insn, 19, 31);
@@ -2283,8 +2800,8 @@
 #endif
 	    }
 	    if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
-		    (xop > 0x17 && xop < 0x1d ) || \
-		    (xop > 0x2c && xop < 0x33) || xop == 0x1f) {
+		    (xop > 0x17 && xop <= 0x1d ) || \
+		    (xop > 0x2c && xop <= 0x33) || xop == 0x1f) {
 		switch (xop) {
 		case 0x0:	/* load word */
 		    gen_op_ldst(ld);
@@ -2296,6 +2813,8 @@
 		    gen_op_ldst(lduh);
 		    break;
 		case 0x3:	/* load double word */
+		    if (rd & 1)
+                        goto illegal_insn;
 		    gen_op_ldst(ldd);
 		    gen_movl_T0_reg(rd + 1);
 		    break;
@@ -2315,6 +2834,8 @@
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
 		case 0x10:	/* load word alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2322,6 +2843,8 @@
 		    break;
 		case 0x11:	/* load unsigned byte alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2329,6 +2852,8 @@
 		    break;
 		case 0x12:	/* load unsigned halfword alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2336,14 +2861,20 @@
 		    break;
 		case 0x13:	/* load double word alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+		    if (rd & 1)
+                        goto illegal_insn;
 		    gen_op_ldda(insn, 1, 8, 0);
 		    gen_movl_T0_reg(rd + 1);
 		    break;
 		case 0x19:	/* load signed byte alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2351,6 +2882,8 @@
 		    break;
 		case 0x1a:	/* load signed halfword alternate */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2358,6 +2891,8 @@
 		    break;
 		case 0x1d:	/* ldstuba -- XXX: should be atomically */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2365,6 +2900,8 @@
 		    break;
 		case 0x1f:	/* swap reg with alt. memory. Also atomically */
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2373,6 +2910,10 @@
 		    break;
 
 #ifndef TARGET_SPARC64
+		case 0x30: /* ldc */
+		case 0x31: /* ldcsr */
+		case 0x33: /* lddc */
+		    goto ncp_insn;
                     /* avoid warnings */
                     (void) &gen_op_stfa;
                     (void) &gen_op_stdfa;
@@ -2454,6 +2995,8 @@
 		    gen_op_ldst(sth);
 		    break;
 		case 0x7:
+		    if (rd & 1)
+                        goto illegal_insn;
                     flush_T2(dc);
 		    gen_movl_reg_T2(rd + 1);
 		    gen_op_ldst(std);
@@ -2461,6 +3004,8 @@
 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
 		case 0x14:
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2468,6 +3013,8 @@
                     break;
 		case 0x15:
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2475,6 +3022,8 @@
                     break;
 		case 0x16:
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
@@ -2482,9 +3031,13 @@
                     break;
 		case 0x17:
 #ifndef TARGET_SPARC64
+		    if (IS_IMM)
+			goto illegal_insn;
 		    if (!supervisor(dc))
 			goto priv_insn;
 #endif
+		    if (rd & 1)
+                        goto illegal_insn;
                     flush_T2(dc);
 		    gen_movl_reg_T2(rd + 1);
 		    gen_op_stda(insn, 0, 8, 0);
@@ -2513,8 +3066,14 @@
 		    gen_op_stfsr();
 		    gen_op_ldst(stf);
 		    break;
+#if !defined(CONFIG_USER_ONLY)
 		case 0x26: /* stdfq */
-		    goto nfpu_insn;
+		    if (!supervisor(dc))
+			goto priv_insn;
+		    if (gen_trap_ifnofpu(dc))
+			goto jmp_insn;
+		    goto nfq_insn;
+#endif
 		case 0x27:
                     gen_op_load_fpr_DT0(DFPREG(rd));
 		    gen_op_ldst(stdf);
@@ -2523,8 +3082,8 @@
 		    goto illegal_insn;
 		}
 	    } else if (xop > 0x33 && xop < 0x3f) {
+		switch (xop) {
 #ifdef TARGET_SPARC64
-		switch (xop) {
 		case 0x34: /* V9 stfa */
 		    gen_op_stfa(insn, 0, 0, 0); // XXX
 		    break;
@@ -2539,12 +3098,16 @@
 		    break;
 		case 0x36: /* V9 stqfa */
 		    goto nfpu_insn;
+#else
+		case 0x34: /* stc */
+		case 0x35: /* stcsr */
+		case 0x36: /* stdcq */
+		case 0x37: /* stdc */
+		    goto ncp_insn;
+#endif
 		default:
 		    goto illegal_insn;
 		}
-#else
-		goto illegal_insn;
-#endif
             }
 	    else
 		goto illegal_insn;
@@ -2581,6 +3144,21 @@
     save_state(dc);
     gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
     dc->is_br = 1;
+    return;
+#if !defined(CONFIG_USER_ONLY)
+ nfq_insn:
+    save_state(dc);
+    gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
+    dc->is_br = 1;
+    return;
+#endif
+#ifndef TARGET_SPARC64
+ ncp_insn:
+    save_state(dc);
+    gen_op_exception(TT_NCP_INSN);
+    dc->is_br = 1;
+    return;
+#endif
 }
 
 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
@@ -2724,7 +3302,6 @@
 
 void cpu_reset(CPUSPARCState *env)
 {
-    memset(env, 0, sizeof(*env));
     tlb_flush(env, 1);
     env->cwp = 0;
     env->wim = 1;
@@ -2736,16 +3313,15 @@
     env->cansave = NWINDOWS - 1;
 #endif
 #else
+    env->psret = 0;
     env->psrs = 1;
     env->psrps = 1;
-    env->gregs[1] = ram_size;
 #ifdef TARGET_SPARC64
     env->pstate = PS_PRIV;
-    env->version = GET_VER(env);
     env->pc = 0x1fff0000000ULL;
 #else
-    env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
     env->pc = 0xffd00000;
+    env->mmuregs[0] &= ~(MMU_E | MMU_NF);
 #endif
     env->npc = env->pc + 4;
 #endif
@@ -2763,6 +3339,90 @@
     return (env);
 }
 
+static const sparc_def_t sparc_defs[] = {
+#ifdef TARGET_SPARC64
+    {
+        .name = "TI UltraSparc II",
+        .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0 << 24)
+                       | (MAXTL << 8) | (NWINDOWS - 1)),
+        .fpu_version = 0x00000000,
+        .mmu_version = 0,
+    },
+#else
+    {
+        .name = "Fujitsu MB86904",
+        .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+    },
+    {
+        .name = "Fujitsu MB86907",
+        .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+        .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+        .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+    },
+    {
+        .name = "TI MicroSparc I",
+        .iu_version = 0x41000000,
+        .fpu_version = 4 << 17,
+        .mmu_version = 0x41000000,
+    },
+    {
+        .name = "TI SuperSparc II",
+        .iu_version = 0x40000000,
+        .fpu_version = 0 << 17,
+        .mmu_version = 0x04000000,
+    },
+    {
+        .name = "Ross RT620",
+        .iu_version = 0x1e000000,
+        .fpu_version = 1 << 17,
+        .mmu_version = 0x17000000,
+    },
+#endif
+};
+
+int sparc_find_by_name(const unsigned char *name, const sparc_def_t **def)
+{
+    int ret;
+    unsigned int i;
+
+    ret = -1;
+    *def = NULL;
+    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+        if (strcasecmp(name, sparc_defs[i].name) == 0) {
+            *def = &sparc_defs[i];
+            ret = 0;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+    unsigned int i;
+
+    for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+        (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
+                       sparc_defs[i].name,
+                       sparc_defs[i].iu_version,
+                       sparc_defs[i].fpu_version,
+                       sparc_defs[i].mmu_version);
+    }
+}
+
+int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def)
+{
+    env->version = def->iu_version;
+    env->fsr = def->fpu_version;
+#if !defined(TARGET_SPARC64)
+    env->mmuregs[0] = def->mmu_version;
+#endif
+    return 0;
+}
+
 #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
 
 void cpu_dump_state(CPUState *env, FILE *f, 
@@ -2800,8 +3460,8 @@
             cpu_fprintf(f, "\n");
     }
 #ifdef TARGET_SPARC64
-    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d\n",
-		env->pstate, GET_CCR(env), env->asi, env->tl);
+    cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
+		env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
     cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
 		env->cansave, env->canrestore, env->otherwin, env->wstate,
 		env->cleanwin, NWINDOWS - 1 - env->cwp);
@@ -2816,7 +3476,7 @@
 }
 
 #if defined(CONFIG_USER_ONLY)
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     return addr;
 }
@@ -2826,7 +3486,7 @@
                                  int *access_index, target_ulong address, int rw,
                                  int is_user);
 
-target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     target_phys_addr_t phys_addr;
     int prot, access_index;

Modified: trunk/src/host/qemu-neo1973/tests/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/tests/Makefile	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/tests/Makefile	2007-05-11 23:44:50 UTC (rev 1948)
@@ -13,7 +13,7 @@
 TESTS+=sha1# test_path
 #TESTS+=test_path
 
-QEMU=../i386-user/qemu-i386
+QEMU=../i386-linux-user/qemu-i386
 
 all: $(TESTS)
 
@@ -83,7 +83,7 @@
 	arm-linux-gcc -Wall -g -O2 -c -o $@ $<
 
 test-arm-iwmmxt: test-arm-iwmmxt.s
-	cpp < $< | arm-palmte-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
+	cpp < $< | arm-linux-gnu-gcc -Wall -static -march=iwmmxt -mabi=aapcs -x assembler - -o $@
 
 # MIPS test
 hello-mips: hello-mips.c
@@ -95,7 +95,7 @@
 # XXX: find a way to compile easily a test for each arch
 test2:
 	@for arch in i386 arm armeb sparc ppc mips mipsel; do \
-           ../$${arch}-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
+           ../$${arch}-linux-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
         done
 
 clean:

Modified: trunk/src/host/qemu-neo1973/tests/test-arm-iwmmxt.s
===================================================================
--- trunk/src/host/qemu-neo1973/tests/test-arm-iwmmxt.s	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/tests/test-arm-iwmmxt.s	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,12 +1,11 @@
-@ Should print "testtesttesttest" if iwMMXt is functional.
+@ Checks whether iwMMXt is functional.
 .code	32
-.align	4
 .globl	main
 
 main:
-adr	r0, data0
-adr	r1, data1
-adr	r2, data2
+ldr	r0, =data0
+ldr	r1, =data1
+ldr	r2, =data2
 #ifndef FPA
 wldrd	wr0, [r0, #0]
 wldrd	wr1, [r0, #8]
@@ -41,9 +40,10 @@
 mov	r0, #0
 swi	#0x900001
 
+.data
 data0:
 .string	"aaaabbbbccccdddd"
 data1:
 .string	"bbbbccccddddeeee"
 data2:
-.string	"sdrssdrssdrssdrs\n"
+.string	"hvLLWs\x1fsdrs9\x1fNJ-\n"

Modified: trunk/src/host/qemu-neo1973/tests/test-i386.c
===================================================================
--- trunk/src/host/qemu-neo1973/tests/test-i386.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/tests/test-i386.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -2583,6 +2583,41 @@
 
 #endif
 
+#define TEST_CONV_RAX(op)\
+{\
+    unsigned long a, r;\
+    a = i2l(0x8234a6f8);\
+    r = a;\
+    asm volatile(#op : "=a" (r) : "0" (r));\
+    printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
+}
+
+#define TEST_CONV_RAX_RDX(op)\
+{\
+    unsigned long a, d, r, rh;                   \
+    a = i2l(0x8234a6f8);\
+    d = i2l(0x8345a1f2);\
+    r = a;\
+    rh = d;\
+    asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
+    printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
+}
+
+void test_conv(void)
+{
+    TEST_CONV_RAX(cbw);
+    TEST_CONV_RAX(cwde);
+#if defined(__x86_64__)
+    TEST_CONV_RAX(cdqe);
+#endif
+
+    TEST_CONV_RAX_RDX(cwd);
+    TEST_CONV_RAX_RDX(cdq);
+#if defined(__x86_64__)
+    TEST_CONV_RAX_RDX(cqo);
+#endif
+}
+
 extern void *__start_initcall;
 extern void *__stop_initcall;
 
@@ -2621,6 +2656,7 @@
     test_single_step();
 #endif
     test_enter();
+    test_conv();
 #ifdef TEST_SSE
     test_sse();
     test_fxsave();

Modified: trunk/src/host/qemu-neo1973/translate-all.c
===================================================================
--- trunk/src/host/qemu-neo1973/translate-all.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/translate-all.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -308,6 +308,8 @@
     env->PC = gen_opc_pc[j];
     env->hflags &= ~MIPS_HFLAG_BMASK;
     env->hflags |= gen_opc_hflags[j];
+#elif defined(TARGET_ALPHA)
+    env->pc = gen_opc_pc[j];
 #endif
     return 0;
 }

Added: trunk/src/host/qemu-neo1973/uboot_image.h
===================================================================
--- trunk/src/host/qemu-neo1973/uboot_image.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/uboot_image.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 2000-2005
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef __UBOOT_IMAGE_H__
+#define __UBOOT_IMAGE_H__
+
+/*
+ * Operating System Codes
+ */
+#define IH_OS_INVALID		0	/* Invalid OS	*/
+#define IH_OS_OPENBSD		1	/* OpenBSD	*/
+#define IH_OS_NETBSD		2	/* NetBSD	*/
+#define IH_OS_FREEBSD		3	/* FreeBSD	*/
+#define IH_OS_4_4BSD		4	/* 4.4BSD	*/
+#define IH_OS_LINUX		5	/* Linux	*/
+#define IH_OS_SVR4		6	/* SVR4		*/
+#define IH_OS_ESIX		7	/* Esix		*/
+#define IH_OS_SOLARIS		8	/* Solaris	*/
+#define IH_OS_IRIX		9	/* Irix		*/
+#define IH_OS_SCO		10	/* SCO		*/
+#define IH_OS_DELL		11	/* Dell		*/
+#define IH_OS_NCR		12	/* NCR		*/
+#define IH_OS_LYNXOS		13	/* LynxOS	*/
+#define IH_OS_VXWORKS		14	/* VxWorks	*/
+#define IH_OS_PSOS		15	/* pSOS		*/
+#define IH_OS_QNX		16	/* QNX		*/
+#define IH_OS_U_BOOT		17	/* Firmware	*/
+#define IH_OS_RTEMS		18	/* RTEMS	*/
+#define IH_OS_ARTOS		19	/* ARTOS	*/
+#define IH_OS_UNITY		20	/* Unity OS	*/
+
+/*
+ * CPU Architecture Codes (supported by Linux)
+ */
+#define IH_CPU_INVALID		0	/* Invalid CPU	*/
+#define IH_CPU_ALPHA		1	/* Alpha	*/
+#define IH_CPU_ARM		2	/* ARM		*/
+#define IH_CPU_I386		3	/* Intel x86	*/
+#define IH_CPU_IA64		4	/* IA64		*/
+#define IH_CPU_MIPS		5	/* MIPS		*/
+#define IH_CPU_MIPS64		6	/* MIPS	 64 Bit */
+#define IH_CPU_PPC		7	/* PowerPC	*/
+#define IH_CPU_S390		8	/* IBM S390	*/
+#define IH_CPU_SH		9	/* SuperH	*/
+#define IH_CPU_SPARC		10	/* Sparc	*/
+#define IH_CPU_SPARC64		11	/* Sparc 64 Bit */
+#define IH_CPU_M68K		12	/* M68K		*/
+#define IH_CPU_NIOS		13	/* Nios-32	*/
+#define IH_CPU_MICROBLAZE	14	/* MicroBlaze   */
+#define IH_CPU_NIOS2		15	/* Nios-II	*/
+#define IH_CPU_BLACKFIN		16	/* Blackfin	*/
+#define IH_CPU_AVR32		17	/* AVR32	*/
+
+/*
+ * Image Types
+ *
+ * "Standalone Programs" are directly runnable in the environment
+ *	provided by U-Boot; it is expected that (if they behave
+ *	well) you can continue to work in U-Boot after return from
+ *	the Standalone Program.
+ * "OS Kernel Images" are usually images of some Embedded OS which
+ *	will take over control completely. Usually these programs
+ *	will install their own set of exception handlers, device
+ *	drivers, set up the MMU, etc. - this means, that you cannot
+ *	expect to re-enter U-Boot except by resetting the CPU.
+ * "RAMDisk Images" are more or less just data blocks, and their
+ *	parameters (address, size) are passed to an OS kernel that is
+ *	being started.
+ * "Multi-File Images" contain several images, typically an OS
+ *	(Linux) kernel image and one or more data images like
+ *	RAMDisks. This construct is useful for instance when you want
+ *	to boot over the network using BOOTP etc., where the boot
+ *	server provides just a single image file, but you want to get
+ *	for instance an OS kernel and a RAMDisk image.
+ *
+ *	"Multi-File Images" start with a list of image sizes, each
+ *	image size (in bytes) specified by an "uint32_t" in network
+ *	byte order. This list is terminated by an "(uint32_t)0".
+ *	Immediately after the terminating 0 follow the images, one by
+ *	one, all aligned on "uint32_t" boundaries (size rounded up to
+ *	a multiple of 4 bytes - except for the last file).
+ *
+ * "Firmware Images" are binary images containing firmware (like
+ *	U-Boot or FPGA images) which usually will be programmed to
+ *	flash memory.
+ *
+ * "Script files" are command sequences that will be executed by
+ *	U-Boot's command interpreter; this feature is especially
+ *	useful when you configure U-Boot to use a real shell (hush)
+ *	as command interpreter (=> Shell Scripts).
+ */
+
+#define IH_TYPE_INVALID		0	/* Invalid Image		*/
+#define IH_TYPE_STANDALONE	1	/* Standalone Program		*/
+#define IH_TYPE_KERNEL		2	/* OS Kernel Image		*/
+#define IH_TYPE_RAMDISK		3	/* RAMDisk Image		*/
+#define IH_TYPE_MULTI		4	/* Multi-File Image		*/
+#define IH_TYPE_FIRMWARE	5	/* Firmware Image		*/
+#define IH_TYPE_SCRIPT		6	/* Script file			*/
+#define IH_TYPE_FILESYSTEM	7	/* Filesystem Image (any type)	*/
+#define IH_TYPE_FLATDT		8	/* Binary Flat Device Tree Blob	*/
+
+/*
+ * Compression Types
+ */
+#define IH_COMP_NONE		0	/*  No	 Compression Used	*/
+#define IH_COMP_GZIP		1	/* gzip	 Compression Used	*/
+#define IH_COMP_BZIP2		2	/* bzip2 Compression Used	*/
+
+#define IH_MAGIC	0x27051956	/* Image Magic Number		*/
+#define IH_NMLEN		32	/* Image Name Length		*/
+
+/*
+ * all data in network byte order (aka natural aka bigendian)
+ */
+
+typedef struct uboot_image_header {
+	uint32_t	ih_magic;	/* Image Header Magic Number	*/
+	uint32_t	ih_hcrc;	/* Image Header CRC Checksum	*/
+	uint32_t	ih_time;	/* Image Creation Timestamp	*/
+	uint32_t	ih_size;	/* Image Data Size		*/
+	uint32_t	ih_load;	/* Data	 Load  Address		*/
+	uint32_t	ih_ep;		/* Entry Point Address		*/
+	uint32_t	ih_dcrc;	/* Image Data CRC Checksum	*/
+	uint8_t		ih_os;		/* Operating System		*/
+	uint8_t		ih_arch;	/* CPU architecture		*/
+	uint8_t		ih_type;	/* Image Type			*/
+	uint8_t		ih_comp;	/* Compression Type		*/
+	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
+} uboot_image_header_t;
+
+
+#endif	/* __IMAGE_H__ */

Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/vl.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -1,7 +1,7 @@
 /*
  * QEMU System Emulator
  * 
- * Copyright (c) 2003-2006 Fabrice Bellard
+ * Copyright (c) 2003-2007 Fabrice Bellard
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -55,6 +55,22 @@
 #include <malloc.h>
 #include <linux/rtc.h>
 #include <linux/ppdev.h>
+#include <linux/parport.h>
+#else
+#include <sys/stat.h>
+#include <sys/ethernet.h>
+#include <sys/sockio.h>
+#include <arpa/inet.h>
+#include <netinet/arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h> // must come after ip.h
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <syslog.h>
+#include <stropts.h>
 #endif
 #endif
 #endif
@@ -122,10 +138,12 @@
 /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
    to store the VM snapshots */
 BlockDriverState *bs_table[MAX_DISKS + 1], *fd_table[MAX_FD];
+BlockDriverState *pflash_table[MAX_PFLASH];
+BlockDriverState *sd_bdrv;
+BlockDriverState *mtd_bdrv;
 /* point to the block driver where the snapshots are managed */
 BlockDriverState *bs_snapshots;
 int vga_ram_size;
-int bios_size;
 static DisplayState display_state;
 int nographic;
 const char* keyboard_layout = NULL;
@@ -139,15 +157,18 @@
 int vm_running;
 int rtc_utc = 1;
 int cirrus_vga_enabled = 1;
+int vmsvga_enabled = 0;
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
 int graphic_height = 768;
+int graphic_depth = 8;
 #else
 int graphic_width = 800;
 int graphic_height = 600;
+int graphic_depth = 15;
 #endif
-int graphic_depth = 15;
 int full_screen = 0;
+int no_frame = 0;
 int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -169,13 +190,17 @@
 int fd_bootchk = 1;
 int no_reboot = 0;
 int cursor_hide = 1;
-int snapshot = 0;
-const char *sd_filename = 0;
-const char *mtd_filename = 0;
 int graphic_rotate = 0;
 int daemonize = 0;
 const char *option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
+int semihosting_enabled = 0;
+int autostart = 1;
+const char *qemu_name;
+#ifdef TARGET_SPARC
+unsigned int nb_prom_envs = 0;
+const char *prom_envs[MAX_PROM_ENVS];
+#endif
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -186,7 +211,7 @@
 uint32_t default_ioport_readb(void *opaque, uint32_t address)
 {
 #ifdef DEBUG_UNUSED_IOPORT
-    fprintf(stderr, "inb: port=0x%04x\n", address);
+    fprintf(stderr, "unused inb: port=0x%04x\n", address);
 #endif
     return 0xff;
 }
@@ -194,7 +219,7 @@
 void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
 {
 #ifdef DEBUG_UNUSED_IOPORT
-    fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
+    fprintf(stderr, "unused outb: port=0x%04x data=0x%02x\n", address, data);
 #endif
 }
 
@@ -218,7 +243,7 @@
 uint32_t default_ioport_readl(void *opaque, uint32_t address)
 {
 #ifdef DEBUG_UNUSED_IOPORT
-    fprintf(stderr, "inl: port=0x%04x\n", address);
+    fprintf(stderr, "unused inl: port=0x%04x\n", address);
 #endif
     return 0xffffffff;
 }
@@ -226,7 +251,7 @@
 void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
 {
 #ifdef DEBUG_UNUSED_IOPORT
-    fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
+    fprintf(stderr, "unused outl: port=0x%04x data=0x%02x\n", address, data);
 #endif
 }
 
@@ -1132,11 +1157,17 @@
 /***********************************************************/
 /* character device */
 
+static void qemu_chr_event(CharDriverState *s, int event)
+{
+    if (!s->chr_event)
+        return;
+    s->chr_event(s->handler_opaque, event);
+}
+
 static void qemu_chr_reset_bh(void *opaque)
 {
     CharDriverState *s = opaque;
-    if (s->chr_event)
-	s->chr_event(s, CHR_EVENT_RESET);
+    qemu_chr_event(s, CHR_EVENT_RESET);
     qemu_bh_delete(s->bh);
     s->bh = NULL;
 }
@@ -1161,6 +1192,19 @@
     return s->chr_ioctl(s, cmd, arg);
 }
 
+int qemu_chr_can_read(CharDriverState *s)
+{
+    if (!s->chr_can_read)
+        return 0;
+    return s->chr_can_read(s->handler_opaque);
+}
+
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+    s->chr_read(s->handler_opaque, buf, len);
+}
+
+
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
 {
     char buf[4096];
@@ -1177,41 +1221,248 @@
         s->chr_send_event(s, event);
 }
 
-void qemu_chr_add_read_handler(CharDriverState *s, 
-                               IOCanRWHandler *fd_can_read, 
-                               IOReadHandler *fd_read, void *opaque)
+void qemu_chr_add_handlers(CharDriverState *s, 
+                           IOCanRWHandler *fd_can_read, 
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque)
 {
-    s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
+    s->chr_can_read = fd_can_read;
+    s->chr_read = fd_read;
+    s->chr_event = fd_event;
+    s->handler_opaque = opaque;
+    if (s->chr_update_read_handler)
+        s->chr_update_read_handler(s);
 }
              
-void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
+static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
-    s->chr_event = chr_event;
+    return len;
 }
 
-static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+static CharDriverState *qemu_chr_open_null(void)
 {
-    return len;
+    CharDriverState *chr;
+
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    if (!chr)
+        return NULL;
+    chr->chr_write = null_chr_write;
+    return chr;
 }
 
-static void null_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
+/* MUX driver for serial I/O splitting */
+static int term_timestamps;
+static int64_t term_timestamps_start;
+#define MAX_MUX 4
+typedef struct {
+    IOCanRWHandler *chr_can_read[MAX_MUX];
+    IOReadHandler *chr_read[MAX_MUX];
+    IOEventHandler *chr_event[MAX_MUX];
+    void *ext_opaque[MAX_MUX];
+    CharDriverState *drv;
+    int mux_cnt;
+    int term_got_escape;
+    int max_size;
+} MuxDriver;
+
+
+static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
+    MuxDriver *d = chr->opaque;
+    int ret;
+    if (!term_timestamps) {
+        ret = d->drv->chr_write(d->drv, buf, len);
+    } else {
+        int i;
+
+        ret = 0;
+        for(i = 0; i < len; i++) {
+            ret += d->drv->chr_write(d->drv, buf+i, 1);
+            if (buf[i] == '\n') {
+                char buf1[64];
+                int64_t ti;
+                int secs;
+
+                ti = get_clock();
+                if (term_timestamps_start == -1)
+                    term_timestamps_start = ti;
+                ti -= term_timestamps_start;
+                secs = ti / 1000000000;
+                snprintf(buf1, sizeof(buf1),
+                         "[%02d:%02d:%02d.%03d] ",
+                         secs / 3600,
+                         (secs / 60) % 60,
+                         secs % 60,
+                         (int)((ti / 1000000) % 1000));
+                d->drv->chr_write(d->drv, buf1, strlen(buf1));
+            }
+        }
+    }
+    return ret;
 }
 
-static CharDriverState *qemu_chr_open_null(void)
+static char *mux_help[] = {
+    "% h    print this help\n\r",
+    "% x    exit emulator\n\r",
+    "% s    save disk data back to file (if -snapshot)\n\r",
+    "% t    toggle console timestamps\n\r"
+    "% b    send break (magic sysrq)\n\r",
+    "% c    switch between console and monitor\n\r",
+    "% %  sends %\n\r",
+    NULL
+};
+
+static int term_escape_char = 0x01; /* ctrl-a is used for escape */
+static void mux_print_help(CharDriverState *chr)
 {
+    int i, j;
+    char ebuf[15] = "Escape-Char";
+    char cbuf[50] = "\n\r";
+
+    if (term_escape_char > 0 && term_escape_char < 26) {
+        sprintf(cbuf,"\n\r");
+        sprintf(ebuf,"C-%c", term_escape_char - 1 + 'a');
+    } else {
+        sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", term_escape_char);
+    }
+    chr->chr_write(chr, cbuf, strlen(cbuf));
+    for (i = 0; mux_help[i] != NULL; i++) {
+        for (j=0; mux_help[i][j] != '\0'; j++) {
+            if (mux_help[i][j] == '%')
+                chr->chr_write(chr, ebuf, strlen(ebuf));
+            else
+                chr->chr_write(chr, &mux_help[i][j], 1);
+        }
+    }
+}
+
+static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
+{
+    if (d->term_got_escape) {
+        d->term_got_escape = 0;
+        if (ch == term_escape_char)
+            goto send_char;
+        switch(ch) {
+        case '?':
+        case 'h':
+            mux_print_help(chr);
+            break;
+        case 'x':
+            {
+                 char *term =  "QEMU: Terminated\n\r";
+                 chr->chr_write(chr,term,strlen(term));
+                 exit(0);
+                 break;
+            }
+        case 's':
+            {
+                int i;
+                for (i = 0; i < MAX_DISKS; i++) {
+                    if (bs_table[i])
+                        bdrv_commit(bs_table[i]);
+                }
+            }
+            break;
+        case 'b':
+            if (chr->chr_event)
+                chr->chr_event(chr->opaque, CHR_EVENT_BREAK);
+            break;
+        case 'c':
+            /* Switch to the next registered device */
+            chr->focus++;
+            if (chr->focus >= d->mux_cnt)
+                chr->focus = 0;
+            break;
+       case 't':
+           term_timestamps = !term_timestamps;
+           term_timestamps_start = -1;
+           break;
+        }
+    } else if (ch == term_escape_char) {
+        d->term_got_escape = 1;
+    } else {
+    send_char:
+        return 1;
+    }
+    return 0;
+}
+
+static int mux_chr_can_read(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    if (d->chr_can_read[chr->focus])
+       return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+    return 0;
+}
+
+static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    int i;
+    for(i = 0; i < size; i++)
+        if (mux_proc_byte(chr, d, buf[i]))
+            d->chr_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1);
+}
+
+static void mux_chr_event(void *opaque, int event)
+{
+    CharDriverState *chr = opaque;
+    MuxDriver *d = chr->opaque;
+    int i;
+
+    /* Send the event to all registered listeners */
+    for (i = 0; i < d->mux_cnt; i++)
+        if (d->chr_event[i])
+            d->chr_event[i](d->ext_opaque[i], event);
+}
+
+static void mux_chr_update_read_handler(CharDriverState *chr)
+{
+    MuxDriver *d = chr->opaque;
+
+    if (d->mux_cnt >= MAX_MUX) {
+        fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
+        return;
+    }
+    d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
+    d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
+    d->chr_read[d->mux_cnt] = chr->chr_read;
+    d->chr_event[d->mux_cnt] = chr->chr_event;
+    /* Fix up the real driver with mux routines */
+    if (d->mux_cnt == 0) {
+        qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
+                              mux_chr_event, chr);
+    }
+    chr->focus = d->mux_cnt;
+    d->mux_cnt++;
+}
+
+CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+{
     CharDriverState *chr;
+    MuxDriver *d;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
     if (!chr)
         return NULL;
-    chr->chr_write = null_chr_write;
-    chr->chr_add_read_handler = null_chr_add_read_handler;
+    d = qemu_mallocz(sizeof(MuxDriver));
+    if (!d) {
+        free(chr);
+        return NULL;
+    }
+
+    chr->opaque = d;
+    d->drv = drv;
+    chr->focus = -1;
+    chr->chr_write = mux_chr_write;
+    chr->chr_update_read_handler = mux_chr_update_read_handler;
     return chr;
 }
 
+
 #ifdef _WIN32
 
 static void socket_cleanup(void)
@@ -1300,17 +1551,12 @@
 
 typedef struct {
     int fd_in, fd_out;
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int max_size;
 } FDCharDriver;
 
-#define STDIO_MAX_CLIENTS 2
+#define STDIO_MAX_CLIENTS 1
+static int stdio_nb_clients = 0;
 
-static int stdio_nb_clients;
-static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
-
 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
@@ -1322,7 +1568,7 @@
     CharDriverState *chr = opaque;
     FDCharDriver *s = chr->opaque;
 
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -1345,20 +1591,15 @@
         return;
     }
     if (size > 0) {
-        s->fd_read(s->fd_opaque, buf, size);
+        qemu_chr_read(chr, buf, size);
     }
 }
 
-static void fd_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
+static void fd_chr_update_read_handler(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
 
     if (s->fd_in >= 0) {
-        s->fd_can_read = fd_can_read;
-        s->fd_read = fd_read;
-        s->fd_opaque = opaque;
         if (nographic && s->fd_in == 0) {
         } else {
             qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, 
@@ -1385,7 +1626,7 @@
     s->fd_out = fd_out;
     chr->opaque = s;
     chr->chr_write = fd_chr_write;
-    chr->chr_add_read_handler = fd_chr_add_read_handler;
+    chr->chr_update_read_handler = fd_chr_update_read_handler;
 
     qemu_chr_reset(chr);
 
@@ -1427,166 +1668,45 @@
 /* for STDIO, we handle the case where several clients use it
    (nographic mode) */
 
-#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
-
 #define TERM_FIFO_MAX_SIZE 1
 
-static int term_got_escape, client_index;
 static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
 static int term_fifo_size;
-static int term_timestamps;
-static int64_t term_timestamps_start;
 
-void term_print_help(void)
+static int stdio_read_poll(void *opaque)
 {
-    printf("\n"
-           "C-a h    print this help\n"
-           "C-a x    exit emulator\n"
-           "C-a s    save disk data back to file (if -snapshot)\n"
-           "C-a b    send break (magic sysrq)\n"
-           "C-a t    toggle console timestamps\n"
-           "C-a c    switch between console and monitor\n"
-           "C-a C-a  send C-a\n"
-           );
-}
+    CharDriverState *chr = opaque;
 
-/* called when a char is received */
-static void stdio_received_byte(int ch)
-{
-    if (term_got_escape) {
-        term_got_escape = 0;
-        switch(ch) {
-        case 'h':
-            term_print_help();
-            break;
-        case 'x':
-            exit(0);
-            break;
-        case 's': 
-            {
-                int i;
-                for (i = 0; i < MAX_DISKS; i++) {
-                    if (bs_table[i])
-                        bdrv_commit(bs_table[i]);
-                }
-            }
-            break;
-        case 'b':
-            if (client_index < stdio_nb_clients) {
-                CharDriverState *chr;
-                FDCharDriver *s;
-
-                chr = stdio_clients[client_index];
-                s = chr->opaque;
-                chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
-            }
-            break;
-        case 'c':
-            client_index++;
-            if (client_index >= stdio_nb_clients)
-                client_index = 0;
-            if (client_index == 0) {
-                /* send a new line in the monitor to get the prompt */
-                ch = '\r';
-                goto send_char;
-            }
-            break;
-        case 't':
-            term_timestamps = !term_timestamps;
-            term_timestamps_start = -1;
-            break;
-        case TERM_ESCAPE:
-            goto send_char;
-        }
-    } else if (ch == TERM_ESCAPE) {
-        term_got_escape = 1;
-    } else {
-    send_char:
-        if (client_index < stdio_nb_clients) {
-            uint8_t buf[1];
-            CharDriverState *chr;
-            FDCharDriver *s;
-            
-            chr = stdio_clients[client_index];
-            s = chr->opaque;
-            if (s->fd_can_read(s->fd_opaque) > 0) {
-                buf[0] = ch;
-                s->fd_read(s->fd_opaque, buf, 1);
-            } else if (term_fifo_size == 0) {
-                term_fifo[term_fifo_size++] = ch;
-            }
-        }
+    /* try to flush the queue if needed */
+    if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
+        qemu_chr_read(chr, term_fifo, 1);
+        term_fifo_size = 0;
     }
-}
-
-static int stdio_read_poll(void *opaque)
-{
-    CharDriverState *chr;
-    FDCharDriver *s;
-
-    if (client_index < stdio_nb_clients) {
-        chr = stdio_clients[client_index];
-        s = chr->opaque;
-        /* try to flush the queue if needed */
-        if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) {
-            s->fd_read(s->fd_opaque, term_fifo, 1);
-            term_fifo_size = 0;
-        }
-        /* see if we can absorb more chars */
-        if (term_fifo_size == 0)
-            return 1;
-        else
-            return 0;
-    } else {
+    /* see if we can absorb more chars */
+    if (term_fifo_size == 0)
         return 1;
-    }
+    else
+        return 0;
 }
 
 static void stdio_read(void *opaque)
 {
     int size;
     uint8_t buf[1];
-    
+    CharDriverState *chr = opaque;
+
     size = read(0, buf, 1);
     if (size == 0) {
         /* stdin has been closed. Remove it from the active list.  */
         qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
         return;
     }
-    if (size > 0)
-        stdio_received_byte(buf[0]);
-}
-
-static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    FDCharDriver *s = chr->opaque;
-    if (!term_timestamps) {
-        return unix_write(s->fd_out, buf, len);
-    } else {
-        int i;
-        char buf1[64];
-
-        for(i = 0; i < len; i++) {
-            unix_write(s->fd_out, buf + i, 1);
-            if (buf[i] == '\n') {
-                int64_t ti;
-                int secs;
-
-                ti = get_clock();
-                if (term_timestamps_start == -1)
-                    term_timestamps_start = ti;
-                ti -= term_timestamps_start;
-                secs = ti / 1000000000;
-                snprintf(buf1, sizeof(buf1), 
-                         "[%02d:%02d:%02d.%03d] ",
-                         secs / 3600,
-                         (secs / 60) % 60,
-                         secs % 60,
-                         (int)((ti / 1000000) % 1000));
-                unix_write(s->fd_out, buf1, strlen(buf1));
-            }
+    if (size > 0) {
+        if (qemu_chr_can_read(chr) > 0) {
+            qemu_chr_read(chr, buf, 1);
+        } else if (term_fifo_size == 0) {
+            term_fifo[term_fifo_size++] = buf[0];
         }
-        return len;
     }
 }
 
@@ -1631,24 +1751,13 @@
 {
     CharDriverState *chr;
 
-    if (nographic) {
-        if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
-            return NULL;
-        chr = qemu_chr_open_fd(0, 1);
-        chr->chr_write = stdio_write;
-        if (stdio_nb_clients == 0)
-            qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
-        client_index = stdio_nb_clients;
-    } else {
-        if (stdio_nb_clients != 0)
-            return NULL;
-        chr = qemu_chr_open_fd(0, 1);
-    }
-    stdio_clients[stdio_nb_clients++] = chr;
-    if (stdio_nb_clients == 1) {
-        /* set the terminal in raw mode */
-        term_init();
-    }
+    if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
+        return NULL;
+    chr = qemu_chr_open_fd(0, 1);
+    qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
+    stdio_nb_clients++;
+    term_init();
+
     return chr;
 }
 
@@ -1810,9 +1919,26 @@
     return chr;
 }
 
+typedef struct {
+    int fd;
+    int mode;
+} ParallelCharDriver;
+
+static int pp_hw_mode(ParallelCharDriver *s, uint16_t mode)
+{
+    if (s->mode != mode) {
+	int m = mode;
+        if (ioctl(s->fd, PPSETMODE, &m) < 0)
+            return 0;
+	s->mode = mode;
+    }
+    return 1;
+}
+
 static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
 {
-    int fd = (int)chr->opaque;
+    ParallelCharDriver *drv = chr->opaque;
+    int fd = drv->fd;
     uint8_t b;
 
     switch(cmd) {
@@ -1829,7 +1955,10 @@
     case CHR_IOCTL_PP_READ_CONTROL:
         if (ioctl(fd, PPRCONTROL, &b) < 0)
             return -ENOTSUP;
-        *(uint8_t *)arg = b;
+	/* Linux gives only the lowest bits, and no way to know data
+	   direction! For better compatibility set the fixed upper
+	   bits. */
+        *(uint8_t *)arg = b | 0xc0;
         break;
     case CHR_IOCTL_PP_WRITE_CONTROL:
         b = *(uint8_t *)arg;
@@ -1841,15 +1970,63 @@
             return -ENOTSUP;
         *(uint8_t *)arg = b;
         break;
+    case CHR_IOCTL_PP_EPP_READ_ADDR:
+	if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
+	    struct ParallelIOArg *parg = arg;
+	    int n = read(fd, parg->buffer, parg->count);
+	    if (n != parg->count) {
+		return -EIO;
+	    }
+	}
+        break;
+    case CHR_IOCTL_PP_EPP_READ:
+	if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+	    struct ParallelIOArg *parg = arg;
+	    int n = read(fd, parg->buffer, parg->count);
+	    if (n != parg->count) {
+		return -EIO;
+	    }
+	}
+        break;
+    case CHR_IOCTL_PP_EPP_WRITE_ADDR:
+	if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
+	    struct ParallelIOArg *parg = arg;
+	    int n = write(fd, parg->buffer, parg->count);
+	    if (n != parg->count) {
+		return -EIO;
+	    }
+	}
+        break;
+    case CHR_IOCTL_PP_EPP_WRITE:
+	if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+	    struct ParallelIOArg *parg = arg;
+	    int n = write(fd, parg->buffer, parg->count);
+	    if (n != parg->count) {
+		return -EIO;
+	    }
+	}
+        break;
     default:
         return -ENOTSUP;
     }
     return 0;
 }
 
+static void pp_close(CharDriverState *chr)
+{
+    ParallelCharDriver *drv = chr->opaque;
+    int fd = drv->fd;
+
+    pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
+    ioctl(fd, PPRELEASE);
+    close(fd);
+    qemu_free(drv);
+}
+
 static CharDriverState *qemu_chr_open_pp(const char *filename)
 {
     CharDriverState *chr;
+    ParallelCharDriver *drv;
     int fd;
 
     fd = open(filename, O_RDWR);
@@ -1861,15 +2038,24 @@
         return NULL;
     }
 
+    drv = qemu_mallocz(sizeof(ParallelCharDriver));
+    if (!drv) {
+        close(fd);
+        return NULL;
+    }
+    drv->fd = fd;
+    drv->mode = IEEE1284_MODE_COMPAT;
+
     chr = qemu_mallocz(sizeof(CharDriverState));
     if (!chr) {
+	qemu_free(drv);
         close(fd);
         return NULL;
     }
-    chr->opaque = (void *)fd;
     chr->chr_write = null_chr_write;
-    chr->chr_add_read_handler = null_chr_add_read_handler;
     chr->chr_ioctl = pp_ioctl;
+    chr->chr_close = pp_close;
+    chr->opaque = drv;
 
     qemu_chr_reset(chr);
 
@@ -1887,9 +2073,6 @@
 
 #ifdef _WIN32
 typedef struct {
-    IOCanRWHandler *fd_can_read; 
-    IOReadHandler *fd_read;
-    void *win_opaque;
     int max_size;
     HANDLE hcom, hrecv, hsend;
     OVERLAPPED orecv, osend;
@@ -1905,8 +2088,10 @@
 static int win_chr_poll(void *opaque);
 static int win_chr_pipe_poll(void *opaque);
 
-static void win_chr_close2(WinCharState *s)
+static void win_chr_close(CharDriverState *chr)
 {
+    WinCharState *s = chr->opaque;
+
     if (s->hsend) {
         CloseHandle(s->hsend);
         s->hsend = NULL;
@@ -1920,19 +2105,14 @@
         s->hcom = NULL;
     }
     if (s->fpipe)
-        qemu_del_polling_cb(win_chr_pipe_poll, s);
+        qemu_del_polling_cb(win_chr_pipe_poll, chr);
     else
-        qemu_del_polling_cb(win_chr_poll, s);
+        qemu_del_polling_cb(win_chr_poll, chr);
 }
 
-static void win_chr_close(CharDriverState *chr)
+static int win_chr_init(CharDriverState *chr, const char *filename)
 {
     WinCharState *s = chr->opaque;
-    win_chr_close2(s);
-}
-
-static int win_chr_init(WinCharState *s, const char *filename)
-{
     COMMCONFIG comcfg;
     COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
     COMSTAT comstat;
@@ -1989,11 +2169,11 @@
         fprintf(stderr, "Failed ClearCommError\n");
         goto fail;
     }
-    qemu_add_polling_cb(win_chr_poll, s);
+    qemu_add_polling_cb(win_chr_poll, chr);
     return 0;
 
  fail:
-    win_chr_close2(s);
+    win_chr_close(chr);
     return -1;
 }
 
@@ -2031,14 +2211,17 @@
     return len1 - len;
 }
 
-static int win_chr_read_poll(WinCharState *s)
+static int win_chr_read_poll(CharDriverState *chr)
 {
-    s->max_size = s->fd_can_read(s->win_opaque);
+    WinCharState *s = chr->opaque;
+
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
-            
-static void win_chr_readfile(WinCharState *s)
+
+static void win_chr_readfile(CharDriverState *chr)
 {
+    WinCharState *s = chr->opaque;
     int ret, err;
     uint8_t buf[1024];
     DWORD size;
@@ -2054,47 +2237,39 @@
     }
 
     if (size > 0) {
-        s->fd_read(s->win_opaque, buf, size);
+        qemu_chr_read(chr, buf, size);
     }
 }
 
-static void win_chr_read(WinCharState *s)
+static void win_chr_read(CharDriverState *chr)
 {
+    WinCharState *s = chr->opaque;
+
     if (s->len > s->max_size)
         s->len = s->max_size;
     if (s->len == 0)
         return;
     
-    win_chr_readfile(s);
+    win_chr_readfile(chr);
 }
 
 static int win_chr_poll(void *opaque)
 {
-    WinCharState *s = opaque;
+    CharDriverState *chr = opaque;
+    WinCharState *s = chr->opaque;
     COMSTAT status;
     DWORD comerr;
     
     ClearCommError(s->hcom, &comerr, &status);
     if (status.cbInQue > 0) {
         s->len = status.cbInQue;
-        win_chr_read_poll(s);
-        win_chr_read(s);
+        win_chr_read_poll(chr);
+        win_chr_read(chr);
         return 1;
     }
     return 0;
 }
 
-static void win_chr_add_read_handler(CharDriverState *chr, 
-                                    IOCanRWHandler *fd_can_read, 
-                                    IOReadHandler *fd_read, void *opaque)
-{
-    WinCharState *s = chr->opaque;
-
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->win_opaque = opaque;
-}
-
 static CharDriverState *qemu_chr_open_win(const char *filename)
 {
     CharDriverState *chr;
@@ -2110,10 +2285,9 @@
     }
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
     chr->chr_close = win_chr_close;
 
-    if (win_chr_init(s, filename) < 0) {
+    if (win_chr_init(chr, filename) < 0) {
         free(s);
         free(chr);
         return NULL;
@@ -2124,21 +2298,23 @@
 
 static int win_chr_pipe_poll(void *opaque)
 {
-    WinCharState *s = opaque;
+    CharDriverState *chr = opaque;
+    WinCharState *s = chr->opaque;
     DWORD size;
 
     PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
     if (size > 0) {
         s->len = size;
-        win_chr_read_poll(s);
-        win_chr_read(s);
+        win_chr_read_poll(chr);
+        win_chr_read(chr);
         return 1;
     }
     return 0;
 }
 
-static int win_chr_pipe_init(WinCharState *s, const char *filename)
+static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
 {
+    WinCharState *s = chr->opaque;
     OVERLAPPED ov;
     int ret;
     DWORD size;
@@ -2190,11 +2366,11 @@
         CloseHandle(ov.hEvent);
         ov.hEvent = NULL;
     }
-    qemu_add_polling_cb(win_chr_pipe_poll, s);
+    qemu_add_polling_cb(win_chr_pipe_poll, chr);
     return 0;
 
  fail:
-    win_chr_close2(s);
+    win_chr_close(chr);
     return -1;
 }
 
@@ -2214,10 +2390,9 @@
     }
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
     chr->chr_close = win_chr_close;
     
-    if (win_chr_pipe_init(s, filename) < 0) {
+    if (win_chr_pipe_init(chr, filename) < 0) {
         free(s);
         free(chr);
         return NULL;
@@ -2242,7 +2417,6 @@
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    chr->chr_add_read_handler = win_chr_add_read_handler;
     qemu_chr_reset(chr);
     return chr;
 }
@@ -2264,9 +2438,6 @@
 /* UDP Net console */
 
 typedef struct {
-    IOCanRWHandler *fd_can_read;
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int fd;
     struct sockaddr_in daddr;
     char buf[1024];
@@ -2288,15 +2459,15 @@
     CharDriverState *chr = opaque;
     NetCharDriver *s = chr->opaque;
 
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
 
     /* If there were any stray characters in the queue process them
      * first
      */
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
-        s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
         s->bufptr++;
-        s->max_size = s->fd_can_read(s->fd_opaque);
+        s->max_size = qemu_chr_can_read(chr);
     }
     return s->max_size;
 }
@@ -2315,22 +2486,17 @@
 
     s->bufptr = 0;
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
-        s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1);
+        qemu_chr_read(chr, &s->buf[s->bufptr], 1);
         s->bufptr++;
-        s->max_size = s->fd_can_read(s->fd_opaque);
+        s->max_size = qemu_chr_can_read(chr);
     }
 }
 
-static void udp_chr_add_read_handler(CharDriverState *chr,
-                                    IOCanRWHandler *fd_can_read,
-                                    IOReadHandler *fd_read, void *opaque)
+static void udp_chr_update_read_handler(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
 
     if (s->fd >= 0) {
-        s->fd_can_read = fd_can_read;
-        s->fd_read = fd_read;
-        s->fd_opaque = opaque;
         qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
                              udp_chr_read, NULL, chr);
     }
@@ -2380,7 +2546,7 @@
     s->bufptr = 0;
     chr->opaque = s;
     chr->chr_write = udp_chr_write;
-    chr->chr_add_read_handler = udp_chr_add_read_handler;
+    chr->chr_update_read_handler = udp_chr_update_read_handler;
     return chr;
 
 return_err:
@@ -2397,13 +2563,11 @@
 /* TCP Net console */
 
 typedef struct {
-    IOCanRWHandler *fd_can_read;
-    IOReadHandler *fd_read;
-    void *fd_opaque;
     int fd, listen_fd;
     int connected;
     int max_size;
     int do_telnetopt;
+    int do_nodelay;
     int is_unix;
 } TCPCharDriver;
 
@@ -2426,9 +2590,7 @@
     TCPCharDriver *s = chr->opaque;
     if (!s->connected)
         return 0;
-    if (!s->fd_can_read)
-	return 0;
-    s->max_size = s->fd_can_read(s->fd_opaque);
+    s->max_size = qemu_chr_can_read(chr);
     return s->max_size;
 }
 
@@ -2461,7 +2623,7 @@
             } else {
                 if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
                     /* Handle IAC break commands by sending a serial break */
-                    chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+                    qemu_chr_event(chr, CHR_EVENT_BREAK);
                     s->do_telnetopt++;
                 }
                 s->do_telnetopt++;
@@ -2508,21 +2670,10 @@
         if (s->do_telnetopt)
             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
         if (size > 0)
-            s->fd_read(s->fd_opaque, buf, size);
+            qemu_chr_read(chr, buf, size);
     }
 }
 
-static void tcp_chr_add_read_handler(CharDriverState *chr,
-                                     IOCanRWHandler *fd_can_read,
-                                    IOReadHandler *fd_read, void *opaque)
-{
-    TCPCharDriver *s = chr->opaque;
-
-    s->fd_can_read = fd_can_read;
-    s->fd_read = fd_read;
-    s->fd_opaque = opaque;
-}
-
 static void tcp_chr_connect(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2549,6 +2700,12 @@
     send(fd, (char *)buf, 3, 0);
 }
 
+static void socket_set_nodelay(int fd)
+{
+    int val = 1;
+    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+}
+
 static void tcp_chr_accept(void *opaque)
 {
     CharDriverState *chr = opaque;
@@ -2582,6 +2739,8 @@
         }
     }
     socket_set_nonblock(fd);
+    if (s->do_nodelay)
+        socket_set_nodelay(fd);
     s->fd = fd;
     qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL);
     tcp_chr_connect(chr);
@@ -2606,6 +2765,7 @@
     int fd = -1, ret, err, val;
     int is_listen = 0;
     int is_waitconnect = 1;
+    int do_nodelay = 0;
     const char *ptr;
     struct sockaddr_in saddr;
 #ifndef _WIN32
@@ -2636,6 +2796,8 @@
             is_listen = 1;
         } else if (!strncmp(ptr,"nowait",6)) {
             is_waitconnect = 0;
+        } else if (!strncmp(ptr,"nodelay",6)) {
+            do_nodelay = 1;
         } else {
             printf("Unknown option: %s\n", ptr);
             goto fail;
@@ -2668,10 +2830,10 @@
     s->fd = -1;
     s->listen_fd = -1;
     s->is_unix = is_unix;
+    s->do_nodelay = do_nodelay && !is_unix;
 
     chr->opaque = s;
     chr->chr_write = tcp_chr_write;
-    chr->chr_add_read_handler = tcp_chr_add_read_handler;
     chr->chr_close = tcp_chr_close;
 
     if (is_listen) {
@@ -2709,6 +2871,10 @@
                 if (err == EINTR || err == EWOULDBLOCK) {
                 } else if (err == EINPROGRESS) {
                     break;
+#ifdef _WIN32
+                } else if (err == WSAEALREADY) {
+                    break;
+#endif
                 } else {
                     goto fail;
                 }
@@ -2718,6 +2884,7 @@
             }
         }
         s->fd = fd;
+        socket_set_nodelay(fd);
         if (s->connected)
             tcp_chr_connect(chr);
         else
@@ -2757,6 +2924,16 @@
     if (strstart(filename, "udp:", &p)) {
         return qemu_chr_open_udp(p);
     } else
+    if (strstart(filename, "mon:", &p)) {
+        CharDriverState *drv = qemu_chr_open(p);
+        if (drv) {
+            drv = qemu_chr_open_mux(drv);
+            monitor_init(drv, !nographic);
+            return drv;
+        }
+        printf("Unable to open driver: %s\n", p);
+        return 0;
+    } else
 #ifndef _WIN32
     if (strstart(filename, "unix:", &p)) {
 	return qemu_chr_open_tcp(p, 0, 1);
@@ -3235,7 +3412,15 @@
     uint8_t buf[4096];
     int size;
 
+#ifdef __sun__
+    struct strbuf sbuf;
+    int f = 0;
+    sbuf.maxlen = sizeof(buf);
+    sbuf.buf = buf;
+    size = getmsg(s->fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;
+#else
     size = read(s->fd, buf, sizeof(buf));
+#endif
     if (size > 0) {
         qemu_send_packet(s->vc, buf, size);
     }
@@ -3278,10 +3463,135 @@
     return fd;
 }
 #elif defined(__sun__)
+#define TUNNEWPPA       (('T'<<16) | 0x0001)
+/* 
+ * Allocate TAP device, returns opened fd. 
+ * Stores dev name in the first arg(must be large enough).
+ */  
+int tap_alloc(char *dev)
+{
+    int tap_fd, if_fd, ppa = -1;
+    static int ip_fd = 0;
+    char *ptr;
+
+    static int arp_fd = 0;
+    int ip_muxid, arp_muxid;
+    struct strioctl  strioc_if, strioc_ppa;
+    int link_type = I_PLINK;;
+    struct lifreq ifr;
+    char actual_name[32] = "";
+
+    memset(&ifr, 0x0, sizeof(ifr));
+
+    if( *dev ){
+       ptr = dev;	
+       while( *ptr && !isdigit((int)*ptr) ) ptr++; 
+       ppa = atoi(ptr);
+    }
+
+    /* Check if IP device was opened */
+    if( ip_fd )
+       close(ip_fd);
+
+    if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
+       return -1;
+    }
+
+    if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/tap");
+       return -1;
+    }
+
+    /* Assign a new PPA and get its unit number. */
+    strioc_ppa.ic_cmd = TUNNEWPPA;
+    strioc_ppa.ic_timout = 0;
+    strioc_ppa.ic_len = sizeof(ppa);
+    strioc_ppa.ic_dp = (char *)&ppa;
+    if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
+       syslog (LOG_ERR, "Can't assign new interface");
+
+    if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){
+       syslog(LOG_ERR, "Can't open /dev/tap (2)");
+       return -1;
+    }
+    if(ioctl(if_fd, I_PUSH, "ip") < 0){
+       syslog(LOG_ERR, "Can't push IP module");
+       return -1;
+    }
+
+    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
+	syslog(LOG_ERR, "Can't get flags\n");
+
+    snprintf (actual_name, 32, "tap%d", ppa);
+    strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+
+    ifr.lifr_ppa = ppa;
+    /* Assign ppa according to the unit number returned by tun device */
+
+    if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
+        syslog (LOG_ERR, "Can't set PPA %d", ppa);
+    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
+        syslog (LOG_ERR, "Can't get flags\n");
+    /* Push arp module to if_fd */
+    if (ioctl (if_fd, I_PUSH, "arp") < 0)
+        syslog (LOG_ERR, "Can't push ARP module (2)");
+
+    /* Push arp module to ip_fd */
+    if (ioctl (ip_fd, I_POP, NULL) < 0)
+        syslog (LOG_ERR, "I_POP failed\n");
+    if (ioctl (ip_fd, I_PUSH, "arp") < 0)
+        syslog (LOG_ERR, "Can't push ARP module (3)\n");
+    /* Open arp_fd */
+    if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0)
+       syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
+
+    /* Set ifname to arp */
+    strioc_if.ic_cmd = SIOCSLIFNAME;
+    strioc_if.ic_timout = 0;
+    strioc_if.ic_len = sizeof(ifr);
+    strioc_if.ic_dp = (char *)&ifr;
+    if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
+        syslog (LOG_ERR, "Can't set ifname to arp\n");
+    }
+
+    if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
+       syslog(LOG_ERR, "Can't link TAP device to IP");
+       return -1;
+    }
+
+    if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
+        syslog (LOG_ERR, "Can't link TAP device to ARP");
+
+    close (if_fd);
+
+    memset(&ifr, 0x0, sizeof(ifr));
+    strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name));
+    ifr.lifr_ip_muxid  = ip_muxid;
+    ifr.lifr_arp_muxid = arp_muxid;
+
+    if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
+    {
+      ioctl (ip_fd, I_PUNLINK , arp_muxid);
+      ioctl (ip_fd, I_PUNLINK, ip_muxid);
+      syslog (LOG_ERR, "Can't set multiplexor id");
+    }
+
+    sprintf(dev, "tap%d", ppa);
+    return tap_fd;
+}
+
 static int tap_open(char *ifname, int ifname_size)
 {
-    fprintf(stderr, "warning: tap_open not yet implemented\n");
-    return -1;
+    char  dev[10]="";
+    int fd;
+    if( (fd = tap_alloc(dev)) < 0 ){
+       fprintf(stderr, "Cannot allocate TAP device\n");
+       return -1;
+    }
+    pstrcpy(ifname, ifname_size, dev);
+    fcntl(fd, F_SETFL, O_NONBLOCK);
+    return fd;
 }
 #else
 static int tap_open(char *ifname, int ifname_size)
@@ -3329,13 +3639,21 @@
     if (fd < 0)
         return -1;
 
-    if (!setup_script)
+    if (!setup_script || !strcmp(setup_script, "no"))
         setup_script = "";
     if (setup_script[0] != '\0') {
         /* try to launch network init script */
         pid = fork();
         if (pid >= 0) {
             if (pid == 0) {
+                int open_max = sysconf (_SC_OPEN_MAX), i;
+                for (i = 0; i < open_max; i++)
+                    if (i != STDIN_FILENO &&
+                        i != STDOUT_FILENO &&
+                        i != STDERR_FILENO &&
+                        i != fd)
+                        close(i);
+
                 parg = args;
                 *parg++ = (char *)setup_script;
                 *parg++ = ifname;
@@ -3617,7 +3935,7 @@
     int so_type=-1, optlen=sizeof(so_type);
 
     if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, &optlen)< 0) {
-	fprintf(stderr, "qemu: error: setsockopt(SO_TYPE) for fd=%d failed\n", fd);
+	fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
 	return NULL;
     }
     switch(so_type) {
@@ -3724,6 +4042,10 @@
             if (err == EINTR || err == EWOULDBLOCK) {
             } else if (err == EINPROGRESS) {
                 break;
+#ifdef _WIN32
+            } else if (err == WSAEALREADY) {
+                break;
+#endif
             } else {
                 perror("connect");
                 closesocket(fd);
@@ -3901,7 +4223,9 @@
             if (net_tap_fd_init(vlan, fd))
                 ret = 0;
         } else {
-            get_param_value(ifname, sizeof(ifname), "ifname", p);
+            if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
+                ifname[0] = '\0';
+            }
             if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
                 pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
             }
@@ -3998,8 +4322,8 @@
         dev = usb_msd_init(p);
     } else if (strstart(devname, "net:", &p)) {
         unsigned int nr = strtoul(p, NULL, 0);
-	if (nr >= (unsigned int)nb_nics || strcmp(nd_table[nr].model, "usb"))
-		return -1;
+        if (nr >= (unsigned int) nb_nics || strcmp(nd_table[nr].model, "usb"))
+            return -1;
         dev = usb_net_init(&nd_table[nr]);
     } else if (strstart(devname, "gadget", &p)) {
         dev = usb_gadget;
@@ -4012,7 +4336,7 @@
             return -1;
         goto attach;
     } else {
-        return 0;
+        return -1;
     }
     if (!dev)
         return -1;
@@ -4355,51 +4679,11 @@
 
     for (iter = pcmcia_sockets; iter; iter = iter->next)
         term_printf("%s: %s\n", iter->socket->slot_string,
-                        iter->socket->attached ? iter->socket->card_string :
-                        "Empty");
+                    iter->socket->attached ? iter->socket->card_string :
+                    "Empty");
 }
 
 /***********************************************************/
-/* pid file */
-
-static char *pid_filename;
-
-/* Remove PID file. Called on normal exit */
-
-static void remove_pidfile(void) 
-{
-    unlink (pid_filename);
-}
-
-static void create_pidfile(const char *filename)
-{
-    struct stat pidstat;
-    FILE *f;
-
-    /* Try to write our PID to the named file */
-    if (stat(filename, &pidstat) < 0) {
-        if (errno == ENOENT) {
-            if ((f = fopen (filename, "w")) == NULL) {
-                perror("Opening pidfile");
-                exit(1);
-            }
-            fprintf(f, "%d\n", getpid());
-            fclose(f);
-            pid_filename = qemu_strdup(filename);
-            if (!pid_filename) {
-                fprintf(stderr, "Could not save PID filename");
-                exit(1);
-            }
-            atexit(remove_pidfile);
-        }
-    } else {
-        fprintf(stderr, "%s already exists. Remove it and try again.\n", 
-                filename);
-        exit(1);
-    }
-}
-
-/***********************************************************/
 /* dumb display */
 
 static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
@@ -4435,6 +4719,7 @@
     IOCanRWHandler *fd_read_poll;
     IOHandler *fd_read;
     IOHandler *fd_write;
+    int deleted;
     void *opaque;
     /* temporary data */
     struct pollfd *ufd;
@@ -4460,8 +4745,7 @@
             if (ioh == NULL)
                 break;
             if (ioh->fd == fd) {
-                *pioh = ioh->next;
-                qemu_free(ioh);
+                ioh->deleted = 1;
                 break;
             }
             pioh = &ioh->next;
@@ -4482,6 +4766,7 @@
         ioh->fd_read = fd_read;
         ioh->fd_write = fd_write;
         ioh->opaque = opaque;
+        ioh->deleted = 0;
     }
     return 0;
 }
@@ -6130,9 +6415,12 @@
 
 void main_loop_wait(int timeout)
 {
-    IOHandlerRecord *ioh, *ioh_next;
+    IOHandlerRecord *ioh;
     fd_set rfds, wfds, xfds;
     int ret, nfds;
+#ifdef _WIN32
+    int ret2, i;
+#endif
     struct timeval tv;
     PollingEntry *pe;
 
@@ -6143,7 +6431,7 @@
         ret |= pe->func(pe->opaque);
     }
 #ifdef _WIN32
-    if (ret == 0 && timeout > 0) {
+    if (ret == 0) {
         int err;
         WaitObjects *w = &wait_objects;
         
@@ -6151,10 +6439,25 @@
         if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
             if (w->func[ret - WAIT_OBJECT_0])
                 w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+                
+            /* Check for additional signaled events */ 
+            for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+                                
+                /* Check if event is signaled */
+                ret2 = WaitForSingleObject(w->events[i], 0);
+                if(ret2 == WAIT_OBJECT_0) {
+                    if (w->func[i])
+                        w->func[i](w->opaque[i]);
+                } else if (ret2 == WAIT_TIMEOUT) {
+                } else {
+                    err = GetLastError();
+                    fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+                }                
+            }                 
         } else if (ret == WAIT_TIMEOUT) {
         } else {
             err = GetLastError();
-            fprintf(stderr, "Wait error %d %d\n", ret, err);
+            fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
         }
     }
 #endif
@@ -6165,6 +6468,8 @@
     FD_ZERO(&wfds);
     FD_ZERO(&xfds);
     for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+        if (ioh->deleted)
+            continue;
         if (ioh->fd_read &&
             (!ioh->fd_read_poll ||
              ioh->fd_read_poll(ioh->opaque) != 0)) {
@@ -6192,9 +6497,11 @@
 #endif
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
     if (ret > 0) {
-        /* XXX: better handling of removal */
-        for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
-            ioh_next = ioh->next;
+        IOHandlerRecord **pioh;
+
+        for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+            if (ioh->deleted)
+                continue;
             if (FD_ISSET(ioh->fd, &rfds)) {
                 ioh->fd_read(ioh->opaque);
             }
@@ -6202,6 +6509,17 @@
                 ioh->fd_write(ioh->opaque);
             }
         }
+
+	/* remove deleted IO handlers */
+	pioh = &first_io_handler;
+	while (*pioh) {
+            ioh = *pioh;
+            if (ioh->deleted) {
+                *pioh = ioh->next;
+                qemu_free(ioh);
+            } else 
+                pioh = &ioh->next;
+        }
     }
 #if defined(CONFIG_SLIRP)
     if (slirp_inited) {
@@ -6255,13 +6573,16 @@
 #ifdef CONFIG_PROFILER
                 qemu_time += profile_getclock() - ti;
 #endif
+                if (ret == EXCP_HLT) {
+                    /* Give the next CPU a chance to run.  */
+                    cur_cpu = env;
+                    continue;
+                }
                 if (ret != EXCP_HALTED)
                     break;
                 /* all CPUs are halted ? */
-                if (env == cur_cpu) {
-                    ret = EXCP_HLT;
+                if (env == cur_cpu)
                     break;
-                }
             }
             cur_cpu = env;
 
@@ -6282,9 +6603,9 @@
             if (ret == EXCP_DEBUG) {
                 vm_stop(EXCP_DEBUG);
             }
-            /* if hlt instruction, we wait until the next IRQ */
+            /* If all cpus are halted then wait until the next IRQ */
             /* XXX: use timeout computed from timers */
-            if (ret == EXCP_HLT)
+            if (ret == EXCP_HALTED)
                 timeout = 10;
             else
                 timeout = 0;
@@ -6305,22 +6626,25 @@
 
 void help(void)
 {
-    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2006 Fabrice Bellard\n"
+    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n"
            "usage: %s [options] [disk_image]\n"
            "\n"
            "'disk_image' is a raw hard image image for IDE hard disk 0\n"
            "\n"
            "Standard options:\n"
            "-M machine      select emulated machine (-M ? for list)\n"
+           "-cpu cpu        select CPU (-cpu ? for list)\n"
            "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
            "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"
+           "-pflash file    use 'file' as a parallel flash image\n"
            "-boot [a|c|d|n] boot on floppy (a), hard disk (c), CD-ROM (d), or network (n)\n"
            "-snapshot       write to temporary files instead of disk image files\n"
 #ifdef CONFIG_SDL
+           "-no-frame       open SDL window without a frame and window decorations\n"
            "-no-quit        disable SDL window close capability\n"
 #endif
 #ifdef TARGET_I386
@@ -6329,7 +6653,7 @@
            "-m megs         set virtual RAM size to megs MB [default=%d]\n"
            "-smp n          set the number of CPUs to 'n' [default=1]\n"
            "-nographic      disable graphical output and redirect serial I/Os to console\n"
-           "-vertical       rotate graphical output left (only PXA targets)\n"
+           "-portrait       rotate graphical output 90 deg left (only PXA LCD)\n"
 #ifndef _WIN32
            "-k language     use keyboard layout (for example \"fr\" for French)\n"
 #endif
@@ -6351,6 +6675,7 @@
 #if defined(TARGET_PPC) || defined(TARGET_SPARC)
            "-g WxH[xDEPTH]  Set the initial graphical resolution and depth\n"
 #endif
+           "-name string    set the name of the guest\n"
            "\n"
            "Network options:\n"
            "-net nic[,vlan=n][,macaddr=addr][,model=type]\n"
@@ -6367,6 +6692,7 @@
            "-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n"
            "                connect the host TAP network interface to VLAN 'n' and use\n"
            "                the network script 'file' (default=%s);\n"
+           "                use 'script=no' to disable script execution;\n"
            "                use 'fd=h' to connect to an already opened TAP interface\n"
 #endif
            "-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n"
@@ -6377,7 +6703,8 @@
            "                is provided, the default is '-net nic -net user'\n"
            "\n"
 #ifdef CONFIG_SLIRP
-           "-tftp prefix    allow tftp access to files starting with prefix [-net user]\n"
+           "-tftp dir       allow tftp access to files in dir [-net user]\n"
+           "-bootp file     advertise file in BOOTP replies\n"
 #ifndef _WIN32
            "-smb dir        allow SMB access to files in 'dir' [-net user]\n"
 #endif
@@ -6396,8 +6723,8 @@
            "-parallel dev   redirect the parallel port to char device 'dev'\n"
            "-pidfile file   Write PID to 'file'\n"
            "-S              freeze CPU at startup (use 'c' to start execution)\n"
-           "-s              wait gdb connection to port %d\n"
-           "-p port         change gdb connection port\n"
+           "-s              wait gdb connection to port\n"
+           "-p port         set gdb connection port [default=%s]\n"
            "-d item1,...    output log to %s (use -d ? for a list of log items)\n"
            "-hdachs c,h,s[,t]  force hard disk 0 physical geometry and the optional BIOS\n"
            "                translation (t=none or lba) (usually qemu can guess them)\n"
@@ -6421,6 +6748,9 @@
 	   "-daemonize      daemonize QEMU after initializing\n"
 #endif
 	   "-option-rom rom load a file, rom, into the option ROM space\n"
+#ifdef TARGET_SPARC
+           "-prom-env variable=value  set OpenBIOS nvram variables\n"
+#endif
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -6445,6 +6775,7 @@
     QEMU_OPTION_h,
 
     QEMU_OPTION_M,
+    QEMU_OPTION_cpu,
     QEMU_OPTION_fda,
     QEMU_OPTION_fdb,
     QEMU_OPTION_hda,
@@ -6454,6 +6785,7 @@
     QEMU_OPTION_cdrom,
     QEMU_OPTION_mtdblock,
     QEMU_OPTION_sd,
+    QEMU_OPTION_pflash,
     QEMU_OPTION_boot,
     QEMU_OPTION_snapshot,
 #ifdef TARGET_I386
@@ -6461,7 +6793,7 @@
 #endif
     QEMU_OPTION_m,
     QEMU_OPTION_nographic,
-    QEMU_OPTION_vertical,
+    QEMU_OPTION_portrait,
 #ifdef HAS_AUDIO
     QEMU_OPTION_audio_help,
     QEMU_OPTION_soundhw,
@@ -6469,6 +6801,7 @@
 
     QEMU_OPTION_net,
     QEMU_OPTION_tftp,
+    QEMU_OPTION_bootp,
     QEMU_OPTION_smb,
     QEMU_OPTION_redir,
 
@@ -6486,13 +6819,16 @@
     QEMU_OPTION_k,
     QEMU_OPTION_localtime,
     QEMU_OPTION_cirrusvga,
+    QEMU_OPTION_vmsvga,
     QEMU_OPTION_g,
     QEMU_OPTION_std_vga,
+    QEMU_OPTION_echr,
     QEMU_OPTION_monitor,
     QEMU_OPTION_serial,
     QEMU_OPTION_parallel,
     QEMU_OPTION_loadvm,
     QEMU_OPTION_full_screen,
+    QEMU_OPTION_no_frame,
     QEMU_OPTION_no_quit,
     QEMU_OPTION_pidfile,
     QEMU_OPTION_no_kqemu,
@@ -6508,6 +6844,9 @@
     QEMU_OPTION_show_cursor,
     QEMU_OPTION_daemonize,
     QEMU_OPTION_option_rom,
+    QEMU_OPTION_semihosting,
+    QEMU_OPTION_name,
+    QEMU_OPTION_prom_env,
 };
 
 typedef struct QEMUOption {
@@ -6518,8 +6857,10 @@
 
 const QEMUOption qemu_options[] = {
     { "h", 0, QEMU_OPTION_h },
+    { "help", 0, QEMU_OPTION_h },
 
     { "M", HAS_ARG, QEMU_OPTION_M },
+    { "cpu", HAS_ARG, QEMU_OPTION_cpu },
     { "fda", HAS_ARG, QEMU_OPTION_fda },
     { "fdb", HAS_ARG, QEMU_OPTION_fdb },
     { "hda", HAS_ARG, QEMU_OPTION_hda },
@@ -6529,6 +6870,7 @@
     { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
     { "mtdblock", HAS_ARG, QEMU_OPTION_mtdblock },
     { "sd", HAS_ARG, QEMU_OPTION_sd },
+    { "pflash", HAS_ARG, QEMU_OPTION_pflash },
     { "boot", HAS_ARG, QEMU_OPTION_boot },
     { "snapshot", 0, QEMU_OPTION_snapshot },
 #ifdef TARGET_I386
@@ -6536,7 +6878,7 @@
 #endif
     { "m", HAS_ARG, QEMU_OPTION_m },
     { "nographic", 0, QEMU_OPTION_nographic },
-    { "vertical", 0, QEMU_OPTION_vertical },
+    { "portrait", 0, QEMU_OPTION_portrait },
     { "k", HAS_ARG, QEMU_OPTION_k },
 #ifdef HAS_AUDIO
     { "audio-help", 0, QEMU_OPTION_audio_help },
@@ -6546,6 +6888,7 @@
     { "net", HAS_ARG, QEMU_OPTION_net},
 #ifdef CONFIG_SLIRP
     { "tftp", HAS_ARG, QEMU_OPTION_tftp },
+    { "bootp", HAS_ARG, QEMU_OPTION_bootp },
 #ifndef _WIN32
     { "smb", HAS_ARG, QEMU_OPTION_smb },
 #endif
@@ -6572,12 +6915,14 @@
 #endif
     { "localtime", 0, QEMU_OPTION_localtime },
     { "std-vga", 0, QEMU_OPTION_std_vga },
+    { "echr", 1, QEMU_OPTION_echr },
     { "monitor", 1, QEMU_OPTION_monitor },
     { "serial", 1, QEMU_OPTION_serial },
     { "parallel", 1, QEMU_OPTION_parallel },
     { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
     { "full-screen", 0, QEMU_OPTION_full_screen },
 #ifdef CONFIG_SDL
+    { "no-frame", 0, QEMU_OPTION_no_frame },
     { "no-quit", 0, QEMU_OPTION_no_quit },
 #endif
     { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
@@ -6590,11 +6935,19 @@
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+    { "vmwarevga", 0, QEMU_OPTION_vmsvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { "no-reboot", 0, QEMU_OPTION_no_reboot },
     { "show-cursor", 0, QEMU_OPTION_show_cursor },
     { "daemonize", 0, QEMU_OPTION_daemonize },
     { "option-rom", HAS_ARG, QEMU_OPTION_option_rom },
+#if defined(TARGET_ARM)
+    { "semihosting", 0, QEMU_OPTION_semihosting },
+#endif
+    { "name", HAS_ARG, QEMU_OPTION_name },
+#if defined(TARGET_SPARC)
+    { "prom-env", HAS_ARG, QEMU_OPTION_prom_env },
+#endif
     { NULL },
 };
 
@@ -6663,27 +7016,33 @@
     qemu_register_machine(&heathrow_machine);
     qemu_register_machine(&core99_machine);
     qemu_register_machine(&prep_machine);
+    qemu_register_machine(&ref405ep_machine);
+    qemu_register_machine(&taihu_machine);
 #elif defined(TARGET_MIPS)
     qemu_register_machine(&mips_machine);
+    qemu_register_machine(&mips_malta_machine);
+    qemu_register_machine(&mips_pica61_machine);
 #elif defined(TARGET_SPARC)
 #ifdef TARGET_SPARC64
     qemu_register_machine(&sun4u_machine);
 #else
-    qemu_register_machine(&sun4m_machine);
+    qemu_register_machine(&ss5_machine);
+    qemu_register_machine(&ss10_machine);
 #endif
 #elif defined(TARGET_ARM)
-    qemu_register_machine(&integratorcp926_machine);
-    qemu_register_machine(&integratorcp1026_machine);
+    qemu_register_machine(&integratorcp_machine);
     qemu_register_machine(&versatilepb_machine);
     qemu_register_machine(&versatileab_machine);
     qemu_register_machine(&realview_machine);
-    qemu_register_machine(&zaurusakita_machine);
-    qemu_register_machine(&zaurusspitz_machine);
-    qemu_register_machine(&zaurusborzoi_machine);
-    qemu_register_machine(&zaurusterrier_machine);
+    qemu_register_machine(&akitapda_machine);
+    qemu_register_machine(&spitzpda_machine);
+    qemu_register_machine(&borzoipda_machine);
+    qemu_register_machine(&terrierpda_machine);
     qemu_register_machine(&neo1973_machine);
 #elif defined(TARGET_SH4)
     qemu_register_machine(&shix_machine);
+#elif defined(TARGET_ALPHA)
+    /* XXX: TODO */
 #else
 #error unsupported CPU
 #endif
@@ -6817,16 +7176,19 @@
 int main(int argc, char **argv)
 {
 #ifdef CONFIG_GDBSTUB
-    int use_gdbstub, gdbstub_port;
+    int use_gdbstub;
+    const char *gdbstub_port;
 #endif
-    int i, cdrom_index;
-    int linux_boot;
+    int i, cdrom_index, pflash_index;
+    int snapshot, linux_boot;
     const char *initrd_filename;
     const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
+    const char *pflash_filename[MAX_PFLASH];
+    const char *sd_filename;
+    const char *mtd_filename;
     const char *kernel_filename, *kernel_cmdline;
     DisplayState *ds = &display_state;
     int cyls, heads, secs, translation;
-    int start_emulation = 1;
     char net_clients[MAX_NET_CLIENTS][256];
     int nb_net_clients;
     int optind;
@@ -6839,10 +7201,12 @@
     int parallel_device_index;
     const char *loadvm = NULL;
     QEMUMachine *machine;
+    const char *cpu_model;
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
     int usbgadget_enabled = 0;
     int fds[2];
+    const char *pid_file = NULL;
 
     LIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
@@ -6877,14 +7241,19 @@
 
     register_machines();
     machine = first_machine;
+    cpu_model = NULL;
     initrd_filename = NULL;
     for(i = 0; i < MAX_FD; i++)
         fd_filename[i] = NULL;
     for(i = 0; i < MAX_DISKS; i++)
         hd_filename[i] = NULL;
+    for(i = 0; i < MAX_PFLASH; i++)
+        pflash_filename[i] = NULL;
+    pflash_index = 0;
+    sd_filename = NULL;
+    mtd_filename = NULL;
     ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
     vga_ram_size = VGA_RAM_SIZE;
-    bios_size = BIOS_SIZE;
 #ifdef CONFIG_GDBSTUB
     use_gdbstub = 0;
     gdbstub_port = DEFAULT_GDBSTUB_PORT;
@@ -6930,6 +7299,9 @@
             const QEMUOption *popt;
 
             optind++;
+            /* Treat --foo the same as -foo.  */
+            if (r[1] == '-')
+                r++;
             popt = qemu_options;
             for(;;) {
                 if (!popt->name) {
@@ -6966,6 +7338,23 @@
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_cpu:
+                /* hw initialization will check this */
+                if (optarg[0] == '?') {
+#if defined(TARGET_PPC)
+                    ppc_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_ARM)
+                    arm_cpu_list();
+#elif defined(TARGET_MIPS)
+                    mips_cpu_list(stdout, &fprintf);
+#elif defined(TARGET_SPARC)
+                    sparc_cpu_list(stdout, &fprintf);
+#endif
+                    exit(1);
+                } else {
+                    cpu_model = optarg;
+                }
+                break;
             case QEMU_OPTION_initrd:
                 initrd_filename = optarg;
                 break;
@@ -6987,6 +7376,13 @@
             case QEMU_OPTION_sd:
                 sd_filename = optarg;
                 break;
+            case QEMU_OPTION_pflash:
+                if (pflash_index >= MAX_PFLASH) {
+                    fprintf(stderr, "qemu: too many parallel flash images\n");
+                    exit(1);
+                }
+                pflash_filename[pflash_index++] = optarg;
+                break;
             case QEMU_OPTION_snapshot:
                 snapshot = 1;
                 break;
@@ -7027,11 +7423,12 @@
                 }
                 break;
             case QEMU_OPTION_nographic:
+                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
+                pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null");
                 pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
-                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
                 nographic = 1;
                 break;
-            case QEMU_OPTION_vertical:
+            case QEMU_OPTION_portrait:
                 graphic_rotate = 1;
                 break;
             case QEMU_OPTION_kernel:
@@ -7085,6 +7482,9 @@
             case QEMU_OPTION_tftp:
 		tftp_prefix = optarg;
                 break;
+            case QEMU_OPTION_bootp:
+                bootp_filename = optarg;
+                break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
 		net_slirp_smb(optarg);
@@ -7137,14 +7537,14 @@
                 use_gdbstub = 1;
                 break;
             case QEMU_OPTION_p:
-                gdbstub_port = atoi(optarg);
+                gdbstub_port = optarg;
                 break;
 #endif
             case QEMU_OPTION_L:
                 bios_dir = optarg;
                 break;
             case QEMU_OPTION_S:
-                start_emulation = 0;
+                autostart = 0;
                 break;
 	    case QEMU_OPTION_k:
 		keyboard_layout = optarg;
@@ -7154,9 +7554,15 @@
                 break;
             case QEMU_OPTION_cirrusvga:
                 cirrus_vga_enabled = 1;
+                vmsvga_enabled = 0;
                 break;
+            case QEMU_OPTION_vmsvga:
+                cirrus_vga_enabled = 0;
+                vmsvga_enabled = 1;
+                break;
             case QEMU_OPTION_std_vga:
                 cirrus_vga_enabled = 0;
+                vmsvga_enabled = 0;
                 break;
             case QEMU_OPTION_g:
                 {
@@ -7192,6 +7598,14 @@
                     graphic_depth = depth;
                 }
                 break;
+            case QEMU_OPTION_echr:
+                {
+                    char *r;
+                    term_escape_char = strtol(optarg, &r, 0);
+                    if (r == optarg)
+                        printf("Bad argument to echr\n");
+                    break;
+                }
             case QEMU_OPTION_monitor:
                 pstrcpy(monitor_device, sizeof(monitor_device), optarg);
                 break;
@@ -7220,12 +7634,15 @@
                 full_screen = 1;
                 break;
 #ifdef CONFIG_SDL
+            case QEMU_OPTION_no_frame:
+                no_frame = 1;
+                break;
             case QEMU_OPTION_no_quit:
                 no_quit = 1;
                 break;
 #endif
             case QEMU_OPTION_pidfile:
-                create_pidfile(optarg);
+                pid_file = optarg;
                 break;
 #ifdef TARGET_I386
             case QEMU_OPTION_win2k_hack:
@@ -7287,6 +7704,22 @@
 		option_rom[nb_option_roms] = optarg;
 		nb_option_roms++;
 		break;
+            case QEMU_OPTION_semihosting:
+                semihosting_enabled = 1;
+                break;
+            case QEMU_OPTION_name:
+                qemu_name = optarg;
+                break;
+#ifdef TARGET_SPARC
+            case QEMU_OPTION_prom_env:
+                if (nb_prom_envs >= MAX_PROM_ENVS) {
+                    fprintf(stderr, "Too many prom variables\n");
+                    exit(1);
+                }
+                prom_envs[nb_prom_envs] = optarg;
+                nb_prom_envs++;
+                break;
+#endif
             }
         }
     }
@@ -7311,16 +7744,19 @@
 	    close(fds[1]);
 
 	again:
-	    len = read(fds[0], &status, 1);
-	    if (len == -1 && (errno == EINTR))
-		goto again;
-	    
-	    if (len != 1 || status != 0)
-		exit(1);
-	    else
-		exit(0);
+            len = read(fds[0], &status, 1);
+            if (len == -1 && (errno == EINTR))
+                goto again;
+
+            if (len != 1)
+                exit(1);
+            else if (status == 1) {
+                fprintf(stderr, "Could not acquire pidfile\n");
+                exit(1);
+            } else
+                exit(0);
 	} else if (pid < 0)
-	    exit(1);
+            exit(1);
 
 	setsid();
 
@@ -7339,6 +7775,15 @@
     }
 #endif
 
+    if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+        if (daemonize) {
+            uint8_t status = 1;
+            write(fds[1], &status, 1);
+        } else
+            fprintf(stderr, "Could not acquire pid file\n");
+        exit(1);
+    }
+
 #ifdef USE_KQEMU
     if (smp_cpus > 1)
         kqemu_allowed = 0;
@@ -7346,6 +7791,7 @@
     linux_boot = (kernel_filename != NULL);
 
     if (!linux_boot &&
+        boot_device != 'n' &&
         hd_filename[0] == '\0' && 
         (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
         fd_filename[0] == '\0')
@@ -7407,17 +7853,8 @@
 #endif
 
     /* init the memory */
-    phys_ram_size = ram_size + vga_ram_size + bios_size;
+    phys_ram_size = ram_size + vga_ram_size + MAX_BIOS_SIZE;
 
-    for (i = 0; i < nb_option_roms; i++) {
-	int ret = get_image_size(option_rom[i]);
-	if (ret == -1) {
-	    fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]);
-	    exit(1);
-	}
-	phys_ram_size += ret;
-    }
-
     phys_ram_base = qemu_vmalloc(phys_ram_size);
     if (!phys_ram_base) {
         fprintf(stderr, "Could not allocate physical memory\n");
@@ -7474,6 +7911,48 @@
         }
     }
 
+    /* Open the virtual parallel flash block devices */
+    for(i = 0; i < MAX_PFLASH; i++) {
+        if (pflash_filename[i]) {
+            if (!pflash_table[i]) {
+                char buf[64];
+                snprintf(buf, sizeof(buf), "fl%c", i + 'a');
+                pflash_table[i] = bdrv_new(buf);
+            }
+            if (bdrv_open(pflash_table[i], pflash_filename[i],
+                          snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
+                fprintf(stderr, "qemu: could not open flash image '%s'\n",
+                        pflash_filename[i]);
+                exit(1);
+            }
+        }
+    }
+
+    sd_bdrv = bdrv_new ("sd");
+    /* FIXME: This isn't really a floppy, but it's a reasonable
+       approximation.  */
+    bdrv_set_type_hint(sd_bdrv, BDRV_TYPE_FLOPPY);
+    if (sd_filename) {
+        if (bdrv_open(sd_bdrv, sd_filename,
+                      snapshot ? BDRV_O_SNAPSHOT : 0) < 0) {
+            fprintf(stderr, "qemu: could not open SD card image %s\n",
+                    sd_filename);
+        } else
+            qemu_key_check(sd_bdrv, sd_filename);
+    }
+
+    if (mtd_filename) {
+        mtd_bdrv = bdrv_new ("mtd");
+        if (bdrv_open(mtd_bdrv, mtd_filename,
+                      snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
+            qemu_key_check(mtd_bdrv, mtd_filename)) {
+            fprintf(stderr, "qemu: could not open Flash image %s\n",
+                    mtd_filename);
+            bdrv_delete(mtd_bdrv);
+            mtd_bdrv = 0;
+        }
+    }
+
     register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
     register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
 
@@ -7486,7 +7965,7 @@
 	vnc_display_init(ds, vnc_display);
     } else {
 #if defined(CONFIG_SDL)
-        sdl_display_init(ds, full_screen);
+        sdl_display_init(ds, full_screen, no_frame);
 #elif defined(CONFIG_COCOA)
         cocoa_display_init(ds, full_screen);
 #else
@@ -7494,12 +7973,27 @@
 #endif
     }
 
-    monitor_hd = qemu_chr_open(monitor_device);
-    if (!monitor_hd) {
-        fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
-        exit(1);
+    /* Maintain compatibility with multiple stdio monitors */
+    if (!strcmp(monitor_device,"stdio")) {
+        for (i = 0; i < MAX_SERIAL_PORTS; i++) {
+            if (!strcmp(serial_devices[i],"mon:stdio")) {
+                monitor_device[0] = '\0';
+                break;
+            } else if (!strcmp(serial_devices[i],"stdio")) {
+                monitor_device[0] = '\0';
+                pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "mon:stdio");
+                break;
+            }
+        }
     }
-    monitor_init(monitor_hd, !nographic);
+    if (monitor_device[0] != '\0') {
+        monitor_hd = qemu_chr_open(monitor_device);
+        if (!monitor_hd) {
+            fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
+            exit(1);
+        }
+        monitor_init(monitor_hd, !nographic);
+    }
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
@@ -7531,7 +8025,7 @@
 
     machine->init(ram_size, vga_ram_size, boot_device,
                   ds, fd_filename, snapshot,
-                  kernel_filename, kernel_cmdline, initrd_filename);
+                  kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
 
     /* init USB devices */
     if (usb_enabled) {
@@ -7554,12 +8048,12 @@
 
 #ifdef CONFIG_GDBSTUB
     if (use_gdbstub) {
+        /* XXX: use standard host:port notation and modify options
+           accordingly. */
         if (gdbserver_start(gdbstub_port) < 0) {
-            fprintf(stderr, "Could not open gdbserver socket on port %d\n", 
+            fprintf(stderr, "qemu: could not open gdbstub device on port '%s'\n",
                     gdbstub_port);
             exit(1);
-        } else {
-            printf("Waiting gdb connection on port %d\n", gdbstub_port);
         }
     } else 
 #endif
@@ -7569,7 +8063,7 @@
     {
         /* XXX: simplify init */
         read_passwords();
-        if (start_emulation) {
+        if (autostart) {
             vm_start();
         }
     }

Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/vl.h	2007-05-11 23:44:50 UTC (rev 1948)
@@ -45,8 +45,8 @@
 #define O_BINARY 0
 #endif
 
-#ifdef __sun__
-#define ENOMEDIUM 4097
+#ifndef ENOMEDIUM
+#define ENOMEDIUM ENODEV
 #endif
 
 #ifdef _WIN32
@@ -54,7 +54,6 @@
 #define fsync _commit
 #define lseek _lseeki64
 #define ENOTSUP 4096
-#define ENOMEDIUM 4097
 extern int qemu_ftruncate64(int, int64_t);
 #define ftruncate qemu_ftruncate64
 
@@ -84,7 +83,6 @@
 
 #include "audio/audio.h"
 #include "cpu.h"
-#include "gdbstub.h"
 
 #endif /* !defined(QEMU_TOOL) */
 
@@ -116,6 +114,7 @@
 extern const char *bios_dir;
 
 extern int vm_running;
+extern const char *qemu_name;
 
 typedef struct vm_change_state_entry VMChangeStateEntry;
 typedef void VMChangeStateHandler(void *opaque, int running);
@@ -150,6 +149,7 @@
 extern int bios_size;
 extern int rtc_utc;
 extern int cirrus_vga_enabled;
+extern int vmsvga_enabled;
 extern int graphic_width;
 extern int graphic_height;
 extern int graphic_depth;
@@ -159,23 +159,28 @@
 extern int usb_enabled;
 extern int smp_cpus;
 extern int cursor_hide;
-extern int snapshot;
-extern const char *sd_filename;
-extern const char *mtd_filename;
 extern int graphic_rotate;
 extern int no_quit;
+extern int semihosting_enabled;
+extern int autostart;
+extern const char *bootp_filename;
 
 #define MAX_OPTION_ROMS 16
 extern const char *option_rom[MAX_OPTION_ROMS];
 extern int nb_option_roms;
 
+#ifdef TARGET_SPARC
+#define MAX_PROM_ENVS 128
+extern const char *prom_envs[MAX_PROM_ENVS];
+extern unsigned int nb_prom_envs;
+#endif
+
 /* XXX: make it dynamic */
+#define MAX_BIOS_SIZE (4 * 1024 * 1024)
 #if defined (TARGET_PPC) || defined (TARGET_SPARC64)
 #define BIOS_SIZE ((512 + 32) * 1024)
 #elif defined(TARGET_MIPS)
-#define BIOS_SIZE (128 * 1024)
-#else
-#define BIOS_SIZE ((256 + 64) * 1024)
+#define BIOS_SIZE (4 * 1024 * 1024)
 #endif
 
 /* keyboard/mouse support */
@@ -291,33 +296,43 @@
 #define CHR_IOCTL_PP_READ_CONTROL     5
 #define CHR_IOCTL_PP_WRITE_CONTROL    6
 #define CHR_IOCTL_PP_READ_STATUS      7
+#define CHR_IOCTL_PP_EPP_READ_ADDR    8
+#define CHR_IOCTL_PP_EPP_READ         9
+#define CHR_IOCTL_PP_EPP_WRITE_ADDR  10
+#define CHR_IOCTL_PP_EPP_WRITE       11
 
-#define CHR_IOCTL_MODEM_HANDSHAKE     8
+#define CHR_IOCTL_MODEM_HANDSHAKE    12
 
 typedef void IOEventHandler(void *opaque, int event);
 
 typedef struct CharDriverState {
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
-    void (*chr_add_read_handler)(struct CharDriverState *s, 
-                                 IOCanRWHandler *fd_can_read, 
-                                 IOReadHandler *fd_read, void *opaque);
+    void (*chr_update_read_handler)(struct CharDriverState *s);
     int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
     IOEventHandler *chr_event;
+    IOCanRWHandler *chr_can_read;
+    IOReadHandler *chr_read;
+    void *handler_opaque;
     void (*chr_send_event)(struct CharDriverState *chr, int event);
     void (*chr_close)(struct CharDriverState *chr);
     void *opaque;
+    int focus;
     QEMUBH *bh;
 } CharDriverState;
 
+CharDriverState *qemu_chr_open(const char *filename);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
 int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
 void qemu_chr_send_event(CharDriverState *s, int event);
-void qemu_chr_add_read_handler(CharDriverState *s, 
-                               IOCanRWHandler *fd_can_read, 
-                               IOReadHandler *fd_read, void *opaque);
-void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
+void qemu_chr_add_handlers(CharDriverState *s, 
+                           IOCanRWHandler *fd_can_read, 
+                           IOReadHandler *fd_read,
+                           IOEventHandler *fd_event,
+                           void *opaque);
 int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg);
 void qemu_chr_reset(CharDriverState *s);
+int qemu_chr_can_read(CharDriverState *s);
+void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
 
 /* consoles */
 
@@ -352,6 +367,11 @@
 
 extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 
+struct ParallelIOArg {
+    void *buffer;
+    int count;
+};
+
 /* VLANs support */
 
 typedef struct VLANClientState VLANClientState;
@@ -689,7 +709,7 @@
                                  int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
-             const char *initrd_filename);
+             const char *initrd_filename, const char *cpu_model);
 
 typedef struct QEMUMachine {
     const char *name;
@@ -701,8 +721,17 @@
 int qemu_register_machine(QEMUMachine *m);
 
 typedef void SetIRQFunc(void *opaque, int irq_num, int level);
-typedef void IRQRequestFunc(void *opaque, int level);
 
+#if defined(TARGET_PPC)
+void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
+#endif
+
+#if defined(TARGET_MIPS)
+void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
+#endif
+
+#include "hw/irq.h"
+
 /* ISA bus */
 
 extern target_phys_addr_t isa_mem_base;
@@ -775,6 +804,9 @@
     /* ??? This is a PC-specific hack, and should be removed.  */
     int irq_index;
 
+    /* IRQ objects for the INTA-INTD pins.  */
+    qemu_irq *irq;
+
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
     int irq_state[4];
 };
@@ -788,8 +820,6 @@
                             uint32_t size, int type, 
                             PCIMapIORegionFunc *map_func);
 
-void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level);
-
 uint32_t pci_default_read_config(PCIDevice *d, 
                                  uint32_t address, int len);
 void pci_default_write_config(PCIDevice *d, 
@@ -797,12 +827,12 @@
 void pci_device_save(PCIDevice *s, QEMUFile *f);
 int pci_device_load(PCIDevice *s, QEMUFile *f);
 
-typedef void (*pci_set_irq_fn)(void *pic, int irq_num, int level);
+typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level);
 typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *pic, int devfn_min, int nirq);
+                         qemu_irq *pic, int devfn_min, int nirq);
 
-void pci_nic_init(PCIBus *bus, NICInfo *nd);
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
@@ -813,37 +843,47 @@
                         pci_map_irq_fn map_irq, const char *name);
 
 /* prep_pci.c */
-PCIBus *pci_prep_init(void);
+PCIBus *pci_prep_init(qemu_irq *pic);
 
 /* grackle_pci.c */
-PCIBus *pci_grackle_init(uint32_t base, void *pic);
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
 
 /* unin_pci.c */
-PCIBus *pci_pmac_init(void *pic);
+PCIBus *pci_pmac_init(qemu_irq *pic);
 
 /* apb_pci.c */
 PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
-                     void *pic);
+                     qemu_irq *pic);
 
-PCIBus *pci_vpb_init(void *pic, int irq, int realview);
+PCIBus *pci_vpb_init(qemu_irq *pic, int irq, int realview);
 
 /* piix_pci.c */
-PCIBus *i440fx_init(PCIDevice **pi440fx_state);
+PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic);
 void i440fx_set_smm(PCIDevice *d, int val);
-int piix3_init(PCIBus *bus);
+int piix3_init(PCIBus *bus, int devfn);
 void i440fx_init_memory_mappings(PCIDevice *d);
 
+int piix4_init(PCIBus *bus, int devfn);
+
 /* openpic.c */
-typedef struct openpic_t openpic_t;
-void openpic_set_irq(void *opaque, int n_IRQ, int level);
-openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
-                         CPUState **envp);
+/* OpenPIC have 5 outputs per CPU connected and one IRQ out single output */
+enum {
+    OPENPIC_OUTPUT_INT = 0, /* IRQ                       */
+    OPENPIC_OUTPUT_CINT,    /* critical IRQ              */
+    OPENPIC_OUTPUT_MCK,     /* Machine check event       */
+    OPENPIC_OUTPUT_DEBUG,   /* Inconditional debug event */
+    OPENPIC_OUTPUT_RESET,   /* Core reset event          */
+    OPENPIC_OUTPUT_NB,
+};
+qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
+                        qemu_irq **irqs, qemu_irq irq_out);
 
 /* heathrow_pic.c */
-typedef struct HeathrowPICS HeathrowPICS;
-void heathrow_pic_set_irq(void *opaque, int num, int level);
-HeathrowPICS *heathrow_pic_init(int *pmem_index);
+qemu_irq *heathrow_pic_init(int *pmem_index);
 
+/* gt64xxx.c */
+PCIBus *pci_gt64120_init(qemu_irq *pic);
+
 #ifdef HAS_AUDIO
 struct soundhw {
     const char *name;
@@ -851,7 +891,7 @@
     int enabled;
     int isa;
     union {
-        int (*init_isa) (AudioState *s);
+        int (*init_isa) (AudioState *s, qemu_irq *pic);
         int (*init_pci) (PCIBus *bus, AudioState *s);
     } init;
 };
@@ -861,7 +901,11 @@
 
 /* vga.c */
 
+#ifndef TARGET_SPARC
 #define VGA_RAM_SIZE (8192 * 1024)
+#else
+#define VGA_RAM_SIZE (9 * 1024 * 1024)
+#endif
 
 struct DisplayState {
     uint8_t *data;
@@ -875,7 +919,13 @@
     void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
     void (*dpy_resize)(struct DisplayState *s, int w, int h);
     void (*dpy_refresh)(struct DisplayState *s);
-    void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
+    void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y,
+                     int dst_x, int dst_y, int w, int h);
+    void (*dpy_fill)(struct DisplayState *s, int x, int y,
+                     int w, int h, uint32_t c);
+    void (*mouse_set)(int x, int y, int on);
+    void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
+                          uint8_t *image, uint8_t *mask);
 };
 
 static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
@@ -893,6 +943,10 @@
 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
                  unsigned long vga_ram_offset, int vga_ram_size,
                  unsigned long vga_bios_offset, int vga_bios_size);
+int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
+                    unsigned long vga_ram_offset, int vga_ram_size,
+                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
+                    int it_shift);
 
 /* cirrus_vga.c */
 void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
@@ -900,43 +954,57 @@
 void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
                          unsigned long vga_ram_offset, int vga_ram_size);
 
+/* vmware_vga.c */
+void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+                     unsigned long vga_ram_offset, int vga_ram_size);
+
 /* sdl.c */
-void sdl_display_init(DisplayState *ds, int full_screen);
+void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
 
 /* cocoa.m */
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
 /* vnc.c */
 void vnc_display_init(DisplayState *ds, const char *display);
+void do_info_vnc(void);
 
+/* x_keymap.c */
+extern uint8_t _translate_keycode(const int key);
+
 /* ide.c */
 #define MAX_DISKS 4
 
 extern BlockDriverState *bs_table[MAX_DISKS + 1];
+extern BlockDriverState *sd_bdrv;
+extern BlockDriverState *mtd_bdrv;
 
-void isa_ide_init(int iobase, int iobase2, int irq,
+void isa_ide_init(int iobase, int iobase2, qemu_irq irq,
                   BlockDriverState *hd0, BlockDriverState *hd1);
 void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
                          int secondary_ide_enabled);
-void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
-int pmac_ide_init (BlockDriverState **hd_table,
-                   SetIRQFunc *set_irq, void *irq_opaque, int irq);
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
+                        qemu_irq *pic);
+int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
 
 /* cdrom.c */
 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
 int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num);
 
+/* ds1225y.c */
+typedef struct ds1225y_t ds1225y_t;
+ds1225y_t *ds1225y_init(target_ulong mem_base, const char *filename);
+
 /* es1370.c */
 int es1370_init (PCIBus *bus, AudioState *s);
 
 /* sb16.c */
-int SB16_init (AudioState *s);
+int SB16_init (AudioState *s, qemu_irq *pic);
 
 /* adlib.c */
-int Adlib_init (AudioState *s);
+int Adlib_init (AudioState *s, qemu_irq *pic);
 
 /* gus.c */
-int GUS_init (AudioState *s);
+int GUS_init (AudioState *s, qemu_irq *pic);
 
 /* dma.c */
 typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size);
@@ -957,52 +1025,67 @@
 
 typedef struct fdctrl_t fdctrl_t;
 
-fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 
+fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, 
                        uint32_t io_base,
                        BlockDriverState **fds);
 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
 
+/* eepro100.c */
+
+void pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn);
+void pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn);
+void pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn);
+
 /* ne2000.c */
 
-void isa_ne2000_init(int base, int irq, NICInfo *nd);
-void pci_ne2000_init(PCIBus *bus, NICInfo *nd);
+void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
+void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* rtl8139.c */
 
-void pci_rtl8139_init(PCIBus *bus, NICInfo *nd);
+void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 /* pcnet.c */
 
-void pci_pcnet_init(PCIBus *bus, NICInfo *nd);
+void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
 void pcnet_h_reset(void *opaque);
-void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque);
+void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque, qemu_irq irq);
 
+/* vmmouse.c */
+void *vmmouse_init(void *m);
 
 /* pckbd.c */
 
-void kbd_init(void);
+void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base);
+void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, target_ulong base, int it_shift);
 
 /* mc146818rtc.c */
 
 typedef struct RTCState RTCState;
 
-RTCState *rtc_init(int base, int irq);
+RTCState *rtc_init(int base, qemu_irq irq);
+RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq);
 void rtc_set_memory(RTCState *s, int addr, int val);
 void rtc_set_date(RTCState *s, const struct tm *tm);
 
 /* serial.c */
 
 typedef struct SerialState SerialState;
-SerialState *serial_init(SetIRQFunc *set_irq, void *opaque,
-                         int base, int irq, CharDriverState *chr);
-SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque,
-                             target_ulong base, int it_shift,
-                             int irq, CharDriverState *chr);
+SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr);
+SerialState *serial_mm_init (target_ulong base, int it_shift,
+                             qemu_irq irq, CharDriverState *chr,
+                             int ioregister);
+uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr);
+void serial_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value);
+uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr);
+void serial_mm_writew (void *opaque, target_phys_addr_t addr, uint32_t value);
+uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr);
+void serial_mm_writel (void *opaque, target_phys_addr_t addr, uint32_t value);
 
 /* parallel.c */
 
 typedef struct ParallelState ParallelState;
-ParallelState *parallel_init(int base, int irq, CharDriverState *chr);
+ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr);
 
 /* i8259.c */
 
@@ -1010,7 +1093,7 @@
 extern PicState2 *isa_pic;
 void pic_set_irq(int irq, int level);
 void pic_set_irq_new(void *opaque, int irq, int level);
-PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque);
+qemu_irq *i8259_init(qemu_irq parent_irq);
 void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
                           void *alt_irq_opaque);
 int pic_read_irq(PicState2 *s);
@@ -1033,7 +1116,7 @@
 
 typedef struct PITState PITState;
 
-PITState *pit_init(int base, int irq);
+PITState *pit_init(int base, qemu_irq irq);
 void pit_set_gate(PITState *pit, int channel, int val);
 int pit_get_gate(PITState *pit, int channel);
 int pit_get_initial_count(PITState *pit, int channel);
@@ -1042,11 +1125,19 @@
 
 /* pcspk.c */
 void pcspk_init(PITState *);
-int pcspk_audio_init(AudioState *);
+int pcspk_audio_init(AudioState *, qemu_irq *pic);
 
+/* GPIO */
+typedef void (*gpio_handler_t)(int line, int level, void *opaque);
+
+#include "hw/i2c.h"
+
+#include "hw/smbus.h"
+
 /* acpi.c */
 extern int acpi_enabled;
-void piix4_pm_init(PCIBus *bus, int devfn);
+i2c_bus *piix4_pm_init(PCIBus *bus, int devfn);
+void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
 void acpi_bios_init(void);
 
 /* pc.c */
@@ -1061,10 +1152,21 @@
 extern QEMUMachine prep_machine;
 extern QEMUMachine core99_machine;
 extern QEMUMachine heathrow_machine;
+extern QEMUMachine ref405ep_machine;
+extern QEMUMachine taihu_machine;
 
 /* mips_r4k.c */
 extern QEMUMachine mips_machine;
 
+/* mips_malta.c */
+extern QEMUMachine mips_malta_machine;
+
+/* mips_int.c */
+extern void cpu_mips_irq_init_cpu(CPUState *env);
+
+/* mips_pica61.c */
+extern QEMUMachine mips_pica61_machine;
+
 /* mips_timer.c */
 extern void cpu_mips_clock_init(CPUState *);
 extern void cpu_mips_irqctrl_init (void);
@@ -1073,7 +1175,32 @@
 extern QEMUMachine shix_machine;
 
 #ifdef TARGET_PPC
-ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
+/* PowerPC hardware exceptions management helpers */
+typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
+typedef struct clk_setup_t clk_setup_t;
+struct clk_setup_t {
+    clk_setup_cb cb;
+    void *opaque;
+};
+static inline void clk_setup (clk_setup_t *clk, uint32_t freq)
+{
+    if (clk->cb != NULL)
+        (*clk->cb)(clk->opaque, freq);
+}
+
+clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq);
+/* Embedded PowerPC DCR management */
+typedef target_ulong (*dcr_read_cb)(void *opaque, int dcrn);
+typedef void (*dcr_write_cb)(void *opaque, int dcrn, target_ulong val);
+int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
+                  int (*dcr_write_error)(int dcrn));
+int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+                      dcr_read_cb drc_read, dcr_write_cb dcr_write);
+clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq);
+/* Embedded PowerPC reset */
+void ppc40x_core_reset (CPUState *env);
+void ppc40x_chip_reset (CPUState *env);
+void ppc40x_system_reset (CPUState *env);
 #endif
 void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
@@ -1082,8 +1209,7 @@
 void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 
 /* sun4m.c */
-extern QEMUMachine sun4m_machine;
-void pic_set_irq_cpu(int irq, int level, unsigned int cpu);
+extern QEMUMachine ss5_machine, ss10_machine;
 
 /* iommu.c */
 void *iommu_init(uint32_t addr);
@@ -1105,31 +1231,37 @@
 
 /* tcx.c */
 void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
-	       unsigned long vram_offset, int vram_size, int width, int height);
+	      unsigned long vram_offset, int vram_size, int width, int height,
+              int depth);
 
 /* slavio_intctl.c */
-void *slavio_intctl_init();
+void pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu);
+void *slavio_intctl_init(uint32_t addr, uint32_t addrg,
+                         const uint32_t *intbit_to_level,
+                         qemu_irq **irq);
 void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env);
 void slavio_pic_info(void *opaque);
 void slavio_irq_info(void *opaque);
-void slavio_pic_set_irq(void *opaque, int irq, int level);
-void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu);
 
 /* loader.c */
 int get_image_size(const char *filename);
 int load_image(const char *filename, uint8_t *addr);
-int load_elf(const char *filename, int64_t virt_to_phys_addend, uint64_t *pentry);
+int load_elf(const char *filename, int64_t virt_to_phys_addend,
+             uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr);
 int load_aout(const char *filename, uint8_t *addr);
+int load_uboot(const char *filename, target_ulong *ep, int *is_linux);
 
 /* slavio_timer.c */
-void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu);
+void slavio_timer_init(uint32_t addr, int irq, int mode, unsigned int cpu,
+                       void *intctl);
 
 /* slavio_serial.c */
-SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
-void slavio_serial_ms_kbd_init(int base, int irq);
+SerialState *slavio_serial_init(int base, qemu_irq irq, CharDriverState *chr1,
+                                CharDriverState *chr2);
+void slavio_serial_ms_kbd_init(int base, qemu_irq);
 
 /* slavio_misc.c */
-void *slavio_misc_init(uint32_t base, int irq);
+void *slavio_misc_init(uint32_t base, qemu_irq irq);
 void slavio_set_power_fail(void *opaque, int power_failing);
 
 /* esp.c */
@@ -1138,8 +1270,8 @@
 void esp_reset(void *opaque);
 
 /* sparc32_dma.c */
-void *sparc32_dma_init(uint32_t daddr, int espirq, int leirq, void *iommu,
-                       void *intctl);
+void *sparc32_dma_init(uint32_t daddr, qemu_irq espirq, qemu_irq leirq,
+                       void *iommu);
 void ledma_set_irq(void *opaque, int isr);
 void ledma_memory_read(void *opaque, target_phys_addr_t addr, 
                        uint8_t *buf, int len, int do_bswap);
@@ -1223,7 +1355,7 @@
 /* cuda.c */
 
 extern ADBBusState adb_bus;
-int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq);
+int cuda_init(qemu_irq irq);
 
 #include "hw/usb.h"
 
@@ -1271,8 +1403,7 @@
 void *lsi_scsi_init(PCIBus *bus, int devfn);
 
 /* integratorcp.c */
-extern QEMUMachine integratorcp926_machine;
-extern QEMUMachine integratorcp1026_machine;
+extern QEMUMachine integratorcp_machine;
 
 /* versatilepb.c */
 extern QEMUMachine versatilepb_machine;
@@ -1282,10 +1413,10 @@
 extern QEMUMachine realview_machine;
 
 /* spitz.c */
-extern QEMUMachine zaurusakita_machine;
-extern QEMUMachine zaurusspitz_machine;
-extern QEMUMachine zaurusborzoi_machine;
-extern QEMUMachine zaurusterrier_machine;
+extern QEMUMachine akitapda_machine;
+extern QEMUMachine spitzpda_machine;
+extern QEMUMachine borzoipda_machine;
+extern QEMUMachine terrierpda_machine;
 
 /* neo1973.c */
 extern QEMUMachine neo1973_machine;
@@ -1298,38 +1429,43 @@
 uint32_t ps2_read_data(void *);
 void ps2_queue(void *, int b);
 void ps2_keyboard_set_translation(void *opaque, int mode);
+void ps2_mouse_fake_event(void *opaque);
 
 /* smc91c111.c */
-void smc91c111_init(NICInfo *, uint32_t, void *, int);
+void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
 
 /* pl110.c */
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq, int);
+void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq, int);
 
 /* pl011.c */
-void pl011_init(uint32_t base, void *pic, int irq, CharDriverState *chr);
+void pl011_init(uint32_t base, qemu_irq irq, CharDriverState *chr);
 
 /* pl050.c */
-void pl050_init(uint32_t base, void *pic, int irq, int is_mouse);
+void pl050_init(uint32_t base, qemu_irq irq, int is_mouse);
 
 /* pl080.c */
-void *pl080_init(uint32_t base, void *pic, int irq, int nchannels);
+void *pl080_init(uint32_t base, qemu_irq irq, int nchannels);
 
+/* pl181.c */
+void pl181_init(uint32_t base, BlockDriverState *bd,
+                qemu_irq irq0, qemu_irq irq1);
+
 /* pl190.c */
-void *pl190_init(uint32_t base, void *parent, int irq, int fiq);
+qemu_irq *pl190_init(uint32_t base, qemu_irq irq, qemu_irq fiq);
 
 /* arm-timer.c */
-void sp804_init(uint32_t base, void *pic, int irq);
-void icp_pit_init(uint32_t base, void *pic, int irq);
+void sp804_init(uint32_t base, qemu_irq irq);
+void icp_pit_init(uint32_t base, qemu_irq *pic, int irq);
 
 /* arm_sysctl.c */
 void arm_sysctl_init(uint32_t base, uint32_t sys_id);
 
 /* arm_gic.c */
-void *arm_gic_init(uint32_t base, void *parent, int parent_irq);
+qemu_irq *arm_gic_init(uint32_t base, qemu_irq parent_irq);
 
 /* arm_boot.c */
 
-void arm_load_kernel(int ram_size, const char *kernel_filename,
+void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
                      const char *kernel_cmdline, const char *initrd_filename,
                      int board_id, target_phys_addr_t loader_start);
 
@@ -1356,6 +1492,8 @@
 int tc58128_init(struct SH7750State *s, char *zone1, char *zone2);
 
 /* NOR flash devices */
+#define MAX_PFLASH 4
+extern BlockDriverState *pflash_table[MAX_PFLASH];
 typedef struct pflash_t pflash_t;
 
 pflash_t *pflash_register (target_ulong base, ram_addr_t off,
@@ -1385,31 +1523,33 @@
 
 #include "ecc.h"
 
+/* ads7846.c */
+struct ads7846_state_s;
+uint32_t ads7846_read(void *opaque);
+void ads7846_write(void *opaque, uint32_t value);
+struct ads7846_state_s *ads7846_init(qemu_irq penirq);
+
 /* max111x.c */
 struct max111x_s;
 uint32_t max111x_read(void *opaque);
 void max111x_write(void *opaque, uint32_t value);
-struct max111x_s *max1110_init(void (*cb)(void *opaque), void *opaque);
-struct max111x_s *max1111_init(void (*cb)(void *opaque), void *opaque);
+struct max111x_s *max1110_init(qemu_irq cb);
+struct max111x_s *max1111_init(qemu_irq cb);
 void max111x_set_input(struct max111x_s *s, int line, uint8_t value);
 
-/* ads7846.c */
-struct ads7846_state_s;
-uint32_t ads7846_read(void *opaque);
-void ads7846_write(void *opaque, uint32_t value);
-struct ads7846_state_s *ads7846_init(
-                void (*penirq)(void *opaque, int level), void *opaque);
-
 /* jbt6k74.c */
 uint8_t jbt6k74_txrx(void *opaque, uint8_t value);
 uint8_t jbt6k74_btxrx(void *opaque, uint8_t value);
 void *jbt6k74_init();
 
+/* modem.c */
+CharDriverState *modem_init();
+void modem_enable(CharDriverState *chr, int enable);
+
 /* PCMCIA/Cardbus */
 
 struct pcmcia_socket_s {
-    void (*set_irq)(void *opaque, int irq, int level);
-    void *opaque;
+    qemu_irq irq;
     int attached;
     const char *slot_string;
     const char *card_string;
@@ -1428,12 +1568,12 @@
     int cis_len;
 
     /* Only valid if attached */
-    uint8_t (*attr_read)(void *state, uint16_t address);
-    void (*attr_write)(void *state, uint16_t address, uint8_t value);
-    uint16_t (*common_read)(void *state, uint16_t address);
-    void (*common_write)(void *state, uint16_t address, uint16_t value);
-    uint16_t (*io_read)(void *state, uint16_t address);
-    void (*io_write)(void *state, uint16_t address, uint16_t value);
+    uint8_t (*attr_read)(void *state, uint32_t address);
+    void (*attr_write)(void *state, uint32_t address, uint8_t value);
+    uint16_t (*common_read)(void *state, uint32_t address);
+    void (*common_write)(void *state, uint32_t address, uint16_t value);
+    uint16_t (*io_read)(void *state, uint32_t address);
+    void (*io_write)(void *state, uint32_t address, uint16_t value);
 };
 
 #define CISTPL_DEVICE		0x01	/* 5V Device Information Tuple */
@@ -1456,20 +1596,12 @@
 /* dscm1xxxx.c */
 struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv);
 
-typedef void (*gpio_handler_t)(int line, int level, void *opaque);
-
-#include "hw/i2c.h"
-
 #define unlikely(cond)	__builtin_expect(!!(cond), 0)
 
-#ifdef TARGET_ARM
 #include "hw/pxa.h"
 #include "hw/s3c.h"
-#endif
 
-/* modem.c */
-CharDriverState *modem_init();
-void modem_enable(CharDriverState *chr, int enable);
+#include "gdbstub.h"
 
 #endif /* defined(QEMU_TOOL) */
 

Modified: trunk/src/host/qemu-neo1973/vnc.c
===================================================================
--- trunk/src/host/qemu-neo1973/vnc.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/vnc.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -68,6 +68,13 @@
     int depth; /* internal VNC frame buffer byte per pixel */
     int has_resize;
     int has_hextile;
+    int has_pointer_type_change;
+    int absolute;
+    int last_x;
+    int last_y;
+
+    const char *display;
+
     Buffer output;
     Buffer input;
     kbd_layout_t *kbd_layout;
@@ -85,6 +92,24 @@
     uint8_t modifiers_state[256];
 };
 
+static VncState *vnc_state; /* needed for info vnc */
+
+void do_info_vnc(void)
+{
+    if (vnc_state == NULL)
+	term_printf("VNC server disabled\n");
+    else {
+	term_printf("VNC server active on: ");
+	term_print_filename(vnc_state->display);
+	term_printf("\n");
+
+	if (vnc_state->csock == -1)
+	    term_printf("No client connected\n");
+	else
+	    term_printf("Client connected\n");
+    }
+}
+
 /* TODO
    1) Get the queue working for IO.
    2) there is some weirdness when using the -S option (the screen is grey
@@ -671,6 +696,19 @@
 {
 }
 
+static void check_pointer_type_change(VncState *vs, int absolute)
+{
+    if (vs->has_pointer_type_change && vs->absolute != absolute) {
+	vnc_write_u8(vs, 0);
+	vnc_write_u8(vs, 0);
+	vnc_write_u16(vs, 1);
+	vnc_framebuffer_update(vs, absolute, 0,
+			       vs->ds->width, vs->ds->height, -257);
+	vnc_flush(vs);
+    }
+    vs->absolute = absolute;
+}
+
 static void pointer_event(VncState *vs, int button_mask, int x, int y)
 {
     int buttons = 0;
@@ -686,21 +724,26 @@
 	dz = -1;
     if (button_mask & 0x10)
 	dz = 1;
-	    
-    if (kbd_mouse_is_absolute()) {
+
+    if (vs->absolute) {
 	kbd_mouse_event(x * 0x7FFF / vs->ds->width,
 			y * 0x7FFF / vs->ds->height,
 			dz, buttons);
+    } else if (vs->has_pointer_type_change) {
+	x -= 0x7FFF;
+	y -= 0x7FFF;
+
+	kbd_mouse_event(x, y, dz, buttons);
     } else {
-	static int last_x = -1;
-	static int last_y = -1;
+	if (vs->last_x != -1)
+	    kbd_mouse_event(x - vs->last_x,
+			    y - vs->last_y,
+			    dz, buttons);
+	vs->last_x = x;
+	vs->last_y = y;
+    }
 
-	if (last_x != -1)
-	    kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
-
-	last_x = x;
-	last_y = y;
-    }
+    check_pointer_type_change(vs, kbd_mouse_is_absolute());
 }
 
 static void reset_keys(VncState *vs)
@@ -809,6 +852,15 @@
 				       int x_position, int y_position,
 				       int w, int h)
 {
+    if (x_position > vs->ds->width)
+        x_position = vs->ds->width;
+    if (y_position > vs->ds->height)
+        y_position = vs->ds->height;
+    if (x_position + w >= vs->ds->width)
+        w = vs->ds->width  - x_position;
+    if (y_position + h >= vs->ds->height)
+        h = vs->ds->height - y_position;
+
     int i;
     vs->need_update = 1;
     if (!incremental) {
@@ -829,6 +881,8 @@
 
     vs->has_hextile = 0;
     vs->has_resize = 0;
+    vs->has_pointer_type_change = 0;
+    vs->absolute = -1;
     vs->ds->dpy_copy = NULL;
 
     for (i = n_encodings - 1; i >= 0; i--) {
@@ -845,10 +899,15 @@
 	case -223: /* DesktopResize */
 	    vs->has_resize = 1;
 	    break;
+	case -257:
+	    vs->has_pointer_type_change = 1;
+	    break;
 	default:
 	    break;
 	}
     }
+
+    check_pointer_type_change(vs, kbd_mouse_is_absolute());
 }
 
 static int compute_nbits(unsigned int val)
@@ -1006,6 +1065,8 @@
 static int protocol_client_init(VncState *vs, char *data, size_t len)
 {
     char pad[3] = { 0, 0, 0 };
+    char buf[1024];
+    int size;
 
     vs->width = vs->ds->width;
     vs->height = vs->ds->height;
@@ -1050,8 +1111,13 @@
 	
     vnc_write(vs, pad, 3);           /* padding */
 
-    vnc_write_u32(vs, 4);        
-    vnc_write(vs, "QEMU", 4);
+    if (qemu_name)
+        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
+    else
+        size = snprintf(buf, sizeof(buf), "QEMU");
+
+    vnc_write_u32(vs, size);
+    vnc_write(vs, buf, size);
     vnc_flush(vs);
 
     vnc_read_when(vs, protocol_client_msg, 1);
@@ -1120,10 +1186,14 @@
 	exit(1);
 
     ds->opaque = vs;
+    vnc_state = vs;
+    vs->display = arg;
 
     vs->lsock = -1;
     vs->csock = -1;
     vs->depth = 4;
+    vs->last_x = -1;
+    vs->last_y = -1;
 
     vs->ds = ds;
 

Added: trunk/src/host/qemu-neo1973/x_keymap.c
===================================================================
--- trunk/src/host/qemu-neo1973/x_keymap.c	2007-05-11 08:16:15 UTC (rev 1947)
+++ trunk/src/host/qemu-neo1973/x_keymap.c	2007-05-11 23:44:50 UTC (rev 1948)
@@ -0,0 +1,110 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+static const uint8_t x_keycode_to_pc_keycode[115] = {
+   0xc7,      /*  97  Home   */
+   0xc8,      /*  98  Up     */
+   0xc9,      /*  99  PgUp   */
+   0xcb,      /* 100  Left   */
+   0x4c,        /* 101  KP-5   */
+   0xcd,      /* 102  Right  */
+   0xcf,      /* 103  End    */
+   0xd0,      /* 104  Down   */
+   0xd1,      /* 105  PgDn   */
+   0xd2,      /* 106  Ins    */
+   0xd3,      /* 107  Del    */
+   0x9c,      /* 108  Enter  */
+   0x9d,      /* 109  Ctrl-R */
+   0x0,       /* 110  Pause  */
+   0xb7,      /* 111  Print  */
+   0xb5,      /* 112  Divide */
+   0xb8,      /* 113  Alt-R  */
+   0xc6,      /* 114  Break  */
+   0x0,         /* 115 */
+   0x0,         /* 116 */
+   0x0,         /* 117 */
+   0x0,         /* 118 */
+   0x0,         /* 119 */
+   0x0,         /* 120 */
+   0x0,         /* 121 */
+   0x0,         /* 122 */
+   0x0,         /* 123 */
+   0x0,         /* 124 */
+   0x0,         /* 125 */
+   0x0,         /* 126 */
+   0x0,         /* 127 */
+   0x0,         /* 128 */
+   0x79,         /* 129 Henkan */
+   0x0,         /* 130 */
+   0x7b,         /* 131 Muhenkan */
+   0x0,         /* 132 */
+   0x7d,         /* 133 Yen */
+   0x0,         /* 134 */
+   0x0,         /* 135 */
+   0x47,         /* 136 KP_7 */
+   0x48,         /* 137 KP_8 */
+   0x49,         /* 138 KP_9 */
+   0x4b,         /* 139 KP_4 */
+   0x4c,         /* 140 KP_5 */
+   0x4d,         /* 141 KP_6 */
+   0x4f,         /* 142 KP_1 */
+   0x50,         /* 143 KP_2 */
+   0x51,         /* 144 KP_3 */
+   0x52,         /* 145 KP_0 */
+   0x53,         /* 146 KP_. */
+   0x47,         /* 147 KP_HOME */
+   0x48,         /* 148 KP_UP */
+   0x49,         /* 149 KP_PgUp */
+   0x4b,         /* 150 KP_Left */
+   0x4c,         /* 151 KP_ */
+   0x4d,         /* 152 KP_Right */
+   0x4f,         /* 153 KP_End */
+   0x50,         /* 154 KP_Down */
+   0x51,         /* 155 KP_PgDn */
+   0x52,         /* 156 KP_Ins */
+   0x53,         /* 157 KP_Del */
+   0x0,         /* 158 */
+   0x0,         /* 159 */
+   0x0,         /* 160 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 170 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 180 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 190 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 200 */
+   0x0,         /* 201 */
+   0x0,         /* 202 */
+   0x0,         /* 203 */
+   0x0,         /* 204 */
+   0x0,         /* 205 */
+   0x0,         /* 206 */
+   0x0,         /* 207 */
+   0x70,         /* 208 Hiragana_Katakana */
+   0x0,         /* 209 */
+   0x0,         /* 210 */
+   0x73,         /* 211 backslash */
+};
+
+uint8_t _translate_keycode(const int key)
+{
+	return x_keycode_to_pc_keycode[key];
+}





More information about the commitlog mailing list